@lang-tag/cli 0.15.0 → 0.17.0

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.
Files changed (30) hide show
  1. package/README.md +23 -14
  2. package/algorithms/case-utils.d.ts +12 -0
  3. package/algorithms/collector/dictionary-collector.d.ts +2 -2
  4. package/algorithms/collector/index.d.ts +3 -3
  5. package/algorithms/collector/namespace-collector.d.ts +2 -2
  6. package/algorithms/collector/type.d.ts +2 -2
  7. package/algorithms/config-generation/config-keeper.d.ts +1 -1
  8. package/algorithms/config-generation/index.d.ts +3 -3
  9. package/algorithms/config-generation/path-based-config-generator.d.ts +4 -3
  10. package/algorithms/config-generation/prepend-namespace-to-path.d.ts +1 -1
  11. package/algorithms/import/flexible-import-algorithm.d.ts +232 -0
  12. package/algorithms/import/index.d.ts +2 -1
  13. package/algorithms/import/simple-mapping-import-algorithm.d.ts +120 -0
  14. package/algorithms/index.cjs +418 -26
  15. package/algorithms/index.d.ts +6 -3
  16. package/algorithms/index.js +420 -28
  17. package/chunks/namespace-collector.cjs +75 -0
  18. package/chunks/namespace-collector.js +76 -0
  19. package/index.cjs +1156 -743
  20. package/index.js +1316 -903
  21. package/logger.d.ts +1 -1
  22. package/package.json +1 -1
  23. package/templates/config/init-config.mustache +1 -0
  24. package/templates/import/imported-tag.mustache +14 -0
  25. package/{config.d.ts → type.d.ts} +41 -32
  26. package/namespace-collector-DCruv_PK.js +0 -95
  27. package/namespace-collector-DRnZvkDR.cjs +0 -94
  28. /package/{template → templates/tag}/base-app.mustache +0 -0
  29. /package/{template → templates/tag}/base-library.mustache +0 -0
  30. /package/{template → templates/tag}/placeholder.mustache +0 -0
@@ -1,8 +1,20 @@
1
- import { T as TranslationsCollector, e as $LT_RemoveFile, c as $LT_EnsureDirectoryExists } from "../namespace-collector-DCruv_PK.js";
2
- import { N } from "../namespace-collector-DCruv_PK.js";
3
- import path, { resolve, sep } from "pathe";
4
- import process__default from "node:process";
5
1
  import * as caseLib from "case";
