watch-lang.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. const fs = require('fs');
  2. const path = require('path');
  3. const {spawn, execSync} = require('child_process');
  4. const LANG_FILE_PATH = path.join(__dirname, 'src', 'lang.ts');
  5. const LANG_SIGN_FILE_PATH = path.join(__dirname, 'src', 'langSign.ts');
  6. const ENV_LOCAL_FILE_PATH = path.join(__dirname, '.env.local');
  7. const npmCmd = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';
  8. // Function to read current version from App.ts
  9. const getCurrentVersion = () => {
  10. try {
  11. const appContent = fs.readFileSync(ENV_LOCAL_FILE_PATH, 'utf8');
  12. const match = appContent.match(/VITE_LANG_PACK_LOCAL_VERSION=(\d+)/);
  13. return match ? parseInt(match[1]) : 0;
  14. } catch(error) {
  15. console.error('❌ Error reading App.ts:', error.message);
  16. return 0;
  17. }
  18. };
  19. // Function to update version in App.ts
  20. const updateVersion = (newVersion) => {
  21. try {
  22. let appContent = fs.readFileSync(ENV_LOCAL_FILE_PATH, 'utf8');
  23. appContent = appContent.replace(
  24. /(VITE_LANG_PACK_LOCAL_VERSION=)\d+/,
  25. `$1${newVersion}`
  26. );
  27. fs.writeFileSync(ENV_LOCAL_FILE_PATH, appContent, 'utf8');
  28. console.log(`✅ Version updated to ${newVersion}`);
  29. execSync(`${npmCmd} run format-lang`);
  30. } catch(error) {
  31. console.error('❌ Error updating App.ts:', error.message);
  32. }
  33. };
  34. // Function to get file hash
  35. const getFileHash = (filePath) => {
  36. try {
  37. const stats = fs.statSync(filePath);
  38. return `${stats.mtime.getTime()}_${stats.size}`;
  39. } catch(error) {
  40. return null;
  41. }
  42. };
  43. // Function to handle file change
  44. const handleFileChange = (filePath, fileName, lastHash, currentVersion, isUpdating) => {
  45. if(isUpdating.value) return; // Prevent multiple updates
  46. const currentHash = getFileHash(filePath);
  47. if(currentHash && currentHash !== lastHash.value) {
  48. console.log(`📝 Changes detected in ${fileName}`);
  49. isUpdating.value = true;
  50. currentVersion.value++;
  51. updateVersion(currentVersion.value);
  52. lastHash.value = currentHash;
  53. // Reset updating flag after a delay to prevent immediate re-triggering
  54. setTimeout(() => {
  55. isUpdating.value = false;
  56. }, 200);
  57. }
  58. };
  59. // Function to check if files exist
  60. const checkFilesExist = (files) => {
  61. for(const {path, name} of files) {
  62. if(!fs.existsSync(path)) {
  63. console.error(`❌ File ${path} not found!`);
  64. return false;
  65. }
  66. }
  67. return true;
  68. };
  69. // Main watching function using fs.watch
  70. const watchLangFile = () => {
  71. const files = [
  72. {path: LANG_FILE_PATH, name: 'lang.ts'},
  73. {path: LANG_SIGN_FILE_PATH, name: 'langSign.ts'}
  74. ];
  75. console.log('🔍 Watching for changes in lang files...');
  76. console.log(`📁 Files: ${files.map(f => f.path).join(', ')}`);
  77. const lastHashes = files.map(f => ({value: getFileHash(f.path)}));
  78. const currentVersion = {value: getCurrentVersion()};
  79. const isUpdating = {value: false};
  80. console.log(`📊 Current version: ${currentVersion.value}`);
  81. // Check if files exist
  82. if(
  83. !checkFilesExist(files.concat([{path: ENV_LOCAL_FILE_PATH, name: '.env.local'}]))
  84. ) {
  85. console.error('❌ Files not found!');
  86. return;
  87. }
  88. // Create watchers for each file
  89. const watchers = files.map((file, index) => {
  90. return fs.watch(file.path, (eventType, filename) => {
  91. if(eventType === 'change') {
  92. // Small delay to complete file writing
  93. setTimeout(() => {
  94. handleFileChange(file.path, file.name, lastHashes[index], currentVersion, isUpdating);
  95. }, 100);
  96. }
  97. });
  98. });
  99. // Error handling
  100. watchers.forEach((watcher, index) => {
  101. watcher.on('error', (error) => {
  102. console.error(`❌ File watching error (${files[index].name}):`, error.message);
  103. });
  104. });
  105. console.log('✅ Watching started. Press Ctrl+C to stop.');
  106. // Process termination handling
  107. const cleanup = () => {
  108. console.log('\n🛑 Stopping watch...');
  109. watchers.forEach(watcher => watcher.close());
  110. process.exit(0);
  111. };
  112. process.on('SIGINT', cleanup);
  113. process.on('SIGTERM', cleanup);
  114. };
  115. // Alternative function with interval (for cases when fs.watch doesn't work)
  116. const watchLangFileWithInterval = () => {
  117. const files = [
  118. {path: LANG_FILE_PATH, name: 'lang.ts'},
  119. {path: LANG_SIGN_FILE_PATH, name: 'langSign.ts'}
  120. ];
  121. console.log('🔍 Watching for changes in lang files (interval mode)...');
  122. console.log(`📁 Files: ${files.map(f => f.path).join(', ')}`);
  123. const lastHashes = files.map(f => ({value: getFileHash(f.path)}));
  124. const currentVersion = {value: getCurrentVersion()};
  125. console.log(`📊 Current version: ${currentVersion.value}`);
  126. // Check if files exist
  127. if(
  128. !checkFilesExist(files.concat([{path: ENV_LOCAL_FILE_PATH, name: '.env.local'}]))
  129. ) {
  130. return;
  131. }
  132. const isUpdating = {value: false};
  133. const interval = setInterval(() => {
  134. files.forEach((file, index) => {
  135. handleFileChange(file.path, file.name, lastHashes[index], currentVersion, isUpdating);
  136. });
  137. }, 1000);
  138. console.log('✅ Watching started. Press Ctrl+C to stop.');
  139. // Process termination handling
  140. const cleanup = () => {
  141. console.log('\n🛑 Stopping watch...');
  142. clearInterval(interval);
  143. process.exit(0);
  144. };
  145. process.on('SIGINT', cleanup);
  146. process.on('SIGTERM', cleanup);
  147. };
  148. // Start watching
  149. if(require.main === module) {
  150. // Try to use fs.watch, if it doesn't work - switch to interval mode
  151. try {
  152. watchLangFile();
  153. } catch(error) {
  154. console.log('⚠️ fs.watch unavailable, switching to interval mode...');
  155. watchLangFileWithInterval();
  156. }
  157. }
  158. module.exports = {
  159. watchLangFile,
  160. watchLangFileWithInterval,
  161. getCurrentVersion,
  162. updateVersion
  163. };