@intlayer/chokidar 1.2.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 (100) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cjs/chokidar/index.cjs +23 -0
  3. package/dist/cjs/chokidar/index.cjs.map +1 -0
  4. package/dist/cjs/chokidar/index.d.ts +2 -0
  5. package/dist/cjs/chokidar/watcher.cjs +89 -0
  6. package/dist/cjs/chokidar/watcher.cjs.map +1 -0
  7. package/dist/cjs/chokidar/watcher.d.ts +5 -0
  8. package/dist/cjs/index.cjs +35 -0
  9. package/dist/cjs/index.cjs.map +1 -0
  10. package/dist/cjs/index.d.ts +4 -0
  11. package/dist/cjs/transpiler/dictionary_to_main/createDictionaryList.cjs +76 -0
  12. package/dist/cjs/transpiler/dictionary_to_main/createDictionaryList.cjs.map +1 -0
  13. package/dist/cjs/transpiler/dictionary_to_main/createDictionaryList.d.ts +6 -0
  14. package/dist/cjs/transpiler/dictionary_to_main/index.cjs +23 -0
  15. package/dist/cjs/transpiler/dictionary_to_main/index.cjs.map +1 -0
  16. package/dist/cjs/transpiler/dictionary_to_main/index.d.ts +1 -0
  17. package/dist/cjs/transpiler/dictionary_to_type/createModuleAugmentation.cjs +87 -0
  18. package/dist/cjs/transpiler/dictionary_to_type/createModuleAugmentation.cjs.map +1 -0
  19. package/dist/cjs/transpiler/dictionary_to_type/createModuleAugmentation.d.ts +7 -0
  20. package/dist/cjs/transpiler/dictionary_to_type/createType.cjs +114 -0
  21. package/dist/cjs/transpiler/dictionary_to_type/createType.cjs.map +1 -0
  22. package/dist/cjs/transpiler/dictionary_to_type/createType.d.ts +42 -0
  23. package/dist/cjs/transpiler/dictionary_to_type/index.cjs +25 -0
  24. package/dist/cjs/transpiler/dictionary_to_type/index.cjs.map +1 -0
  25. package/dist/cjs/transpiler/dictionary_to_type/index.d.ts +3 -0
  26. package/dist/cjs/transpiler/intlater_module_to_dictionary/extractNestedJSON.cjs +45 -0
  27. package/dist/cjs/transpiler/intlater_module_to_dictionary/extractNestedJSON.cjs.map +1 -0
  28. package/dist/cjs/transpiler/intlater_module_to_dictionary/extractNestedJSON.d.ts +44 -0
  29. package/dist/cjs/transpiler/intlater_module_to_dictionary/index.cjs +27 -0
  30. package/dist/cjs/transpiler/intlater_module_to_dictionary/index.cjs.map +1 -0
  31. package/dist/cjs/transpiler/intlater_module_to_dictionary/index.d.ts +4 -0
  32. package/dist/cjs/transpiler/intlater_module_to_dictionary/loadContentDeclaration.cjs +98 -0
  33. package/dist/cjs/transpiler/intlater_module_to_dictionary/loadContentDeclaration.cjs.map +1 -0
  34. package/dist/cjs/transpiler/intlater_module_to_dictionary/loadContentDeclaration.d.ts +10 -0
  35. package/dist/cjs/transpiler/intlater_module_to_dictionary/processModule.cjs +69 -0
  36. package/dist/cjs/transpiler/intlater_module_to_dictionary/processModule.cjs.map +1 -0
  37. package/dist/cjs/transpiler/intlater_module_to_dictionary/processModule.d.ts +8 -0
  38. package/dist/cjs/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.cjs +66 -0
  39. package/dist/cjs/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.cjs.map +1 -0
  40. package/dist/cjs/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.d.ts +6 -0
  41. package/dist/cjs/utils.cjs +55 -0
  42. package/dist/cjs/utils.cjs.map +1 -0
  43. package/dist/cjs/utils.d.ts +4 -0
  44. package/dist/esm/chokidar/index.d.mts +2 -0
  45. package/dist/esm/chokidar/index.mjs +2 -0
  46. package/dist/esm/chokidar/index.mjs.map +1 -0
  47. package/dist/esm/chokidar/watcher.d.mts +5 -0
  48. package/dist/esm/chokidar/watcher.mjs +58 -0
  49. package/dist/esm/chokidar/watcher.mjs.map +1 -0
  50. package/dist/esm/index.d.mts +4 -0
  51. package/dist/esm/index.mjs +9 -0
  52. package/dist/esm/index.mjs.map +1 -0
  53. package/dist/esm/transpiler/dictionary_to_main/createDictionaryList.d.mts +6 -0
  54. package/dist/esm/transpiler/dictionary_to_main/createDictionaryList.mjs +52 -0
  55. package/dist/esm/transpiler/dictionary_to_main/createDictionaryList.mjs.map +1 -0
  56. package/dist/esm/transpiler/dictionary_to_main/index.d.mts +1 -0
  57. package/dist/esm/transpiler/dictionary_to_main/index.mjs +2 -0
  58. package/dist/esm/transpiler/dictionary_to_main/index.mjs.map +1 -0
  59. package/dist/esm/transpiler/dictionary_to_type/createModuleAugmentation.d.mts +7 -0
  60. package/dist/esm/transpiler/dictionary_to_type/createModuleAugmentation.mjs +62 -0
  61. package/dist/esm/transpiler/dictionary_to_type/createModuleAugmentation.mjs.map +1 -0
  62. package/dist/esm/transpiler/dictionary_to_type/createType.d.mts +42 -0
  63. package/dist/esm/transpiler/dictionary_to_type/createType.mjs +89 -0
  64. package/dist/esm/transpiler/dictionary_to_type/createType.mjs.map +1 -0
  65. package/dist/esm/transpiler/dictionary_to_type/index.d.mts +3 -0
  66. package/dist/esm/transpiler/dictionary_to_type/index.mjs +3 -0
  67. package/dist/esm/transpiler/dictionary_to_type/index.mjs.map +1 -0
  68. package/dist/esm/transpiler/intlater_module_to_dictionary/extractNestedJSON.d.mts +44 -0
  69. package/dist/esm/transpiler/intlater_module_to_dictionary/extractNestedJSON.mjs +21 -0
  70. package/dist/esm/transpiler/intlater_module_to_dictionary/extractNestedJSON.mjs.map +1 -0
  71. package/dist/esm/transpiler/intlater_module_to_dictionary/index.d.mts +4 -0
  72. package/dist/esm/transpiler/intlater_module_to_dictionary/index.mjs +4 -0
  73. package/dist/esm/transpiler/intlater_module_to_dictionary/index.mjs.map +1 -0
  74. package/dist/esm/transpiler/intlater_module_to_dictionary/loadContentDeclaration.d.mts +10 -0
  75. package/dist/esm/transpiler/intlater_module_to_dictionary/loadContentDeclaration.mjs +73 -0
  76. package/dist/esm/transpiler/intlater_module_to_dictionary/loadContentDeclaration.mjs.map +1 -0
  77. package/dist/esm/transpiler/intlater_module_to_dictionary/processModule.d.mts +8 -0
  78. package/dist/esm/transpiler/intlater_module_to_dictionary/processModule.mjs +45 -0
  79. package/dist/esm/transpiler/intlater_module_to_dictionary/processModule.mjs.map +1 -0
  80. package/dist/esm/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.d.mts +6 -0
  81. package/dist/esm/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.mjs +42 -0
  82. package/dist/esm/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.mjs.map +1 -0
  83. package/dist/esm/utils.d.mts +4 -0
  84. package/dist/esm/utils.mjs +20 -0
  85. package/dist/esm/utils.mjs.map +1 -0
  86. package/package.json +85 -0
  87. package/src/chokidar/index.ts +1 -0
  88. package/src/chokidar/watcher.ts +84 -0
  89. package/src/index.ts +3 -0
  90. package/src/transpiler/dictionary_to_main/createDictionaryList.ts +65 -0
  91. package/src/transpiler/dictionary_to_main/index.ts +1 -0
  92. package/src/transpiler/dictionary_to_type/createModuleAugmentation.ts +95 -0
  93. package/src/transpiler/dictionary_to_type/createType.ts +145 -0
  94. package/src/transpiler/dictionary_to_type/index.ts +2 -0
  95. package/src/transpiler/intlater_module_to_dictionary/extractNestedJSON.ts +60 -0
  96. package/src/transpiler/intlater_module_to_dictionary/index.ts +3 -0
  97. package/src/transpiler/intlater_module_to_dictionary/loadContentDeclaration.ts +114 -0
  98. package/src/transpiler/intlater_module_to_dictionary/processModule.ts +66 -0
  99. package/src/transpiler/intlater_module_to_dictionary/transpileContentDeclaration.ts +62 -0
  100. package/src/utils.ts +26 -0