2
+ import process__default from "node:process";
3
+ import { rm, mkdir } from "fs/promises";
4
+ import path, { resolve, sep, join } from "pathe";
5
+ import { T as TranslationsCollector } from "../chunks/namespace-collector.js";
6
+ import { N } from "../chunks/namespace-collector.js";
7
+ import micromatch from "micromatch";
8
+ function applyCaseTransform(str, caseType) {
9
+ if (caseType === "no") {
10
+ return str;
11
+ }
12
+ const caseFunction = caseLib[caseType];
13
+ if (typeof caseFunction === "function") {
14
+ return caseFunction(str);
15
+ }
16
+ return str;
17
+ }
6
18
  class DictionaryCollector extends TranslationsCollector {
7
19
  constructor(options = {
8
20
  appendNamespaceToPath: false
@@ -36,12 +48,15 @@ class DictionaryCollector extends TranslationsCollector {
36
48
  }
37
49
  async preWrite(clean) {
38
50
  this.clean = clean;
39
- const baseDictionaryFile = path.join(this.config.localesDirectory, `${this.config.baseLanguageCode}.json`);
51
+ const baseDictionaryFile = path.join(
52
+ this.config.localesDirectory,
53
+ `${this.config.baseLanguageCode}.json`
54
+ );
40
55
  if (clean) {
41
56
  this.logger.info("Removing {file}", { file: baseDictionaryFile });
42
- await $LT_RemoveFile(baseDictionaryFile);
57
+ await removeFile(baseDictionaryFile);
43
58
  }
44
- await $LT_EnsureDirectoryExists(this.config.localesDirectory);
59
+ await ensureDirectoryExists(this.config.localesDirectory);
45
60
  }
46
61
  async resolveCollectionFilePath(baseLanguageCode) {
47
62
  return resolve(
@@ -52,16 +67,23 @@ class DictionaryCollector extends TranslationsCollector {
52
67
  }
53
68
  async onMissingCollection(baseLanguageCode) {
54
69
  if (!this.clean) {
55
- this.logger.warn(`Original dictionary file "{namespace}.json" not found. A new one will be created.`, { namespace: baseLanguageCode });
70
+ this.logger.warn(
71
+ `Original dictionary file "{namespace}.json" not found. A new one will be created.`,
72
+ { namespace: baseLanguageCode }
73
+ );
56
74
  }
57
75
  }
58
76
  async postWrite(changedCollections) {
59
77
  if (!changedCollections?.length) {
60
- this.logger.info("No changes were made based on the current configuration and files");
78
+ this.logger.info(
79
+ "No changes were made based on the current configuration and files"
80
+ );
61
81
  return;
62
82
  }
63
83
  if (changedCollections.length > 1) {
64
- throw new Error("Should not write more than 1 collection! Only 1 base language dictionary expected!");
84
+ throw new Error(
85
+ "Should not write more than 1 collection! Only 1 base language dictionary expected!"
86
+ );
65
87
  }
66
88
  const dict = resolve(
67
89
  this.config.localesDirectory,
@@ -70,6 +92,21 @@ class DictionaryCollector extends TranslationsCollector {
70
92
  this.logger.success("Updated dictionary {dict}", { dict });
71
93
  }
72
94
  }
95
+ async function ensureDirectoryExists(filePath) {
96
+ try {
97
+ await mkdir(filePath, { recursive: true });
98
+ } catch (error) {
99
+ if (error.code !== "EEXIST") {
100
+ throw error;
101
+ }
102
+ }
103
+ }
104
+ async function removeFile(filePath) {
105
+ try {
106
+ await rm(filePath, { force: true });
107
+ } catch (error) {
108
+ }
109
+ }
73
110
  const TRIGGER_NAME$2 = "path-based-config-generator";
74
111
  function pathBasedConfigGenerator(options = {}) {
75
112
  const {
@@ -116,15 +153,22 @@ function pathBasedConfigGenerator(options = {}) {
116
153
  if (hasPathRules) {
117
154
  pathSegments = applyPathRules(pathSegments, pathRules);
118
155
  } else {
119
- pathSegments = applyStructuredIgnore(pathSegments, ignoreStructured);
156
+ pathSegments = applyStructuredIgnore(
157
+ pathSegments,
158
+ ignoreStructured
159
+ );
120
160
  }
121
161
  if (ignoreIncludesRootDirectories && langTagConfig.includes && pathSegments.length > 0) {
122
- const extractedDirectories = extractRootDirectoriesFromIncludes(langTagConfig.includes);
162
+ const extractedDirectories = extractRootDirectoriesFromIncludes(
163
+ langTagConfig.includes
164
+ );
123
165
  if (extractedDirectories.includes(pathSegments[0])) {
124
166
  pathSegments = pathSegments.slice(1);
125
167
  }
126
168
  }
127
- pathSegments = pathSegments.filter((seg) => !ignoreDirectories.includes(seg));
169
+ pathSegments = pathSegments.filter(
170
+ (seg) => !ignoreDirectories.includes(seg)
171
+ );
128
172
  let namespace;
129
173
  let path2;
130
174
  if (pathSegments.length >= 1) {
@@ -147,7 +191,9 @@ function pathBasedConfigGenerator(options = {}) {
147
191
  }
148
192
  if (path2 && pathCase) {
149
193
  const pathParts = path2.split(".");
150
- const transformedParts = pathParts.map((part) => applyCaseTransform(part, pathCase));
194
+ const transformedParts = pathParts.map(
195
+ (part) => applyCaseTransform(part, pathCase)
196
+ );
151
197
  path2 = transformedParts.join(".");
152
198
  }
153
199
  const newConfig = event.config ? { ...event.config } : {};
@@ -306,7 +352,10 @@ function applyPathRules(segments, structure) {
306
352
  const remainingSegments = segments.slice(i + 1);
307
353
  const ruleWithoutRedirect = { ...rule };
308
354
  delete ruleWithoutRedirect[">>"];
309
- const processedRemaining = applyPathRules(remainingSegments, ruleWithoutRedirect);
355
+ const processedRemaining = applyPathRules(
356
+ remainingSegments,
357
+ ruleWithoutRedirect
358
+ );
310
359
  deepestRedirect = {
311
360
  rule: redirectRule,
312
361
  remainingSegments: processedRemaining,
@@ -340,13 +389,6 @@ function applyPathRules(segments, structure) {
340
389
  }
341
390
  return result;
342
391
  }
343
- function applyCaseTransform(str, caseType) {
344
- const caseFunction = caseLib[caseType];
345
- if (typeof caseFunction === "function") {
346
- return caseFunction(str);
347
- }
348
- return str;
349
- }
350
392
  function extractRootDirectoriesFromIncludes(includes) {
351
393
  const directories = /* @__PURE__ */ new Set();
352
394
  for (const pattern of includes) {
@@ -439,17 +481,367 @@ function prependNamespaceToPath(options = {}) {
439
481
  } else {
440
482
  newPath = actualNamespace;
441
483
  }
442
- event.save({
443
- ...currentConfig || {},
444
- path: newPath,
445
- namespace: void 0
446
- }, TRIGGER_NAME);
484
+ event.save(
485
+ {
486
+ ...currentConfig || {},
487
+ path: newPath,
488
+ namespace: void 0
489
+ },
490
+ TRIGGER_NAME
491
+ );
492
+ };
493
+ }
494
+ function flexibleImportAlgorithm(options = {}) {
495
+ const {
496
+ variableName = {},
497
+ filePath = {},
498
+ include,
499
+ exclude = {},
500
+ configRemap
501
+ } = options;
502
+ const { packages: includePackages, namespaces: includeNamespaces } = include || {};
503
+ const {
504
+ packages: excludePackages = [],
505
+ namespaces: excludeNamespaces = []
506
+ } = exclude;
507
+ return (event) => {
508
+ const { exports, importManager, logger } = event;
509
+ for (const { packageJSON, exportData } of exports) {
510
+ const packageName = packageJSON.name || "unknown-package";
511
+ if (includePackages && !matchesAnyPattern(packageName, includePackages)) {
512
+ logger.debug(
513
+ `Skipping package not in include list: ${packageName}`
514
+ );
515
+ continue;
516
+ }
517
+ if (matchesAnyPattern(packageName, excludePackages)) {
518
+ logger.debug(`Skipping excluded package: ${packageName}`);
519
+ continue;
520
+ }
521
+ logger.debug(`Processing library: ${packageName}`);
522
+ for (const file of exportData.files) {
523
+ const originalFileName = file.relativeFilePath;
524
+ const targetFilePath = generateFilePath(
525
+ packageName,
526
+ originalFileName,
527
+ filePath
528
+ );
529
+ for (let i = 0; i < file.tags.length; i++) {
530
+ const tag = file.tags[i];
531
+ const tagNamespace = tag.config?.namespace;
532
+ if (includeNamespaces && tagNamespace && !matchesAnyPattern(tagNamespace, includeNamespaces)) {
533
+ logger.debug(
534
+ `Skipping namespace not in include list: ${tagNamespace}`
535
+ );
536
+ continue;
537
+ }
538
+ if (tagNamespace && matchesAnyPattern(tagNamespace, excludeNamespaces)) {
539
+ logger.debug(
540
+ `Skipping excluded namespace: ${tagNamespace}`
541
+ );
542
+ continue;
543
+ }
544
+ const finalVariableName = generateVariableName(
545
+ tag.variableName,
546
+ packageName,
547
+ originalFileName,
548
+ i,
549
+ variableName,
550
+ tag
551
+ );
552
+ if (finalVariableName === null) {
553
+ logger.debug(
554
+ `Skipping tag without variableName in ${join(packageName, originalFileName)}`
555
+ );
556
+ continue;
557
+ }
558
+ let finalConfig = tag.config;
559
+ if (configRemap) {
560
+ const remappedConfig = configRemap(tag.config, {
561
+ packageName,
562
+ fileName: originalFileName,
563
+ variableName: finalVariableName,
564
+ tagIndex: i
565
+ });
566
+ if (remappedConfig === null) {
567
+ logger.debug(
568
+ `Removing config due to configRemap returning null in ${join(packageName, originalFileName)}`
569
+ );
570
+ finalConfig = null;
571
+ } else {
572
+ finalConfig = remappedConfig;
573
+ }
574
+ }
575
+ importManager.importTag(targetFilePath, {
576
+ variableName: finalVariableName,
577
+ translations: tag.translations,
578
+ config: finalConfig
579
+ });
580
+ logger.debug(
581
+ `Imported: ${finalVariableName} -> ${targetFilePath}`
582
+ );
583
+ }
584
+ }
585
+ }
586
+ };
587
+ }
588
+ function sanitizeVariableName(name) {
589
+ let sanitized = name.replace(/[^a-zA-Z0-9_$]/g, "$");
590
+ if (/^[0-9]/.test(sanitized)) {
591
+ sanitized = "$" + sanitized;
592
+ }
593
+ if (sanitized === "") {
594
+ sanitized = "$";
595
+ }
596
+ return sanitized;
597
+ }
598
+ function applyCaseTransformToPath(filePath, caseType) {
599
+ if (typeof caseType === "string") {
600
+ const segments = filePath.split("/");
601
+ const fileName = segments[segments.length - 1];
602
+ const directorySegments = segments.slice(0, -1);
603
+ const transformedDirectories = directorySegments.map(
604
+ (dir) => applyCaseTransform(dir, caseType)
605
+ );
606
+ const transformedFileName = applyCaseTransformToFileName(
607
+ fileName,
608
+ caseType
609
+ );
610
+ if (transformedDirectories.length === 0) {
611
+ return transformedFileName;
612
+ }
613
+ return [...transformedDirectories, transformedFileName].join("/");
614
+ }
615
+ if (typeof caseType === "object") {
616
+ const { directories = "no", files = "no" } = caseType;
617
+ const segments = filePath.split("/");
618
+ const fileName = segments[segments.length - 1];
619
+ const directorySegments = segments.slice(0, -1);
620
+ const transformedDirectories = directorySegments.map(
621
+ (dir) => applyCaseTransform(dir, directories)
622
+ );
623
+ const transformedFileName = applyCaseTransformToFileName(
624
+ fileName,
625
+ files
626
+ );
627
+ if (transformedDirectories.length === 0) {
628
+ return transformedFileName;
629
+ }
630
+ return [...transformedDirectories, transformedFileName].join("/");
631
+ }
632
+ return filePath;
633
+ }
634
+ function normalizePackageName(packageName, scopedPackageHandling = "replace", context = "variableName") {
635
+ switch (scopedPackageHandling) {
636
+ case "remove-scope":
637
+ let result = packageName.replace(/^@[^/]+\//, "");
638
+ if (context === "variableName") {
639
+ result = result.replace(/[^a-zA-Z0-9_$]/g, "_");
640
+ }
641
+ return result;
642
+ case "replace":
643
+ default:
644
+ let normalized = packageName.replace(/@/g, "").replace(/\//g, context === "variableName" ? "_" : "-");
645
+ if (context === "variableName") {
646
+ normalized = normalized.replace(/[^a-zA-Z0-9_$]/g, "_");
647
+ }
648
+ return normalized;
649
+ }
650
+ }
651
+ function generateVariableName(originalVariableName, packageName, fileName, index, options, tag) {
652
+ const {
653
+ prefixWithPackageName = false,
654
+ scopedPackageHandling = "replace",
655
+ case: caseType = "no",
656
+ sanitizeVariableName: shouldSanitize = true,
657
+ handleMissingVariableName = "auto-generate",
658
+ customVariableName
659
+ } = options;
660
+ if (customVariableName) {
661
+ const customName = customVariableName({
662
+ packageName,
663
+ fileName,
664
+ originalVariableName,
665
+ tagIndex: index,
666
+ tag
667
+ });
668
+ if (customName !== null) {
669
+ originalVariableName = customName;
670
+ }
671
+ }
672
+ if (!originalVariableName) {
673
+ switch (handleMissingVariableName) {
674
+ case "skip":
675
+ return null;
676
+ case "auto-generate":
677
+ originalVariableName = `translations${index + 1}`;
678
+ break;
679
+ default:
680
+ if (typeof handleMissingVariableName === "function") {
681
+ originalVariableName = handleMissingVariableName(
682
+ {},
683
+ packageName,
684
+ fileName,
685
+ index
686
+ );
687
+ } else {
688
+ return null;
689
+ }
690
+ }
691
+ }
692
+ let finalName = originalVariableName;
693
+ if (prefixWithPackageName) {
694
+ const normalizedPackageName = normalizePackageName(
695
+ packageName,
696
+ scopedPackageHandling,
697
+ "variableName"
698
+ );
699
+ finalName = `${normalizedPackageName}_${originalVariableName}`;
700
+ }
701
+ const transformedName = applyCaseTransform(finalName, caseType);
702
+ return shouldSanitize ? sanitizeVariableName(transformedName) : transformedName;
703
+ }
704
+ function generateFilePath(packageName, originalFileName, options) {
705
+ const {
706
+ groupByPackage = false,
707
+ includePackageInPath = false,
708
+ scopedPackageHandling = "replace",
709
+ case: caseType = "no"
710
+ } = options;
711
+ if (groupByPackage) {
712
+ const normalizedPackageName = normalizePackageName(
713
+ packageName,
714
+ scopedPackageHandling,
715
+ "filePath"
716
+ );
717
+ const fileName = `${normalizedPackageName}.ts`;
718
+ return applyCaseTransformToFileName(
719
+ fileName,
720
+ typeof caseType === "string" ? caseType : caseType.files || "no"
721
+ );
722
+ } else if (includePackageInPath) {
723
+ const normalizedPackageName = normalizePackageName(
724
+ packageName,
725
+ scopedPackageHandling,
726
+ "filePath"
727
+ );
728
+ if (typeof caseType === "string") {
729
+ const transformedPackageName = applyCaseTransform(
730
+ normalizedPackageName,
731
+ caseType
732
+ );
733
+ const transformedFilePath = applyCaseTransformToPath(
734
+ originalFileName,
735
+ caseType
736
+ );
737
+ return join(transformedPackageName, transformedFilePath);
738
+ } else {
739
+ const transformedPackageName = applyCaseTransform(
740
+ normalizedPackageName,
741
+ caseType.directories || "no"
742
+ );
743
+ const transformedFilePath = applyCaseTransformToPath(
744
+ originalFileName,
745
+ caseType
746
+ );
747
+ return join(transformedPackageName, transformedFilePath);
748
+ }
749
+ } else {
750
+ return applyCaseTransformToPath(originalFileName, caseType);
751
+ }
752
+ }
753
+ function applyCaseTransformToFileName(fileName, caseType) {
754
+ if (caseType === "no") {
755
+ return fileName;
756
+ }
757
+ const lastDotIndex = fileName.lastIndexOf(".");
758
+ if (lastDotIndex === -1) {
759
+ return applyCaseTransform(fileName, caseType);
760
+ }
761
+ const nameWithoutExt = fileName.substring(0, lastDotIndex);
762
+ const extension = fileName.substring(lastDotIndex);
763
+ const transformedName = applyCaseTransform(nameWithoutExt, caseType);
764
+ return transformedName + extension;
765
+ }
766
+ function matchesAnyPattern(str, patterns) {
767
+ return micromatch.isMatch(str, patterns);
768
+ }
769
+ function simpleMappingImportAlgorithm(options) {
770
+ const { mappings, configRemap } = options;
771
+ const packageMap = /* @__PURE__ */ new Map();
772
+ const fileMap = /* @__PURE__ */ new Map();
773
+ for (const mapping of mappings) {
774
+ packageMap.set(mapping.packageName, mapping);
775
+ const files = /* @__PURE__ */ new Map();
776
+ for (const file of mapping.files) {
777
+ files.set(file.sourceFile, file);
778
+ }
779
+ fileMap.set(mapping.packageName, files);
780
+ }
781
+ return (event) => {
782
+ const { exports, importManager, logger } = event;
783
+ for (const { packageJSON, exportData } of exports) {
784
+ const packageName = packageJSON.name || "unknown-package";
785
+ const packageMapping = packageMap.get(packageName);
786
+ if (!packageMapping) {
787
+ logger.debug(`Skipping unmapped package: ${packageName}`);
788
+ continue;
789
+ }
790
+ logger.debug(`Processing mapped package: ${packageName}`);
791
+ for (const file of exportData.files) {
792
+ const sourceFile = file.relativeFilePath;
793
+ const packageFiles = fileMap.get(packageName);
794
+ if (!packageFiles) continue;
795
+ const fileMapping = packageFiles.get(sourceFile);
796
+ if (!fileMapping) {
797
+ logger.debug(
798
+ `Skipping unmapped file: ${packageName}/${sourceFile}`
799
+ );
800
+ continue;
801
+ }
802
+ logger.debug(
803
+ `Processing mapped file: ${packageName}/${sourceFile} -> ${fileMapping.targetFile}`
804
+ );
805
+ for (const tag of file.tags) {
806
+ const originalVariableName = tag.variableName;
807
+ if (!originalVariableName || !(originalVariableName in fileMapping.variables)) {
808
+ logger.debug(
809
+ `Skipping unmapped variable: ${originalVariableName} in ${packageName}/${sourceFile}`
810
+ );
811
+ continue;
812
+ }
813
+ const newVariableName = fileMapping.variables[originalVariableName] || originalVariableName;
814
+ const targetFilePath = fileMapping.targetFile;
815
+ let finalConfig = tag.config;
816
+ if (configRemap) {
817
+ finalConfig = configRemap(tag.config, {
818
+ packageName,
819
+ sourceFile,
820
+ targetFile: targetFilePath,
821
+ variableName: newVariableName,
822
+ originalVariableName
823
+ });
824
+ }
825
+ importManager.importTag(targetFilePath, {
826
+ variableName: newVariableName,
827
+ translations: tag.translations,
828
+ config: finalConfig
829
+ });
830
+ logger.debug(
831
+ `Imported: ${originalVariableName} -> ${newVariableName} in ${targetFilePath}`
832
+ );
833
+ }
834
+ }
835
+ }
447
836
  };
448
837
  }
449
838
  export {
450
839
  DictionaryCollector,
451
840
  N as NamespaceCollector,
841
+ applyCaseTransform,
452
842
  configKeeper,
843
+ flexibleImportAlgorithm,
453
844
  pathBasedConfigGenerator,
454
- prependNamespaceToPath
845
+ prependNamespaceToPath,
846
+ simpleMappingImportAlgorithm
455
847
  };
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ const process = require("node:process");
3
+ const promises = require("fs/promises");
4
+ const path = require("pathe");
5
+ class TranslationsCollector {
6
+ config;
7
+ logger;
8
+ }
9
+ class NamespaceCollector extends TranslationsCollector {
10
+ clean;
11
+ languageDirectory;
12
+ aggregateCollection(namespace) {
13
+ return namespace;
14
+ }
15
+ transformTag(tag) {
16
+ return tag;
17
+ }
18
+ async preWrite(clean) {
19
+ this.clean = clean;
20
+ this.languageDirectory = path.join(
21
+ this.config.localesDirectory,
22
+ this.config.baseLanguageCode
23
+ );
24
+ if (clean) {
25
+ this.logger.info("Cleaning output directory...");
26
+ await removeDirectory(this.languageDirectory);
27
+ }
28
+ await ensureDirectoryExists(this.languageDirectory);
29
+ }
30
+ async resolveCollectionFilePath(collectionName) {
31
+ return path.resolve(
32
+ process.cwd(),
33
+ this.languageDirectory,
34
+ collectionName + ".json"
35
+ );
36
+ }
37
+ async onMissingCollection(collectionName) {
38
+ if (!this.clean) {
39
+ this.logger.warn(
40
+ `Original namespace file "{namespace}.json" not found. A new one will be created.`,
41
+ { namespace: collectionName }
42
+ );
43
+ }
44
+ }
45
+ async postWrite(changedCollections) {
46
+ if (!changedCollections?.length) {
47
+ this.logger.info(
48
+ "No changes were made based on the current configuration and files"
49
+ );
50
+ return;
51
+ }
52
+ const n = changedCollections.map((n2) => `"${n2}.json"`).join(", ");
53
+ this.logger.success("Updated namespaces {outputDir} ({namespaces})", {
54
+ outputDir: this.config.localesDirectory,
55
+ namespaces: n
56
+ });
57
+ }
58
+ }
59
+ async function ensureDirectoryExists(filePath) {
60
+ try {
61
+ await promises.mkdir(filePath, { recursive: true });
62
+ } catch (error) {
63
+ if (error.code !== "EEXIST") {
64
+ throw error;
65
+ }
66
+ }
67
+ }
68
+ async function removeDirectory(dirPath) {
69
+ try {
70
+ await promises.rm(dirPath, { recursive: true, force: true });
71
+ } catch (error) {
72
+ }
73
+ }
74
+ exports.NamespaceCollector = NamespaceCollector;
75
+ exports.TranslationsCollector = TranslationsCollector;
@@ -0,0 +1,76 @@
1
+ import process__default from "node:process";
2
+ import { rm, mkdir } from "fs/promises";
3
+ import path, { resolve } from "pathe";
4
+ class TranslationsCollector {
5
+ config;
6
+ logger;
7
+ }
8
+ class NamespaceCollector extends TranslationsCollector {
9
+ clean;
10
+ languageDirectory;
11
+ aggregateCollection(namespace) {
12
+ return namespace;
13
+ }
14
+ transformTag(tag) {
15
+ return tag;
16
+ }
17
+ async preWrite(clean) {
18
+ this.clean = clean;
19
+ this.languageDirectory = path.join(
20
+ this.config.localesDirectory,
21
+ this.config.baseLanguageCode
22
+ );
23
+ if (clean) {
24
+ this.logger.info("Cleaning output directory...");
25
+ await removeDirectory(this.languageDirectory);
26
+ }
27
+ await ensureDirectoryExists(this.languageDirectory);
28
+ }
29
+ async resolveCollectionFilePath(collectionName) {
30
+ return resolve(
31
+ process__default.cwd(),
32
+ this.languageDirectory,
33
+ collectionName + ".json"
34
+ );
35
+ }
36
+ async onMissingCollection(collectionName) {
37
+ if (!this.clean) {
38
+ this.logger.warn(
39
+ `Original namespace file "{namespace}.json" not found. A new one will be created.`,
40
+ { namespace: collectionName }
41
+ );
42
+ }
43
+ }
44
+ async postWrite(changedCollections) {
45
+ if (!changedCollections?.length) {
46
+ this.logger.info(
47
+ "No changes were made based on the current configuration and files"
48
+ );
49
+ return;
50
+ }
51
+ const n = changedCollections.map((n2) => `"${n2}.json"`).join(", ");
52
+ this.logger.success("Updated namespaces {outputDir} ({namespaces})", {
53
+ outputDir: this.config.localesDirectory,
54
+ namespaces: n
55
+ });
56
+ }
57
+ }
58
+ async function ensureDirectoryExists(filePath) {
59
+ try {
60
+ await mkdir(filePath, { recursive: true });
61
+ } catch (error) {
62
+ if (error.code !== "EEXIST") {
63
+ throw error;
64
+ }
65
+ }
66
+ }
67
+ async function removeDirectory(dirPath) {
68
+ try {
69
+ await rm(dirPath, { recursive: true, force: true });
70
+ } catch (error) {
71
+ }
72
+ }
73
+ export {
74
+ NamespaceCollector as N,
75
+ TranslationsCollector as T
76
+ };