@lingual/i18n-check 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -18
- package/dist/bin/index.js +61 -57
- package/dist/bin/index.test.js +321 -289
- package/dist/errorReporters.d.ts +1 -1
- package/dist/errorReporters.js +21 -21
- package/dist/errorReporters.test.js +39 -39
- package/dist/index.d.ts +4 -3
- package/dist/index.js +82 -47
- package/dist/utils/findInvalidTranslations.d.ts +2 -2
- package/dist/utils/findInvalidTranslations.js +20 -19
- package/dist/utils/findInvalidTranslations.test.js +30 -30
- package/dist/utils/findInvalidi18nTranslations.d.ts +2 -2
- package/dist/utils/findInvalidi18nTranslations.js +35 -35
- package/dist/utils/findInvalidi18nTranslations.test.js +72 -72
- package/dist/utils/findMissingKeys.d.ts +1 -1
- package/dist/utils/findMissingKeys.js +2 -2
- package/dist/utils/findMissingKeys.test.js +20 -20
- package/dist/utils/flattenTranslations.d.ts +1 -1
- package/dist/utils/flattenTranslations.js +3 -3
- package/dist/utils/flattenTranslations.test.js +13 -13
- package/dist/utils/i18NextParser.d.ts +6 -6
- package/dist/utils/i18NextParser.js +29 -29
- package/dist/utils/i18NextParser.test.js +104 -104
- package/dist/utils/nextIntlSrcParser.js +11 -11
- package/dist/utils/nextIntlSrcParser.test.js +156 -156
- package/package.json +14 -4
package/README.md
CHANGED
|
@@ -223,6 +223,28 @@ yarn i18n:check --locales translations/folderExamples -s en-US -e translations/f
|
|
|
223
223
|
The `--exclude` option also accepts a mix of files and folders, which follows the same pattern as above, i.e.
|
|
224
224
|
`-e translations/folderExamples/fr/* translations/messageExamples/it.json`
|
|
225
225
|
|
|
226
|
+
### --ignore, -i
|
|
227
|
+
|
|
228
|
+
There can be situations where we only want to translate a feature for a specific region and therefore need to ignore any missing key checks against non supported locales. Another scenario is that we know of the missing keys and want to be able to skip these missing keys when running checks. For these aforementioned scenarios, by using the `--ignore` or `-i` option you can specify which keys to ignore, additionally also being able to define ignoring all keys inside a defined path, i.e. `some.keys.path.*`.
|
|
229
|
+
|
|
230
|
+
To ignore regular keys:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
yarn i18n:check --locales translations/folderExamples -s en-US -i some.key.to.ignore other.key.to.ignore
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
To ignore all keys within a provided path:
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
yarn i18n:check --locales translations/folderExamples -s en-US -i "some.path.to.keys.*"
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
A mix of regular keys and paths:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
yarn i18n:check --locales translations/folderExamples -s en-US -i "some.path.to.keys.*" some.key.to.ignore other.key.to.ignore
|
|
246
|
+
```
|
|
247
|
+
|
|
226
248
|
### --parser-component-functions
|
|
227
249
|
|
|
228
250
|
When using the `--unused` option, there will be situations where the i18next-parser will not be able to find components that wrap a `Trans` component.The component names for i18next-parser to match should be provided via the `--parser-component-functions` option. This option should onlybe used to define additional names for matching, a by default `Trans` will always be matched.
|
|
@@ -371,7 +393,7 @@ Aside from using the CLI, i18n-check also exposes a set of check functions that
|
|
|
371
393
|
Start by importing i18n-check:
|
|
372
394
|
|
|
373
395
|
```ts
|
|
374
|
-
import * as i18nCheck from
|
|
396
|
+
import * as i18nCheck from '@lingual/i18n-check';
|
|
375
397
|
```
|
|
376
398
|
|
|
377
399
|
### `i18nCheck.checkTranslations(source, targets [, options])`
|
|
@@ -379,10 +401,10 @@ import * as i18nCheck from "@lingual/i18n-check";
|
|
|
379
401
|
`checkTranslations` expects the base and comparison or target files and returns an object containing the missing and invalid keys. The optional `options` objects can be provided as a third argument to define the format style via the `format` property, this is useful if you want to validate `i18next` specific translations.
|
|
380
402
|
|
|
381
403
|
```ts
|
|
382
|
-
import { checkTranslations } from
|
|
404
|
+
import { checkTranslations } from '@lingual/i18n-check';
|
|
383
405
|
|
|
384
406
|
const options = {
|
|
385
|
-
format:
|
|
407
|
+
format: 'i18next',
|
|
386
408
|
};
|
|
387
409
|
|
|
388
410
|
const { invalidKeys, missingKeys } = checkTranslations(
|
|
@@ -395,11 +417,11 @@ const { invalidKeys, missingKeys } = checkTranslations(
|
|
|
395
417
|
Additionally the `options` object enables to also define which checks should run via the `checks` property, f.e. if you only want to check for missing or invalid keys only.
|
|
396
418
|
|
|
397
419
|
```ts
|
|
398
|
-
import { checkTranslations } from
|
|
420
|
+
import { checkTranslations } from '@lingual/i18n-check';
|
|
399
421
|
|
|
400
422
|
const options = {
|
|
401
|
-
format:
|
|
402
|
-
checks: [
|
|
423
|
+
format: 'icu',
|
|
424
|
+
checks: ['invalidKeys'],
|
|
403
425
|
};
|
|
404
426
|
|
|
405
427
|
const { invalidKeys } = checkTranslations(source, targets, options);
|
|
@@ -433,7 +455,7 @@ The result for `missingKeys` as well as `invalidKeys` is an object containing th
|
|
|
433
455
|
`checkMissingTranslations` checks for any missing keys in the target files. All files are compared against the source file.
|
|
434
456
|
|
|
435
457
|
```ts
|
|
436
|
-
import { checkMissingTranslations } from
|
|
458
|
+
import { checkMissingTranslations } from '@lingual/i18n-check';
|
|
437
459
|
|
|
438
460
|
const result = checkMissingTranslations(source, targets);
|
|
439
461
|
|
|
@@ -450,10 +472,10 @@ The result is an object containing the provided locales and their corresponding
|
|
|
450
472
|
`checkInvalidTranslations` checks if there are any invalid keys in the target files. All files are compared against the source file.
|
|
451
473
|
|
|
452
474
|
```ts
|
|
453
|
-
import { checkInvalidTranslations } from
|
|
475
|
+
import { checkInvalidTranslations } from '@lingual/i18n-check';
|
|
454
476
|
|
|
455
477
|
const options = {
|
|
456
|
-
format:
|
|
478
|
+
format: 'i18next',
|
|
457
479
|
};
|
|
458
480
|
|
|
459
481
|
const result = checkInvalidTranslations(source, targets, options);
|
|
@@ -470,7 +492,7 @@ The result is an object containing the provided locales and their corresponding
|
|
|
470
492
|
|
|
471
493
|
If you want to checkout and run the code, you need to run the `build` command first.
|
|
472
494
|
|
|
473
|
-
Run `
|
|
495
|
+
Run `pnpm run build` and then depending on the scenario one of the following commands.
|
|
474
496
|
|
|
475
497
|
Basic icu translation example:
|
|
476
498
|
|
|
@@ -516,14 +538,6 @@ To run the tests use one of the following commands:
|
|
|
516
538
|
pnpm test
|
|
517
539
|
```
|
|
518
540
|
|
|
519
|
-
```bash
|
|
520
|
-
yarn test
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
```bash
|
|
524
|
-
npm test
|
|
525
|
-
```
|
|
526
|
-
|
|
527
541
|
## Links
|
|
528
542
|
|
|
529
543
|
- [Introducing i18n-check](https://lingual.dev/blog/introducing-i18n-check/)
|
package/dist/bin/index.js
CHANGED
|
@@ -14,23 +14,24 @@ const __1 = require("..");
|
|
|
14
14
|
const errorReporters_1 = require("../errorReporters");
|
|
15
15
|
const flattenTranslations_1 = require("../utils/flattenTranslations");
|
|
16
16
|
const node_path_1 = __importDefault(require("node:path"));
|
|
17
|
-
const version = require(
|
|
17
|
+
const version = require('../../package.json').version;
|
|
18
18
|
commander_1.program
|
|
19
19
|
.version(version)
|
|
20
|
-
.option(
|
|
21
|
-
.option(
|
|
22
|
-
.option(
|
|
23
|
-
.option(
|
|
24
|
-
.option(
|
|
25
|
-
.option(
|
|
26
|
-
.option(
|
|
27
|
-
.option(
|
|
28
|
-
.option(
|
|
20
|
+
.option('-l, --locales <locales...>', 'name of the directory containing the locales to validate')
|
|
21
|
+
.option('-s, --source <locale>', 'the source locale to validate against')
|
|
22
|
+
.option('-f, --format <type>', 'define the specific format: i18next, react-intl or next-intl')
|
|
23
|
+
.option('-c, --check <checks...>', 'this option is deprecated - use -o or --only instead')
|
|
24
|
+
.option('-o, --only <only...>', 'define the specific checks you want to run: invalidKeys, missingKeys, unused, undefined. By default the check will validate against missing and invalid keys, i.e. --only invalidKeys,missingKeys')
|
|
25
|
+
.option('-r, --reporter <style>', 'define the reporting style: standard or summary')
|
|
26
|
+
.option('-e, --exclude <exclude...>', 'define the file(s) and/or folders(s) that should be excluded from the check')
|
|
27
|
+
.option('-i, --ignore <ignore...>', 'define the key(s) or group of keys (i.e. `some.namespace.*`) that should be excluded from the check')
|
|
28
|
+
.option('-u, --unused <paths...>', 'define the source path(s) to find all unused and undefined keys')
|
|
29
|
+
.option('--parser-component-functions <components...>', 'a list of component names to parse when using the --unused option')
|
|
29
30
|
.parse();
|
|
30
31
|
const getCheckOptions = () => {
|
|
31
|
-
const checkOption = commander_1.program.getOptionValue(
|
|
32
|
-
if (commander_1.program.getOptionValue(
|
|
33
|
-
console.log(chalk_1.default.yellow(
|
|
32
|
+
const checkOption = commander_1.program.getOptionValue('only') || commander_1.program.getOptionValue('check');
|
|
33
|
+
if (commander_1.program.getOptionValue('check')) {
|
|
34
|
+
console.log(chalk_1.default.yellow('The --check option has been deprecated, use the --only option instead.'));
|
|
34
35
|
}
|
|
35
36
|
if (!checkOption) {
|
|
36
37
|
return errorReporters_1.CheckOptions;
|
|
@@ -43,33 +44,34 @@ const isSource = (fileInfo, srcPath) => {
|
|
|
43
44
|
};
|
|
44
45
|
const main = async () => {
|
|
45
46
|
const start = performance.now();
|
|
46
|
-
const srcPath = commander_1.program.getOptionValue(
|
|
47
|
-
const localePath = commander_1.program.getOptionValue(
|
|
48
|
-
const format = commander_1.program.getOptionValue(
|
|
49
|
-
const exclude = commander_1.program.getOptionValue(
|
|
50
|
-
const
|
|
51
|
-
const
|
|
47
|
+
const srcPath = commander_1.program.getOptionValue('source');
|
|
48
|
+
const localePath = commander_1.program.getOptionValue('locales');
|
|
49
|
+
const format = commander_1.program.getOptionValue('format');
|
|
50
|
+
const exclude = commander_1.program.getOptionValue('exclude');
|
|
51
|
+
const ignore = commander_1.program.getOptionValue('ignore');
|
|
52
|
+
const unusedSrcPath = commander_1.program.getOptionValue('unused');
|
|
53
|
+
const componentFunctions = commander_1.program.getOptionValue('parserComponentFunctions');
|
|
52
54
|
if (!srcPath) {
|
|
53
|
-
console.log(chalk_1.default.red(
|
|
55
|
+
console.log(chalk_1.default.red('Source not found. Please provide a valid source locale, i.e. -s en-US'));
|
|
54
56
|
(0, node_process_1.exit)(1);
|
|
55
57
|
}
|
|
56
58
|
if (!localePath || localePath.length === 0) {
|
|
57
|
-
console.log(chalk_1.default.red(
|
|
59
|
+
console.log(chalk_1.default.red('Locale file(s) not found. Please provide valid locale file(s), i.e. -locales translations/'));
|
|
58
60
|
(0, node_process_1.exit)(1);
|
|
59
61
|
}
|
|
60
62
|
const excludedPaths = exclude ?? [];
|
|
61
63
|
const localePathFolders = localePath;
|
|
62
64
|
const isMultiFolders = localePathFolders.length > 1;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
const srcFiles = [];
|
|
66
|
+
const targetFiles = [];
|
|
65
67
|
const pattern = isMultiFolders
|
|
66
|
-
? `{${localePath.join(
|
|
67
|
-
: `${localePath.join(
|
|
68
|
+
? `{${localePath.join(',').trim()}}/**/*.{json,yaml,yml}`
|
|
69
|
+
: `${localePath.join(',').trim()}/**/*.{json,yaml,yml}`;
|
|
68
70
|
const files = await (0, glob_1.glob)(pattern, {
|
|
69
|
-
ignore: [
|
|
71
|
+
ignore: ['node_modules/**'].concat(excludedPaths),
|
|
70
72
|
windowsPathsNoEscape: true,
|
|
71
73
|
});
|
|
72
|
-
console.log(
|
|
74
|
+
console.log('i18n translations checker');
|
|
73
75
|
console.log(chalk_1.default.gray(`Source: ${srcPath}`));
|
|
74
76
|
if (format) {
|
|
75
77
|
console.log(chalk_1.default.blackBright(`Selected format is: ${format}`));
|
|
@@ -77,12 +79,13 @@ const main = async () => {
|
|
|
77
79
|
const options = {
|
|
78
80
|
checks: getCheckOptions(),
|
|
79
81
|
format: format ?? undefined,
|
|
82
|
+
ignore,
|
|
80
83
|
};
|
|
81
84
|
const fileInfos = [];
|
|
82
85
|
files.sort().forEach((file) => {
|
|
83
86
|
const filePath = file.split(node_path_1.default.sep);
|
|
84
|
-
const name = filePath.pop() ??
|
|
85
|
-
const extension = name.split(
|
|
87
|
+
const name = filePath.pop() ?? '';
|
|
88
|
+
const extension = name.split('.').pop() ?? 'json';
|
|
86
89
|
fileInfos.push({
|
|
87
90
|
extension,
|
|
88
91
|
file,
|
|
@@ -92,11 +95,11 @@ const main = async () => {
|
|
|
92
95
|
});
|
|
93
96
|
fileInfos.forEach(({ extension, file, name, path }) => {
|
|
94
97
|
let rawContent;
|
|
95
|
-
if (extension ===
|
|
96
|
-
rawContent = js_yaml_1.default.load(node_fs_1.default.readFileSync(file,
|
|
98
|
+
if (extension === 'yaml') {
|
|
99
|
+
rawContent = js_yaml_1.default.load(node_fs_1.default.readFileSync(file, 'utf-8'));
|
|
97
100
|
}
|
|
98
101
|
else {
|
|
99
|
-
rawContent = JSON.parse(node_fs_1.default.readFileSync(file,
|
|
102
|
+
rawContent = JSON.parse(node_fs_1.default.readFileSync(file, 'utf-8'));
|
|
100
103
|
}
|
|
101
104
|
const content = (0, flattenTranslations_1.flattenTranslations)(rawContent);
|
|
102
105
|
if (isSource({ file, name, path }, srcPath)) {
|
|
@@ -107,12 +110,12 @@ const main = async () => {
|
|
|
107
110
|
});
|
|
108
111
|
}
|
|
109
112
|
else {
|
|
110
|
-
const fullPath = path.join(
|
|
113
|
+
const fullPath = path.join('-');
|
|
111
114
|
const reference = fileInfos.find((fileInfo) => {
|
|
112
115
|
if (!isSource(fileInfo, srcPath)) {
|
|
113
116
|
return false;
|
|
114
117
|
}
|
|
115
|
-
if (fileInfo.path.join(
|
|
118
|
+
if (fileInfo.path.join('-') === fullPath) {
|
|
116
119
|
return true;
|
|
117
120
|
}
|
|
118
121
|
// Check if the folder path matches - ignoring the last folder
|
|
@@ -130,8 +133,8 @@ const main = async () => {
|
|
|
130
133
|
//
|
|
131
134
|
// Referencing: `path/to/locales/en-US/one.json`, `path/to/locales/de-DE/one.json`
|
|
132
135
|
// Non Referencing: `path/to/locales/en-US/one.json`, `path/to/other/locales/de-DE/one.json`
|
|
133
|
-
if (fileInfo.path.slice(0, fileInfo.path.length - 1).join(
|
|
134
|
-
path.slice(0, path.length - 1).join(
|
|
136
|
+
if (fileInfo.path.slice(0, fileInfo.path.length - 1).join('-') ===
|
|
137
|
+
path.slice(0, path.length - 1).join('-')) {
|
|
135
138
|
return fileInfo.name === name;
|
|
136
139
|
}
|
|
137
140
|
return false;
|
|
@@ -146,13 +149,13 @@ const main = async () => {
|
|
|
146
149
|
}
|
|
147
150
|
});
|
|
148
151
|
if (srcFiles.length === 0) {
|
|
149
|
-
console.log(chalk_1.default.red(
|
|
152
|
+
console.log(chalk_1.default.red('Source not found. Please provide a valid source locale, i.e. -s en-US'));
|
|
150
153
|
(0, node_process_1.exit)(1);
|
|
151
154
|
}
|
|
152
|
-
if ((options.checks.includes(
|
|
153
|
-
options.checks.includes(
|
|
155
|
+
if ((options.checks.includes('missingKeys') ||
|
|
156
|
+
options.checks.includes('invalidKeys')) &&
|
|
154
157
|
targetFiles.length === 0) {
|
|
155
|
-
console.log(chalk_1.default.red(
|
|
158
|
+
console.log(chalk_1.default.red('Locale file(s) not found. Please provide valid locale file(s), i.e. --locales translations/'));
|
|
156
159
|
(0, node_process_1.exit)(1);
|
|
157
160
|
}
|
|
158
161
|
try {
|
|
@@ -161,10 +164,10 @@ const main = async () => {
|
|
|
161
164
|
if (unusedSrcPath) {
|
|
162
165
|
const isMultiUnusedFolders = unusedSrcPath.length > 1;
|
|
163
166
|
const pattern = isMultiUnusedFolders
|
|
164
|
-
? `{${unusedSrcPath.join(
|
|
165
|
-
: `${unusedSrcPath.join(
|
|
167
|
+
? `{${unusedSrcPath.join(',').trim()}}/**/*.{ts,tsx}`
|
|
168
|
+
: `${unusedSrcPath.join(',').trim()}/**/*.{ts,tsx}`;
|
|
166
169
|
const filesToParse = (0, glob_1.globSync)(pattern, {
|
|
167
|
-
ignore: [
|
|
170
|
+
ignore: ['node_modules/**'],
|
|
168
171
|
windowsPathsNoEscape: true,
|
|
169
172
|
});
|
|
170
173
|
const unusedKeys = await (0, __1.checkUnusedKeys)(srcFiles, filesToParse, options, componentFunctions);
|
|
@@ -183,6 +186,7 @@ const main = async () => {
|
|
|
183
186
|
else {
|
|
184
187
|
(0, node_process_1.exit)(0);
|
|
185
188
|
}
|
|
189
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
186
190
|
}
|
|
187
191
|
catch (e) {
|
|
188
192
|
console.log(chalk_1.default.red("\nError: Can't validate translations. Check if the format is supported or specify the translation format i.e. -f i18next"));
|
|
@@ -190,10 +194,10 @@ const main = async () => {
|
|
|
190
194
|
}
|
|
191
195
|
};
|
|
192
196
|
const printTranslationResult = ({ missingKeys, invalidKeys, }) => {
|
|
193
|
-
const reporter = commander_1.program.getOptionValue(
|
|
194
|
-
const isSummary = reporter ===
|
|
197
|
+
const reporter = commander_1.program.getOptionValue('reporter');
|
|
198
|
+
const isSummary = reporter === 'summary';
|
|
195
199
|
if (missingKeys && Object.keys(missingKeys).length > 0) {
|
|
196
|
-
console.log(chalk_1.default.red(
|
|
200
|
+
console.log(chalk_1.default.red('\nFound missing keys!'));
|
|
197
201
|
if (isSummary) {
|
|
198
202
|
console.log(chalk_1.default.red((0, errorReporters_1.formatSummaryTable)(missingKeys)));
|
|
199
203
|
}
|
|
@@ -203,10 +207,10 @@ const printTranslationResult = ({ missingKeys, invalidKeys, }) => {
|
|
|
203
207
|
}
|
|
204
208
|
}
|
|
205
209
|
else if (missingKeys) {
|
|
206
|
-
console.log(chalk_1.default.green(
|
|
210
|
+
console.log(chalk_1.default.green('\nNo missing keys found!'));
|
|
207
211
|
}
|
|
208
212
|
if (invalidKeys && Object.keys(invalidKeys).length > 0) {
|
|
209
|
-
console.log(chalk_1.default.red(
|
|
213
|
+
console.log(chalk_1.default.red('\nFound invalid keys!'));
|
|
210
214
|
if (isSummary) {
|
|
211
215
|
console.log(chalk_1.default.red((0, errorReporters_1.formatSummaryTable)(invalidKeys)));
|
|
212
216
|
}
|
|
@@ -216,14 +220,14 @@ const printTranslationResult = ({ missingKeys, invalidKeys, }) => {
|
|
|
216
220
|
}
|
|
217
221
|
}
|
|
218
222
|
else if (invalidKeys) {
|
|
219
|
-
console.log(chalk_1.default.green(
|
|
223
|
+
console.log(chalk_1.default.green('\nNo invalid translations found!'));
|
|
220
224
|
}
|
|
221
225
|
};
|
|
222
226
|
const printUnusedKeysResult = ({ unusedKeys, }) => {
|
|
223
|
-
const reporter = commander_1.program.getOptionValue(
|
|
224
|
-
const isSummary = reporter ===
|
|
227
|
+
const reporter = commander_1.program.getOptionValue('reporter');
|
|
228
|
+
const isSummary = reporter === 'summary';
|
|
225
229
|
if (unusedKeys && hasKeys(unusedKeys)) {
|
|
226
|
-
console.log(chalk_1.default.red(
|
|
230
|
+
console.log(chalk_1.default.red('\nFound unused keys!'));
|
|
227
231
|
if (isSummary) {
|
|
228
232
|
console.log(chalk_1.default.red((0, errorReporters_1.formatSummaryTable)(unusedKeys)));
|
|
229
233
|
}
|
|
@@ -232,14 +236,14 @@ const printUnusedKeysResult = ({ unusedKeys, }) => {
|
|
|
232
236
|
}
|
|
233
237
|
}
|
|
234
238
|
else if (unusedKeys) {
|
|
235
|
-
console.log(chalk_1.default.green(
|
|
239
|
+
console.log(chalk_1.default.green('\nNo unused keys found!'));
|
|
236
240
|
}
|
|
237
241
|
};
|
|
238
242
|
const printUndefinedKeysResult = ({ undefinedKeys, }) => {
|
|
239
|
-
const reporter = commander_1.program.getOptionValue(
|
|
240
|
-
const isSummary = reporter ===
|
|
243
|
+
const reporter = commander_1.program.getOptionValue('reporter');
|
|
244
|
+
const isSummary = reporter === 'summary';
|
|
241
245
|
if (undefinedKeys && hasKeys(undefinedKeys)) {
|
|
242
|
-
console.log(chalk_1.default.red(
|
|
246
|
+
console.log(chalk_1.default.red('\nFound undefined keys!'));
|
|
243
247
|
if (isSummary) {
|
|
244
248
|
console.log(chalk_1.default.red((0, errorReporters_1.formatSummaryTable)(undefinedKeys)));
|
|
245
249
|
}
|
|
@@ -248,7 +252,7 @@ const printUndefinedKeysResult = ({ undefinedKeys, }) => {
|
|
|
248
252
|
}
|
|
249
253
|
}
|
|
250
254
|
else if (undefinedKeys) {
|
|
251
|
-
console.log(chalk_1.default.green(
|
|
255
|
+
console.log(chalk_1.default.green('\nNo undefined keys found!'));
|
|
252
256
|
}
|
|
253
257
|
};
|
|
254
258
|
const hasKeys = (checkResult) => {
|