@@ -0,0 +1,20 @@
1
+ import crypto from "crypto-js";
2
+ const getFileHash = (filePath) => {
3
+ const hash = crypto.SHA3(filePath);
4
+ return hash.toString(crypto.enc.Base64).replace(/[^A-Z\d]/gi, "").substring(0, 20);
5
+ };
6
+ const transformToCamelCase = (string) => {
7
+ const words = string.split(/[\s\-_]+/);
8
+ const camelCasedWords = words.map((word, index) => {
9
+ if (index === 0) {
10
+ return word[0].toUpperCase() + word.slice(1);
11
+ }
12
+ return word.charAt(0).toUpperCase() + word.slice(1);
13
+ });
14
+ return camelCasedWords.join("");
15
+ };
16
+ export {
17
+ getFileHash,
18
+ transformToCamelCase
19
+ };
20
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["import crypto from 'crypto-js';\n\nexport const getFileHash = (filePath: string) => {\n const hash = crypto.SHA3(filePath);\n\n return hash\n .toString(crypto.enc.Base64)\n .replace(/[^A-Z\\d]/gi, '')\n .substring(0, 20);\n};\n\nexport const transformToCamelCase = (string: string): string => {\n // Split the string into words using a regex that finds spaces, hyphens, and underscores\n const words = string.split(/[\\s\\-_]+/);\n\n // Transform each word except the first to have its first letter uppercase\n const camelCasedWords = words.map((word, index) => {\n if (index === 0) {\n return word[0].toUpperCase() + word.slice(1);\n }\n return word.charAt(0).toUpperCase() + word.slice(1);\n });\n\n // Join the words back together\n return camelCasedWords.join('');\n};\n"],"mappings":"AAAA,OAAO,YAAY;AAEZ,MAAM,cAAc,CAAC,aAAqB;AAC/C,QAAM,OAAO,OAAO,KAAK,QAAQ;AAEjC,SAAO,KACJ,SAAS,OAAO,IAAI,MAAM,EAC1B,QAAQ,cAAc,EAAE,EACxB,UAAU,GAAG,EAAE;AACpB;AAEO,MAAM,uBAAuB,CAAC,WAA2B;AAE9D,QAAM,QAAQ,OAAO,MAAM,UAAU;AAGrC,QAAM,kBAAkB,MAAM,IAAI,CAAC,MAAM,UAAU;AACjD,QAAI,UAAU,GAAG;AACf,aAAO,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AAAA,IAC7C;AACA,WAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AAAA,EACpD,CAAC;AAGD,SAAO,gBAAgB,KAAK,EAAE;AAChC;","names":[]}
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@intlayer/chokidar",
3
+ "version": "1.2.0",
4
+ "private": false,
5
+ "description": "Chokidar application for IntLayer - Transpile IntLayer declaration files into dictionaries.",
6
+ "keywords": [
7
+ "intlayer",
8
+ "chokidar",
9
+ "application",
10
+ "transpile",
11
+ "typescript",
12
+ "javascript",
13
+ "json",
14
+ "file"
15
+ ],
16
+ "homepage": "https://github.com/aypineau/intlayer",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/aypineau/intlayer.git"
20
+ },
21
+ "license": "MIT",
22
+ "author": {
23
+ "name": "Aymeric PINEAU",
24
+ "url": "https://github.com/aypineau"
25
+ },
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/esm/index.d.mts",
29
+ "require": "./dist/cjs/index.cjs",
30
+ "import": "./dist/esm/index.mjs"
31
+ },
32
+ "./package.json": "./package.json"
33
+ },
34
+ "main": "src/index.ts",
35
+ "typesVersions": {
36
+ "*": {
37
+ "package.json": [
38
+ "./package.json"
39
+ ]
40
+ }
41
+ },
42
+ "files": [
43
+ "./dist",
44
+ "./src",
45
+ "./bin",
46
+ "./package.json"
47
+ ],
48
+ "dependencies": {
49
+ "chokidar": "^3.6.0",
50
+ "crypto-js": "^4.2.0",
51
+ "esbuild": "^0.20.2",
52
+ "esbuild-loader": "^4.1.0",
53
+ "glob": "^10.3.12",
54
+ "node-loader": "^2.0.0",
55
+ "rimraf": "5.0.5",
56
+ "@intlayer/config": "^1.2.0",
57
+ "@intlayer/core": "^1.2.0",
58
+ "intlayer": "^1.2.0"
59
+ },
60
+ "devDependencies": {
61
+ "@changesets/cli": "2.27.1",
62
+ "@types/crypto-js": "^4.2.2",
63
+ "@types/node": "^20.12.7",
64
+ "node-polyfill-webpack-plugin": "^3.0.0",
65
+ "tsup": "^8.0.2",
66
+ "typescript": "^5.4.5",
67
+ "webpack-watch-files-plugin": "^1.2.1",
68
+ "@utils/eslint-config": "^1.0.1",
69
+ "@utils/ts-config": "^1.0.1"
70
+ },
71
+ "engines": {
72
+ "node": ">=14.18"
73
+ },
74
+ "bug": {
75
+ "url": "https://github.com/aypineau/intlayer/issues"
76
+ },
77
+ "scripts": {
78
+ "build": "tsup",
79
+ "clean": "rimraf ./dist",
80
+ "dev": "tsup --watch",
81
+ "lint": "eslint . --ext .ts,.tsx,.js,.jsx,.cjs,.mjs",
82
+ "lint:fix": "eslint . --ext .ts,.tsx,.js,.jsx,.cjs,.mjs --fix",
83
+ "prettier:fix": "prettier --write src/**/*"
84
+ }
85
+ }
@@ -0,0 +1 @@
1
+ export * from './watcher';
@@ -0,0 +1,84 @@
1
+ import { relative } from 'path';
2
+ import { getConfiguration } from '@intlayer/config';
3
+ import chokidar, { type WatchOptions } from 'chokidar';
4
+ import { sync } from 'glob';
5
+ import { createDictionaryList } from '../transpiler/dictionary_to_main/createDictionaryList';
6
+ import {
7
+ createTypes,
8
+ createModuleAugmentation,
9
+ } from '../transpiler/dictionary_to_type/index';
10
+ import { transpileContentDeclaration } from '../transpiler/intlater_module_to_dictionary/transpileContentDeclaration';
11
+
12
+ // Initialize chokidar watcher (non-persistent)
13
+ export const watch = (options?: WatchOptions) => {
14
+ const { content } = getConfiguration({
15
+ verbose: true,
16
+ });
17
+ const { watchedFilesPatternWithPath, baseDir } = content;
18
+
19
+ const files: string[] = sync(watchedFilesPatternWithPath);
20
+
21
+ return chokidar
22
+ .watch(watchedFilesPatternWithPath, {
23
+ persistent: true, // Make the watcher persistent
24
+ ignoreInitial: true, // Process existing files
25
+ ...options,
26
+ })
27
+ .on('ready', async () => {
28
+ const dictionariesPaths = await transpileContentDeclaration(files);
29
+
30
+ console.info('Building Intlayer types...');
31
+ createTypes(dictionariesPaths);
32
+
33
+ console.info('Building Intlayer module augmentation...');
34
+ createModuleAugmentation();
35
+
36
+ console.info('Building Intlayer dictionary list...');
37
+ createDictionaryList();
38
+
39
+ const relativeDictionariesPath = dictionariesPaths.map((dictionary) =>
40
+ relative(baseDir, dictionary)
41
+ );
42
+
43
+ console.info('Dictionaries:', relativeDictionariesPath);
44
+ })
45
+ .on('unlink', (filePath) => {
46
+ // Process the file with the functionToRun
47
+ console.info('Removed file detected: ', relative(baseDir, filePath));
48
+ // await transpileContentDeclaration(filePath);
49
+
50
+ // console.info('Building TypeScript types...');
51
+ // createTypes([filePath]);
52
+
53
+ // console.info('Building type index...');
54
+ // createModuleAugmentation();
55
+
56
+ // console.info('Building main...');
57
+ // createDictionaryList();
58
+ })
59
+ .on('add', async (filePath) => {
60
+ // Process the file with the functionToRun
61
+ console.info('Additional file detected: ', relative(baseDir, filePath));
62
+ const dictionaries = await transpileContentDeclaration(filePath);
63
+
64
+ console.info('Building TypeScript types...');
65
+ createTypes(dictionaries);
66
+
67
+ console.info('Building type index...');
68
+ createModuleAugmentation();
69
+
70
+ console.info('Building main...');
71
+ createDictionaryList();
72
+ })
73
+ .on('change', async (filePath) => {
74
+ // Process the file with the functionToRun
75
+ console.info('Change detected: ', relative(baseDir, filePath));
76
+ const dictionaries = await transpileContentDeclaration(filePath);
77
+
78
+ console.info('Building TypeScript types...');
79
+ createTypes(dictionaries);
80
+ })
81
+ .on('error', (error) => {
82
+ console.error('Watcher error:', error);
83
+ });
84
+ };
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { watch } from './chokidar/watcher';
2
+ export { createDictionaryList } from './transpiler/dictionary_to_main/createDictionaryList';
3
+ export { createModuleAugmentation } from './transpiler/dictionary_to_type/createModuleAugmentation';
@@ -0,0 +1,65 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { basename, extname, relative, resolve } from 'path';
3
+ import { getConfiguration } from '@intlayer/config';
4
+ import { sync } from 'glob';
5
+ import { getFileHash } from '../../utils';
6
+
7
+ const { content } = getConfiguration();
8
+ const { dictionariesDir, mainDir } = content;
9
+
10
+ /**
11
+ * This function generates the content of the dictionary list file
12
+ */
13
+ const generateDictionaryListContent = (
14
+ dictionaries: string[],
15
+ format: 'cjs' | 'esm' = 'esm'
16
+ ): string => {
17
+ let content = '';
18
+
19
+ const dictionariesRef = dictionaries.map((dictionaryPath) => ({
20
+ relativePath: relative(mainDir, dictionaryPath),
21
+ id: basename(dictionaryPath, extname(dictionaryPath)), // Get the base name as the dictionary id
22
+ hash: `_${getFileHash(dictionaryPath)}`, // Get the hash of the dictionary to avoid conflicts
23
+ }));
24
+
25
+ // Import all dictionaries
26
+ dictionariesRef.forEach((dictionary) => {
27
+ if (format === 'esm')
28
+ content += `import ${dictionary.hash} from '${dictionary.relativePath}';\n`;
29
+ if (format === 'cjs')
30
+ content += `const ${dictionary.hash} = require('${dictionary.relativePath}');\n`;
31
+ });
32
+
33
+ content += '\n';
34
+
35
+ // Format Dictionary Map
36
+ const formattedDictionaryMap: string = dictionariesRef
37
+ .map((dictionary) => `"${dictionary.id}": ${dictionary.hash}`)
38
+ .join(',\n');
39
+
40
+ if (format === 'esm')
41
+ content += `export default {\n${formattedDictionaryMap}\n};\n`;
42
+ if (format === 'cjs')
43
+ content += `module.exports = {\n${formattedDictionaryMap}\n};\n`;
44
+
45
+ return content;
46
+ };
47
+
48
+ /**
49
+ * This function generates a list of dictionaries in the main directory
50
+ */
51
+ export const createDictionaryList = () => {
52
+ // Create main directory if it doesn't exist
53
+ if (!existsSync(mainDir)) {
54
+ mkdirSync(mainDir, { recursive: true });
55
+ }
56
+
57
+ const dictionaries: string[] = sync(`${dictionariesDir}/**/*.json`);
58
+
59
+ // Create the dictionary list file
60
+ const cjsContent = generateDictionaryListContent(dictionaries, 'cjs');
61
+ writeFileSync(resolve(mainDir, 'dictionaries.cjs'), cjsContent);
62
+
63
+ const esmContent = generateDictionaryListContent(dictionaries, 'esm');
64
+ writeFileSync(resolve(mainDir, 'dictionaries.mjs'), esmContent);
65
+ };
@@ -0,0 +1 @@
1
+ export * from './createDictionaryList';
@@ -0,0 +1,95 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { basename, join, relative } from 'path';
3
+ import { Locales, getConfiguration } from '@intlayer/config';
4
+ import { sync } from 'glob';
5
+ import { getFileHash, transformToCamelCase } from '../../utils';
6
+
7
+ const { content, internationalization } = getConfiguration();
8
+ const { typesDir, moduleAugmentationDir } = content;
9
+ const { locales } = internationalization;
10
+
11
+ export const getTypeName = (id: string): string =>
12
+ transformToCamelCase(`${id}Content`);
13
+
14
+ /**
15
+ * This function generates the content of the module augmentation file
16
+ */
17
+ const generateTypeIndexContent = (typeFiles: string[]): string => {
18
+ let content =
19
+ "/* eslint-disable */\nimport 'intlayer';\nimport { Locales } from '@intlayer/config'\n";
20
+
21
+ const dictionariesRef = typeFiles.map((dictionaryPath) => ({
22
+ relativePath: relative(moduleAugmentationDir, dictionaryPath),
23
+ id: basename(dictionaryPath, '.d.ts'), // Get the base name as the dictionary id
24
+ hash: `_${getFileHash(dictionaryPath)}`, // Get the hash of the dictionary to avoid conflicts
25
+ }));
26
+
27
+ // Import all dictionaries
28
+ dictionariesRef.forEach((dictionary) => {
29
+ const typeName = getTypeName(dictionary.id);
30
+ content += `import type { ${typeName} as ${dictionary.hash} } from '${dictionary.relativePath}';\n`;
31
+ });
32
+
33
+ content += '\n';
34
+
35
+ // Format Dictionary Map
36
+ const formattedDictionaryMap: string = dictionariesRef
37
+ .map((dictionary) => ` "${dictionary.id}": ${dictionary.hash};`)
38
+ .join('\n');
39
+
40
+ const formatLocales = locales
41
+ .map((locale) => {
42
+ for (const key in Locales) {
43
+ if (Locales[key as keyof typeof Locales] === locale) {
44
+ return ` ${key} = '${locale}'`;
45
+ }
46
+ }
47
+ })
48
+ .join(',\n');
49
+
50
+ /**
51
+ * Write the module augmentation to extend the intlayer module with the dictionaries types
52
+ * Will suggest the type resulting of the dictionaries
53
+ *
54
+ * declare module 'intlayer' {
55
+ * interface IntlayerDictionaryTypesConnector = {
56
+ * dictionaries: {
57
+ * id: DictionaryType;
58
+ * }
59
+ * }
60
+ *
61
+ * enum ConfigLocales {
62
+ * ENGLISH = 'en',
63
+ * FRENCH = 'fr',
64
+ * SPANISH = 'es',
65
+ * }
66
+ *
67
+ * interface IConfigLocales<Content> extends Record<ConfigLocales, Content> {}
68
+ *
69
+ * }
70
+ * See https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
71
+ */
72
+ content += `declare module 'intlayer' {\n`;
73
+ content += ` interface IntlayerDictionaryTypesConnector {\n${formattedDictionaryMap}\n }\n\n`;
74
+ content += ` enum ConfigLocales {\n${formatLocales}\n };\n\n`;
75
+ content += ` interface IConfigLocales<Content> extends Record<ConfigLocales, Content> {}\n`;
76
+ content += `};`;
77
+
78
+ return content;
79
+ };
80
+
81
+ /**
82
+ * This function generates a index file merging all the types
83
+ */
84
+ export const createModuleAugmentation = () => {
85
+ // Create main directory if it doesn't exist
86
+ if (!existsSync(moduleAugmentationDir)) {
87
+ mkdirSync(moduleAugmentationDir, { recursive: true });
88
+ }
89
+
90
+ const dictionaries: string[] = sync(`${typesDir}/**/*.d.ts`);
91
+ // Create the dictionary list file
92
+
93
+ const tsContent = generateTypeIndexContent(dictionaries);
94
+ writeFileSync(join(moduleAugmentationDir, 'intlayer.d.ts'), tsContent);
95
+ };
@@ -0,0 +1,145 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { createRequire } from 'module';
3
+ import { resolve } from 'path';
4
+ import { getConfiguration } from '@intlayer/config';
5
+ import {
6
+ NodeType,
7
+ type Content,
8
+ type ContentModule,
9
+ type TypedNode,
10
+ } from '@intlayer/core';
11
+ import { getTypeName } from './createModuleAugmentation';
12
+
13
+ const { content, internationalization } = getConfiguration();
14
+ const { typesDir } = content;
15
+
16
+ const isESModule = typeof import.meta.url === 'string';
17
+ const requireFunction = isESModule ? createRequire(import.meta.url) : require;
18
+
19
+ /**
20
+ *
21
+ * This function generates a TypeScript type definition from a JSON object
22
+ *
23
+ * Example:
24
+ *
25
+ * const input = {
26
+ * id: '1',
27
+ * name: 'John Doe',
28
+ * address: {
29
+ * id: '2',
30
+ * street: '123 Main St',
31
+ * city: 'Springfield',
32
+ * }
33
+ * };
34
+ *
35
+ * const result = generateTypeScriptType(input, 'RootObject');
36
+ * console.log(result);
37
+ *
38
+ * Output:
39
+ *
40
+ * type RootObject = {
41
+ * id: '1',
42
+ * name: string,
43
+ * address: {
44
+ * id: '2',
45
+ * street: string,
46
+ * city: string,
47
+ * },
48
+ * };
49
+ *
50
+ */
51
+ export const generateTypeScriptType = (obj: ContentModule): string => {
52
+ let typeDefinition = ``;
53
+
54
+ const typeName = getTypeName(obj.id);
55
+
56
+ typeDefinition += `export type ${typeName} = {\n`;
57
+ typeDefinition += generateTypeScriptTypeContent(obj);
58
+ typeDefinition += '};\n\n';
59
+
60
+ return typeDefinition;
61
+ };
62
+
63
+ export const generateTypeScriptTypeContent = (obj: Content): string => {
64
+ let typeDefinition = ``;
65
+
66
+ for (const [key, value] of Object.entries(obj)) {
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ const nodeType: NodeType | undefined = (value as TypedNode).nodeType;
69
+ type ValueKey = keyof typeof value;
70
+
71
+ if (
72
+ // Check if the value is a typed node
73
+ typeof value === 'object' &&
74
+ nodeType === NodeType.Translation
75
+ ) {
76
+ const tsType =
77
+ typeof value?.[internationalization.defaultLocale as ValueKey];
78
+ typeDefinition += ` ${key}: ${tsType},\n`;
79
+ } else if (
80
+ // Check if the value is a typed node
81
+ typeof value === 'object' &&
82
+ nodeType === NodeType.Enumeration
83
+ ) {
84
+ const tsType =
85
+ typeof value?.[internationalization.defaultLocale as ValueKey];
86
+
87
+ typeDefinition += ` ${key}: (quantity: number) => ${tsType},\n`;
88
+ } else if (
89
+ // Check if the value is a nested object
90
+ typeof value === 'object' &&
91
+ !Array.isArray(value)
92
+ ) {
93
+ // Nested object, recurse
94
+ const nestedType = generateTypeScriptTypeContent(value as Content);
95
+ typeDefinition += ` ${key}: {${nestedType}},\n`;
96
+ } else if (
97
+ // Check if the value is an array
98
+ Array.isArray(value)
99
+ ) {
100
+ // Array handling (simplified, assumes non-empty arrays with uniform type)
101
+ const arrayType = typeof value[0];
102
+ typeDefinition += ` ${key}: ${arrayType}[],\n`;
103
+ } else if (
104
+ // Check if the value is an 'id'
105
+ typeof value === 'string' &&
106
+ key === 'id'
107
+ ) {
108
+ // Special handling for 'id' field
109
+ const tsType = `"${value}"`;
110
+ typeDefinition += ` ${key}: ${tsType},\n`;
111
+ } else {
112
+ // Primitive type
113
+ const tsType = typeof value;
114
+ typeDefinition += ` ${key}: ${tsType},\n`;
115
+ }
116
+ }
117
+
118
+ return typeDefinition;
119
+ };
120
+
121
+ /**
122
+ * This function generates a TypeScript type definition from a JSON object
123
+ */
124
+ export const createTypes = (dictionariesPaths: string[]): string[] => {
125
+ const resultTypesPaths: string[] = [];
126
+
127
+ // Create type folders if they don't exist
128
+ if (!existsSync(typesDir)) {
129
+ mkdirSync(typesDir, { recursive: true });
130
+ }
131
+
132
+ for (const dictionaryPath of dictionariesPaths) {
133
+ const contentModule: ContentModule = requireFunction(dictionaryPath);
134
+ const dictionaryName: string = contentModule.id;
135
+ const typeDefinition: string = generateTypeScriptType(contentModule);
136
+
137
+ const outputPath = resolve(typesDir, `${dictionaryName}.d.ts`);
138
+
139
+ writeFileSync(outputPath, typeDefinition);
140
+
141
+ resultTypesPaths.push(outputPath);
142
+ }
143
+
144
+ return resultTypesPaths;
145
+ };
@@ -0,0 +1,2 @@
1
+ export * from './createModuleAugmentation';
2
+ export * from './createType';
@@ -0,0 +1,60 @@
1
+ import type { Content, ContentModule } from '@intlayer/core';
2
+
3
+ /**
4
+ *
5
+ * This function extracts all nested objects with an 'id' field from the input object and returns them as an array
6
+ *
7
+ * Example:
8
+ *
9
+ * const input = {
10
+ * id: '1',
11
+ * name: 'John Doe',
12
+ * address: {
13
+ * id: '2',
14
+ * street: '123 Main St',
15
+ * city: 'Springfield',
16
+ * state: 'IL'
17
+ * },
18
+ * };
19
+ * const result = extractObjectsWithId(input);
20
+ * console.log(result);
21
+ *
22
+ * Output:
23
+ *
24
+ * [{
25
+ * id: '1',
26
+ * name: 'John Doe',
27
+ * address: {
28
+ * id: '2',
29
+ * street: '123 Main St',
30
+ * city: 'Springfield',
31
+ * state: 'IL'
32
+ * }
33
+ * },
34
+ * {
35
+ * id: '2',
36
+ * street: '123 Main St',
37
+ * city: 'Springfield',
38
+ * state: 'IL'
39
+ * }]
40
+ *
41
+ */
42
+ export const extractObjectsWithId = (input: ContentModule): ContentModule[] => {
43
+ // Function to recursively search and extract nested objects with an 'id'
44
+ const search = (obj: Content, results: ContentModule[]): void => {
45
+ if (obj && typeof obj === 'object') {
46
+ if (Object.prototype.hasOwnProperty.call(obj, 'id')) {
47
+ results.push(obj as ContentModule);
48
+ }
49
+ for (const key of Object.keys(obj)) {
50
+ if (typeof obj[key] === 'object') {
51
+ search(obj[key] as Content, results);
52
+ }
53
+ }
54
+ }
55
+ };
56
+
57
+ const results: ContentModule[] = [];
58
+ search(input, results);
59
+ return results;
60
+ };
@@ -0,0 +1,3 @@
1
+ export * from './extractNestedJSON';
2
+ export * from './processModule';
3
+ export * from './transpileContentDeclaration';