@intlayer/engine 9.5.6 → 9.5.7

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 (130) hide show
  1. package/dist/cjs/_virtual/_utils_asset.cjs +1 -1
  2. package/dist/cjs/build.cjs +4 -4
  3. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +2 -2
  4. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +3 -3
  5. package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +1 -1
  6. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +3 -3
  7. package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +2 -2
  8. package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs +2 -2
  9. package/dist/cjs/cleanOutputDir.cjs +1 -1
  10. package/dist/cjs/cleanRemovedContentDeclaration.cjs +1 -1
  11. package/dist/cjs/cli.cjs +3 -3
  12. package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +1 -1
  13. package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs +2 -2
  14. package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs +2 -2
  15. package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs +2 -2
  16. package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs +2 -2
  17. package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs +2 -2
  18. package/dist/cjs/createType/createModuleAugmentation.cjs +3 -3
  19. package/dist/cjs/createType/createType.cjs +1 -1
  20. package/dist/cjs/docReview/index.cjs +5 -5
  21. package/dist/cjs/docReview/pipeline.cjs +4 -4
  22. package/dist/cjs/fetchDistantDictionaries.cjs +1 -1
  23. package/dist/cjs/handleContentDeclarationFileChange.cjs +2 -2
  24. package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +1 -1
  25. package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +1 -1
  26. package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +1 -1
  27. package/dist/cjs/init/utils/fileSystem.cjs +1 -1
  28. package/dist/cjs/init/utils/githubActions.cjs +1 -1
  29. package/dist/cjs/init/utils/packageManager.cjs +1 -1
  30. package/dist/cjs/initConfig/index.cjs +1 -1
  31. package/dist/cjs/installLSP.cjs +1 -1
  32. package/dist/cjs/installMCP/installMCP.cjs +1 -1
  33. package/dist/cjs/installSkills/index.cjs +1 -1
  34. package/dist/cjs/listDictionariesPath.cjs +1 -1
  35. package/dist/cjs/listGitFiles.cjs +1 -1
  36. package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -2
  37. package/dist/cjs/loadDictionaries/index.cjs +1 -1
  38. package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +2 -2
  39. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +1 -1
  40. package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs +1 -1
  41. package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs +1 -1
  42. package/dist/cjs/logConfigDetails.cjs +1 -1
  43. package/dist/cjs/prepareIntlayer.cjs +4 -4
  44. package/dist/cjs/scan/index.cjs +1 -1
  45. package/dist/cjs/scan/scanWebsite.cjs +1 -1
  46. package/dist/cjs/syncPluginKit/createFileAdapter.cjs +1 -1
  47. package/dist/cjs/syncPluginKit/index.cjs +1 -1
  48. package/dist/cjs/utils/buildComponentFilesList.cjs +1 -1
  49. package/dist/cjs/utils/contentWatcherLock.cjs +2 -2
  50. package/dist/cjs/utils/index.cjs +4 -4
  51. package/dist/cjs/utils/readDictionariesFromDisk.cjs +1 -1
  52. package/dist/cjs/utils/runOnce.cjs +67 -16
  53. package/dist/cjs/utils/runOnce.cjs.map +1 -1
  54. package/dist/cjs/utils/runParallel/pidTree.cjs +1 -1
  55. package/dist/cjs/utils/withFileLock.cjs +1 -1
  56. package/dist/cjs/watcher.cjs +6 -6
  57. package/dist/cjs/writeConfiguration/index.cjs +1 -1
  58. package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs +2 -2
  59. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +1 -1
  60. package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +4 -4
  61. package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +3 -3
  62. package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +1 -1
  63. package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +1 -1
  64. package/dist/cjs/writeFileIfChanged.cjs +1 -1
  65. package/dist/esm/_virtual/_utils_asset.mjs +1 -1
  66. package/dist/esm/build.mjs +4 -4
  67. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +2 -2
  68. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +3 -3
  69. package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +1 -1
  70. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +3 -3
  71. package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +2 -2
  72. package/dist/esm/buildIntlayerDictionary/writeUnmergedDictionary.mjs +2 -2
  73. package/dist/esm/cleanOutputDir.mjs +1 -1
  74. package/dist/esm/cleanRemovedContentDeclaration.mjs +1 -1
  75. package/dist/esm/cli.mjs +3 -3
  76. package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +1 -1
  77. package/dist/esm/createDictionaryEntryPoint/getBuiltDictionariesPath.mjs +2 -2
  78. package/dist/esm/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.mjs +2 -2
  79. package/dist/esm/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.mjs +2 -2
  80. package/dist/esm/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.mjs +2 -2
  81. package/dist/esm/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.mjs +2 -2
  82. package/dist/esm/createType/createModuleAugmentation.mjs +3 -3
  83. package/dist/esm/createType/createType.mjs +1 -1
  84. package/dist/esm/docReview/index.mjs +5 -5
  85. package/dist/esm/docReview/pipeline.mjs +4 -4
  86. package/dist/esm/fetchDistantDictionaries.mjs +1 -1
  87. package/dist/esm/handleContentDeclarationFileChange.mjs +2 -2
  88. package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +1 -1
  89. package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +1 -1
  90. package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +1 -1
  91. package/dist/esm/init/utils/fileSystem.mjs +1 -1
  92. package/dist/esm/init/utils/githubActions.mjs +1 -1
  93. package/dist/esm/init/utils/packageManager.mjs +1 -1
  94. package/dist/esm/initConfig/index.mjs +1 -1
  95. package/dist/esm/installLSP.mjs +1 -1
  96. package/dist/esm/installMCP/installMCP.mjs +1 -1
  97. package/dist/esm/installSkills/index.mjs +1 -1
  98. package/dist/esm/listDictionariesPath.mjs +1 -1
  99. package/dist/esm/listGitFiles.mjs +1 -1
  100. package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -2
  101. package/dist/esm/loadDictionaries/index.mjs +1 -1
  102. package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +2 -2
  103. package/dist/esm/loadDictionaries/loadDictionaries.mjs +1 -1
  104. package/dist/esm/loadDictionaries/loadLocalDictionaries.mjs +1 -1
  105. package/dist/esm/loadDictionaries/loadMarkdownContentDeclaration.mjs +1 -1
  106. package/dist/esm/logConfigDetails.mjs +1 -1
  107. package/dist/esm/prepareIntlayer.mjs +4 -4
  108. package/dist/esm/scan/index.mjs +1 -1
  109. package/dist/esm/scan/scanWebsite.mjs +1 -1
  110. package/dist/esm/syncPluginKit/createFileAdapter.mjs +1 -1
  111. package/dist/esm/syncPluginKit/index.mjs +1 -1
  112. package/dist/esm/utils/buildComponentFilesList.mjs +1 -1
  113. package/dist/esm/utils/contentWatcherLock.mjs +2 -2
  114. package/dist/esm/utils/index.mjs +4 -4
  115. package/dist/esm/utils/readDictionariesFromDisk.mjs +1 -1
  116. package/dist/esm/utils/runOnce.mjs +68 -17
  117. package/dist/esm/utils/runOnce.mjs.map +1 -1
  118. package/dist/esm/utils/runParallel/pidTree.mjs +1 -1
  119. package/dist/esm/utils/withFileLock.mjs +1 -1
  120. package/dist/esm/watcher.mjs +6 -6
  121. package/dist/esm/writeConfiguration/index.mjs +1 -1
  122. package/dist/esm/writeContentDeclaration/processContentDeclarationContent.mjs +2 -2
  123. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +1 -1
  124. package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +4 -4
  125. package/dist/esm/writeContentDeclaration/writeJSFile.mjs +3 -3
  126. package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +1 -1
  127. package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +1 -1
  128. package/dist/esm/writeFileIfChanged.mjs +1 -1
  129. package/dist/types/utils/runOnce.d.ts.map +1 -1
  130. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_scan_parseHtml = require('./parseHtml.cjs');
3
2
  const require_scan_calculateScore = require('./calculateScore.cjs');
3
+ const require_scan_parseHtml = require('./parseHtml.cjs');
4
4
  const require_scan_analyzeBundleContent = require('./analyzeBundleContent.cjs');
5
5
  const require_scan_checks = require('./checks.cjs');
6
6
  const require_scan_scanWebsite = require('./scanWebsite.cjs');
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_scan_parseHtml = require('./parseHtml.cjs');
3
2
  const require_scan_calculateScore = require('./calculateScore.cjs');
3
+ const require_scan_parseHtml = require('./parseHtml.cjs');
4
4
  const require_scan_checks = require('./checks.cjs');
5
5
  let _intlayer_config_colors = require("@intlayer/config/colors");
6
6
  let _intlayer_config_logger = require("@intlayer/config/logger");
@@ -3,11 +3,11 @@ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_writeFileIfChanged = require('../writeFileIfChanged.cjs');
4
4
  const require_syncPluginKit_extractKeyAndLocaleFromPath = require('./extractKeyAndLocaleFromPath.cjs');
5
5
  const require_syncPluginKit_filePathPatternHelpers = require('./filePathPatternHelpers.cjs');
6
- let node_fs_promises = require("node:fs/promises");
7
6
  let node_path = require("node:path");
8
7
  let _intlayer_config_utils = require("@intlayer/config/utils");
9
8
  let fast_glob = require("fast-glob");
10
9
  fast_glob = require_runtime.__toESM(fast_glob);
10
+ let node_fs_promises = require("node:fs/promises");
11
11
 
12
12
  //#region src/syncPluginKit/createFileAdapter.ts
13
13
  /**
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_syncPluginKit_createSyncPlugin = require('./createSyncPlugin.cjs');
3
2
  const require_syncPluginKit_extractKeyAndLocaleFromPath = require('./extractKeyAndLocaleFromPath.cjs');
4
3
  const require_syncPluginKit_filePathPatternHelpers = require('./filePathPatternHelpers.cjs');
5
4
  const require_syncPluginKit_createFileAdapter = require('./createFileAdapter.cjs');
5
+ const require_syncPluginKit_createSyncPlugin = require('./createSyncPlugin.cjs');
6
6
 
7
7
  exports.buildFilePathPatternContext = require_syncPluginKit_filePathPatternHelpers.buildFilePathPatternContext;
8
8
  exports.createFileAdapter = require_syncPluginKit_createFileAdapter.createFileAdapter;
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  let node_path = require("node:path");
4
- let _intlayer_config_utils = require("@intlayer/config/utils");
5
4
  let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
5
+ let _intlayer_config_utils = require("@intlayer/config/utils");
6
6
  let fast_glob = require("fast-glob");
7
7
  fast_glob = require_runtime.__toESM(fast_glob);
8
8
 
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
- let node_fs = require("node:fs");
4
- let node_fs_promises = require("node:fs/promises");
5
3
  let node_path = require("node:path");
6
4
  let _intlayer_config_colors = require("@intlayer/config/colors");
7
5
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
8
6
  let _intlayer_config_logger = require("@intlayer/config/logger");
7
+ let node_fs = require("node:fs");
8
+ let node_fs_promises = require("node:fs/promises");
9
9
 
10
10
  //#region src/utils/contentWatcherLock.ts
11
11
  /**
@@ -1,8 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_utils_pLimit = require('./pLimit.cjs');
3
- const require_utils_parallelize = require('./parallelize.cjs');
4
- const require_utils_getPathHash = require('./getPathHash.cjs');
5
- const require_utils_formatter = require('./formatter.cjs');
6
2
  const require_utils_autoDecorateContent = require('./autoDecorateContent.cjs');
7
3
  const require_utils_buildComponentFilesList = require('./buildComponentFilesList.cjs');
8
4
  const require_utils_chunkArray = require('./chunkArray.cjs');
@@ -10,9 +6,13 @@ const require_utils_splitTextByLine = require('./splitTextByLine.cjs');
10
6
  const require_utils_getChunk = require('./getChunk.cjs');
11
7
  const require_utils_chunkJSON = require('./chunkJSON.cjs');
12
8
  const require_utils_contentWatcherLock = require('./contentWatcherLock.cjs');
9
+ const require_utils_formatter = require('./formatter.cjs');
13
10
  const require_utils_getContentExtension = require('./getContentExtension.cjs');
14
11
  const require_utils_getFormatFromExtension = require('./getFormatFromExtension.cjs');
12
+ const require_utils_getPathHash = require('./getPathHash.cjs');
15
13
  const require_utils_mergeChunks = require('./mergeChunks.cjs');
14
+ const require_utils_pLimit = require('./pLimit.cjs');
15
+ const require_utils_parallelize = require('./parallelize.cjs');
16
16
  const require_utils_parallelizeGlobal = require('./parallelizeGlobal.cjs');
17
17
  const require_utils_parseContentDeclarationFileName = require('./parseContentDeclarationFileName.cjs');
18
18
  const require_utils_reduceObjectFormat = require('./reduceObjectFormat.cjs');
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- let node_fs = require("node:fs");
3
2
  let node_path = require("node:path");
3
+ let node_fs = require("node:fs");
4
4
 
5
5
  //#region src/utils/readDictionariesFromDisk.ts
6
6
  /**
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ let node_path = require("node:path");
3
4
  let node_fs = require("node:fs");
4
5
  let node_fs_promises = require("node:fs/promises");
5
- let node_path = require("node:path");
6
6
  let _intlayer_core_package_json = require("@intlayer/core/package.json");
7
7
  _intlayer_core_package_json = require_runtime.__toESM(_intlayer_core_package_json);
8
8
 
@@ -23,6 +23,12 @@ process.on("exit", () => {
23
23
  for (const sentinelFilePath of ownedSentinelFilePaths) try {
24
24
  (0, node_fs.rmSync)(sentinelFilePath, { force: true });
25
25
  } catch {}
26
+ for (const mutexDirPath of ownedMutexDirPaths) try {
27
+ (0, node_fs.rmSync)(mutexDirPath, {
28
+ recursive: true,
29
+ force: true
30
+ });
31
+ } catch {}
26
32
  });
27
33
  /**
28
34
  * Reads the sentinel file, returning `undefined` when it does not exist or
@@ -103,6 +109,53 @@ const removeSentinel = async (sentinelFilePath) => {
103
109
  await (0, node_fs_promises.unlink)(sentinelFilePath);
104
110
  } catch {}
105
111
  };
112
+ /** Delay between two attempts to enter the sentinel critical section. */
113
+ const MUTEX_POLL_INTERVAL_MS = 10;
114
+ /**
115
+ * A critical-section mutex older than this was left behind by a process that
116
+ * died while holding it, and can be taken over.
117
+ */
118
+ const MUTEX_STALE_MS = 1e4;
119
+ /** Mutex directories owned by this process, released on exit like sentinels. */
120
+ const ownedMutexDirPaths = /* @__PURE__ */ new Set();
121
+ /**
122
+ * Serializes the "read the sentinel, decide, replace it" sequence across
123
+ * processes so it behaves as a compare-and-swap.
124
+ *
125
+ * Without it, two contenders reading the same stale sentinel could both remove
126
+ * it, and the slower one would delete the `running` sentinel the faster one
127
+ * had just created — letting two callbacks run at once. A directory is used
128
+ * because `mkdir` is atomic on every platform.
129
+ */
130
+ const withSentinelMutex = async (sentinelFilePath, criticalSection) => {
131
+ const mutexDirPath = `${sentinelFilePath}.mutex`;
132
+ while (true) try {
133
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(sentinelFilePath), { recursive: true });
134
+ await (0, node_fs_promises.mkdir)(mutexDirPath);
135
+ break;
136
+ } catch (error) {
137
+ const code = error.code;
138
+ if (code === "ENOENT") continue;
139
+ if (code !== "EEXIST") throw error;
140
+ try {
141
+ const mutexStats = await (0, node_fs_promises.stat)(mutexDirPath);
142
+ if (Date.now() - mutexStats.mtime.getTime() > MUTEX_STALE_MS) {
143
+ await (0, node_fs_promises.rmdir)(mutexDirPath).catch(() => {});
144
+ continue;
145
+ }
146
+ } catch {
147
+ continue;
148
+ }
149
+ await delay(MUTEX_POLL_INTERVAL_MS);
150
+ }
151
+ ownedMutexDirPaths.add(mutexDirPath);
152
+ try {
153
+ return await criticalSection();
154
+ } finally {
155
+ ownedMutexDirPaths.delete(mutexDirPath);
156
+ await (0, node_fs_promises.rmdir)(mutexDirPath).catch(() => {});
157
+ }
158
+ };
106
159
  /**
107
160
  * Ensures a callback function runs only once within a specified time window across multiple processes.
108
161
  * Uses a sentinel file to coordinate execution and prevent duplicate work.
@@ -138,24 +191,22 @@ const runOnce = async (sentinelFilePath, callback, options) => {
138
191
  const currentTimestamp = Date.now();
139
192
  const waitDeadline = currentTimestamp + lockWaitTimeoutMs;
140
193
  while (true) {
141
- const sentinelState = await readSentinelState(sentinelFilePath);
142
- if (sentinelState) {
143
- const sentinelAge = Date.now() - sentinelState.mtimeMs;
144
- if (sentinelState.status === "running") {
145
- if (!(sentinelAge > lockWaitTimeoutMs || !isOwnerProcessAlive(sentinelState.pid)) && Date.now() < waitDeadline) {
146
- await delay(LOCK_POLL_INTERVAL_MS);
147
- continue;
148
- }
194
+ const outcome = await withSentinelMutex(sentinelFilePath, async () => {
195
+ const sentinelState = await readSentinelState(sentinelFilePath);
196
+ if (sentinelState) {
197
+ const sentinelAge = Date.now() - sentinelState.mtimeMs;
198
+ if (sentinelState.status === "running") {
199
+ if (!(sentinelAge > lockWaitTimeoutMs || !isOwnerProcessAlive(sentinelState.pid)) && Date.now() < waitDeadline) return "wait";
200
+ } else if (!forceRun && sentinelAge <= cacheTimeoutMs && sentinelState.version === _intlayer_core_package_json.default.version) return "cached";
149
201
  await removeSentinel(sentinelFilePath);
150
- continue;
151
- }
152
- if (!forceRun && sentinelAge <= cacheTimeoutMs && sentinelState.version === _intlayer_core_package_json.default.version) {
153
- await onIsCached?.();
154
- return;
155
202
  }
156
- await removeSentinel(sentinelFilePath);
203
+ return await acquireSentinel(sentinelFilePath, currentTimestamp) ? "acquired" : "wait";
204
+ });
205
+ if (outcome === "cached") {
206
+ await onIsCached?.();
207
+ return;
157
208
  }
158
- if (await acquireSentinel(sentinelFilePath, currentTimestamp)) break;
209
+ if (outcome === "acquired") break;
159
210
  await delay(LOCK_POLL_INTERVAL_MS);
160
211
  }
161
212
  ownedSentinelFilePaths.add(sentinelFilePath);
@@ -1 +1 @@
1
- {"version":3,"file":"runOnce.cjs","names":["stat","readFile","packageJson","mkdir","dirname","writeFile","unlink"],"sources":["../../../src/utils/runOnce.ts"],"sourcesContent":["import { rmSync } from 'node:fs';\nimport { mkdir, readFile, stat, unlink, writeFile } from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport packageJson from '@intlayer/core/package.json' with { type: 'json' };\n\n/**\n * Lifecycle of the run described by a sentinel file.\n *\n * - `running` — a process owns the sentinel and its callback is still in flight.\n * Other processes must wait instead of starting a concurrent run.\n * - `done` — the callback completed; the sentinel is now a plain cache marker.\n */\ntype SentinelStatus = 'running' | 'done';\n\ntype SentinelData = {\n version: string;\n timestamp: number;\n status: SentinelStatus;\n /** PID of the process that owns the sentinel, used to detect abandoned locks. */\n pid: number;\n};\n\n/** Sentinel state as read from disk, enriched with the file's modification time. */\ntype SentinelState = SentinelData & { mtimeMs: number };\n\n/**\n * Context handed to the callback so it can interact with the lock it runs under.\n */\nexport type RunOnceContext = {\n /**\n * Re-create the sentinel file after an operation that may have deleted it —\n * typically cleaning the output directory, which wipes the cache directory the\n * sentinel lives in. Without this, concurrent processes would see no lock and\n * start a competing run while this one is still writing.\n */\n renewLock: () => Promise<void>;\n};\n\ntype RunOnceOptions = {\n /**\n * The function to execute when the sentinel is not found or is older than the cache timeout.\n */\n onIsCached?: () => void | Promise<void>;\n /**\n * The time window in milliseconds during which the sentinel is considered valid.\n *\n * @default 60000 = 1 minute\n */\n cacheTimeoutMs?: number;\n /**\n * If true, the callback will always run. If undefined, the callback will run only if the sentinel is older than the cache timeout.\n *\n * @default false\n */\n forceRun?: boolean;\n /**\n * How long to wait for another process to release the sentinel before\n * considering its run abandoned and taking the lock over.\n *\n * @default 300000 = 5 minutes\n */\n lockWaitTimeoutMs?: number;\n};\n\nconst DEFAULT_RUN_ONCE_OPTIONS = {\n cacheTimeoutMs: 60 * 1000, // 1 minute in milliseconds,\n lockWaitTimeoutMs: 5 * 60 * 1000, // 5 minutes in milliseconds\n} satisfies RunOnceOptions;\n\n/** Delay between two reads of a sentinel owned by another process. */\nconst LOCK_POLL_INTERVAL_MS = 50;\n\nconst delay = (durationMs: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, durationMs));\n\n/**\n * Sentinels owned by this process, released synchronously on exit so a crash or\n * a Ctrl-C never leaves a `running` lock that would stall the next run.\n */\nconst ownedSentinelFilePaths = new Set<string>();\n\nprocess.on('exit', () => {\n for (const sentinelFilePath of ownedSentinelFilePaths) {\n try {\n rmSync(sentinelFilePath, { force: true });\n } catch {}\n }\n});\n\n/**\n * Reads the sentinel file, returning `undefined` when it does not exist or\n * cannot be parsed.\n *\n * Sentinels written by older versions carry no `status`; they always describe a\n * finished run, so they are reported as `done`.\n */\nconst readSentinelState = async (\n sentinelFilePath: string\n): Promise<SentinelState | undefined> => {\n try {\n const [sentinelStats, raw] = await Promise.all([\n stat(sentinelFilePath),\n readFile(sentinelFilePath, 'utf8'),\n ]);\n\n const parsed = JSON.parse(raw) as Partial<SentinelData>;\n\n return {\n version: parsed.version ?? '',\n timestamp: parsed.timestamp ?? 0,\n status: parsed.status ?? 'done',\n pid: parsed.pid ?? 0,\n mtimeMs: sentinelStats.mtime.getTime(),\n };\n } catch {\n return undefined;\n }\n};\n\n/**\n * Whether the process that wrote the sentinel is still alive. An unknown PID\n * (legacy sentinel) is assumed alive so the staleness timeout stays the only\n * way to reclaim it.\n */\nconst isOwnerProcessAlive = (pid: number): boolean => {\n if (!pid || pid === process.pid) return true;\n\n try {\n // Signal 0 performs an existence check without delivering a signal.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n // EPERM means the process exists but belongs to another user.\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n};\n\nconst serializeSentinel = (timestamp: number, status: SentinelStatus): string =>\n JSON.stringify({\n version: packageJson.version,\n timestamp,\n status,\n pid: process.pid,\n } satisfies SentinelData);\n\n/**\n * Attempts to take ownership of the sentinel.\n *\n * `wx` makes the creation atomic, so exactly one process can win even when\n * several start at the same moment.\n *\n * @returns `true` when this process now owns the sentinel, `false` when another\n * process created it first.\n */\nconst acquireSentinel = async (\n sentinelFilePath: string,\n timestamp: number\n): Promise<boolean> => {\n const data = serializeSentinel(timestamp, 'running');\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n // Ensure the directory exists before writing the file\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n\n await writeFile(sentinelFilePath, data, { flag: 'wx' });\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n\n if (code === 'EEXIST') return false;\n // The directory was removed between the mkdir and the write (e.g. a\n // concurrent output-directory clean); retry once.\n if (code === 'ENOENT' && attempt === 0) continue;\n\n throw error;\n }\n }\n\n return false;\n};\n\n/**\n * Rewrites the sentinel owned by this process, overwriting any existing file.\n */\nconst writeOwnedSentinel = async (\n sentinelFilePath: string,\n timestamp: number,\n status: SentinelStatus\n): Promise<void> => {\n try {\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n await writeFile(sentinelFilePath, serializeSentinel(timestamp, status));\n } catch {}\n};\n\nconst removeSentinel = async (sentinelFilePath: string): Promise<void> => {\n try {\n await unlink(sentinelFilePath);\n } catch {}\n};\n\n/**\n * Ensures a callback function runs only once within a specified time window across multiple processes.\n * Uses a sentinel file to coordinate execution and prevent duplicate work.\n *\n * Processes that lose the race for the sentinel wait for the owner to finish\n * rather than running a competing copy of the callback — concurrent runs would\n * otherwise write to (and clean) the same output directory at the same time.\n *\n * @param sentinelFilePath - Path to the sentinel file used for coordination\n * @param callback - The function to execute (should be async)\n * @param options - The options for the runOnce function\n *\n * @example\n * ```typescript\n * await runOnce(\n * '/tmp/intlayer-sentinel',\n * async ({ renewLock }) => {\n * await cleanOutputDir(configuration); // may delete the sentinel\n * await renewLock();\n * await prepareIntlayer();\n * },\n * { cacheTimeoutMs: 30 * 1000 } // 30 seconds cache\n * );\n * ```\n *\n * @throws {Error} When there are unexpected filesystem errors\n */\nexport const runOnce = async (\n sentinelFilePath: string,\n callback: (context: RunOnceContext) => void | Promise<void>,\n options?: RunOnceOptions\n) => {\n const { onIsCached, cacheTimeoutMs, forceRun, lockWaitTimeoutMs } = {\n ...DEFAULT_RUN_ONCE_OPTIONS,\n ...(options ?? {}),\n };\n const currentTimestamp = Date.now();\n const waitDeadline = currentTimestamp + lockWaitTimeoutMs;\n\n // Acquisition loop: read the sentinel, then either return early (fresh cache),\n // wait for the current owner, or take the lock. Every branch either returns or\n // makes progress, so the loop always terminates.\n while (true) {\n const sentinelState = await readSentinelState(sentinelFilePath);\n\n if (sentinelState) {\n const sentinelAge = Date.now() - sentinelState.mtimeMs;\n\n if (sentinelState.status === 'running') {\n const isAbandoned =\n sentinelAge > lockWaitTimeoutMs ||\n !isOwnerProcessAlive(sentinelState.pid);\n\n if (!isAbandoned && Date.now() < waitDeadline) {\n await delay(LOCK_POLL_INTERVAL_MS);\n continue;\n }\n\n // The owner died or overran the timeout: reclaim the sentinel.\n await removeSentinel(sentinelFilePath);\n continue;\n }\n\n const isCacheValid =\n !forceRun &&\n sentinelAge <= cacheTimeoutMs &&\n sentinelState.version === packageJson.version;\n\n if (isCacheValid) {\n await onIsCached?.();\n return;\n }\n\n await removeSentinel(sentinelFilePath);\n }\n\n const hasAcquiredSentinel = await acquireSentinel(\n sentinelFilePath,\n currentTimestamp\n );\n\n if (hasAcquiredSentinel) break;\n\n // Another process won the race in the meantime: loop back and wait for it.\n // The delay also guarantees the loop yields, so a sentinel being repeatedly\n // created and removed can never turn into a busy wait.\n await delay(LOCK_POLL_INTERVAL_MS);\n }\n\n ownedSentinelFilePaths.add(sentinelFilePath);\n\n const renewLock = () =>\n writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'running');\n\n try {\n await callback({ renewLock });\n\n // Mark the run as finished, re-creating the sentinel if the callback\n // deleted it (e.g. by cleaning the output directory).\n await writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'done');\n } catch {\n await removeSentinel(sentinelFilePath); // Remove sentinel file if an error occurs\n } finally {\n ownedSentinelFilePaths.delete(sentinelFilePath);\n }\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"runOnce.cjs","names":["stat","readFile","packageJson","mkdir","dirname","writeFile","unlink","rmdir"],"sources":["../../../src/utils/runOnce.ts"],"sourcesContent":["import { rmSync } from 'node:fs';\nimport {\n mkdir,\n readFile,\n rmdir,\n stat,\n unlink,\n writeFile,\n} from 'node:fs/promises';\nimport { dirname } from 'node:path';\nimport packageJson from '@intlayer/core/package.json' with { type: 'json' };\n\n/**\n * Lifecycle of the run described by a sentinel file.\n *\n * - `running` — a process owns the sentinel and its callback is still in flight.\n * Other processes must wait instead of starting a concurrent run.\n * - `done` — the callback completed; the sentinel is now a plain cache marker.\n */\ntype SentinelStatus = 'running' | 'done';\n\ntype SentinelData = {\n version: string;\n timestamp: number;\n status: SentinelStatus;\n /** PID of the process that owns the sentinel, used to detect abandoned locks. */\n pid: number;\n};\n\n/** Sentinel state as read from disk, enriched with the file's modification time. */\ntype SentinelState = SentinelData & { mtimeMs: number };\n\n/**\n * Context handed to the callback so it can interact with the lock it runs under.\n */\nexport type RunOnceContext = {\n /**\n * Re-create the sentinel file after an operation that may have deleted it —\n * typically cleaning the output directory, which wipes the cache directory the\n * sentinel lives in. Without this, concurrent processes would see no lock and\n * start a competing run while this one is still writing.\n */\n renewLock: () => Promise<void>;\n};\n\ntype RunOnceOptions = {\n /**\n * The function to execute when the sentinel is not found or is older than the cache timeout.\n */\n onIsCached?: () => void | Promise<void>;\n /**\n * The time window in milliseconds during which the sentinel is considered valid.\n *\n * @default 60000 = 1 minute\n */\n cacheTimeoutMs?: number;\n /**\n * If true, the callback will always run. If undefined, the callback will run only if the sentinel is older than the cache timeout.\n *\n * @default false\n */\n forceRun?: boolean;\n /**\n * How long to wait for another process to release the sentinel before\n * considering its run abandoned and taking the lock over.\n *\n * @default 300000 = 5 minutes\n */\n lockWaitTimeoutMs?: number;\n};\n\nconst DEFAULT_RUN_ONCE_OPTIONS = {\n cacheTimeoutMs: 60 * 1000, // 1 minute in milliseconds,\n lockWaitTimeoutMs: 5 * 60 * 1000, // 5 minutes in milliseconds\n} satisfies RunOnceOptions;\n\n/** Delay between two reads of a sentinel owned by another process. */\nconst LOCK_POLL_INTERVAL_MS = 50;\n\nconst delay = (durationMs: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, durationMs));\n\n/**\n * Sentinels owned by this process, released synchronously on exit so a crash or\n * a Ctrl-C never leaves a `running` lock that would stall the next run.\n */\nconst ownedSentinelFilePaths = new Set<string>();\n\nprocess.on('exit', () => {\n for (const sentinelFilePath of ownedSentinelFilePaths) {\n try {\n rmSync(sentinelFilePath, { force: true });\n } catch {}\n }\n for (const mutexDirPath of ownedMutexDirPaths) {\n try {\n rmSync(mutexDirPath, { recursive: true, force: true });\n } catch {}\n }\n});\n\n/**\n * Reads the sentinel file, returning `undefined` when it does not exist or\n * cannot be parsed.\n *\n * Sentinels written by older versions carry no `status`; they always describe a\n * finished run, so they are reported as `done`.\n */\nconst readSentinelState = async (\n sentinelFilePath: string\n): Promise<SentinelState | undefined> => {\n try {\n const [sentinelStats, raw] = await Promise.all([\n stat(sentinelFilePath),\n readFile(sentinelFilePath, 'utf8'),\n ]);\n\n const parsed = JSON.parse(raw) as Partial<SentinelData>;\n\n return {\n version: parsed.version ?? '',\n timestamp: parsed.timestamp ?? 0,\n status: parsed.status ?? 'done',\n pid: parsed.pid ?? 0,\n mtimeMs: sentinelStats.mtime.getTime(),\n };\n } catch {\n return undefined;\n }\n};\n\n/**\n * Whether the process that wrote the sentinel is still alive. An unknown PID\n * (legacy sentinel) is assumed alive so the staleness timeout stays the only\n * way to reclaim it.\n */\nconst isOwnerProcessAlive = (pid: number): boolean => {\n if (!pid || pid === process.pid) return true;\n\n try {\n // Signal 0 performs an existence check without delivering a signal.\n process.kill(pid, 0);\n return true;\n } catch (error) {\n // EPERM means the process exists but belongs to another user.\n return (error as NodeJS.ErrnoException).code === 'EPERM';\n }\n};\n\nconst serializeSentinel = (timestamp: number, status: SentinelStatus): string =>\n JSON.stringify({\n version: packageJson.version,\n timestamp,\n status,\n pid: process.pid,\n } satisfies SentinelData);\n\n/**\n * Attempts to take ownership of the sentinel.\n *\n * `wx` makes the creation atomic, so exactly one process can win even when\n * several start at the same moment.\n *\n * @returns `true` when this process now owns the sentinel, `false` when another\n * process created it first.\n */\nconst acquireSentinel = async (\n sentinelFilePath: string,\n timestamp: number\n): Promise<boolean> => {\n const data = serializeSentinel(timestamp, 'running');\n\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n // Ensure the directory exists before writing the file\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n\n await writeFile(sentinelFilePath, data, { flag: 'wx' });\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n\n if (code === 'EEXIST') return false;\n // The directory was removed between the mkdir and the write (e.g. a\n // concurrent output-directory clean); retry once.\n if (code === 'ENOENT' && attempt === 0) continue;\n\n throw error;\n }\n }\n\n return false;\n};\n\n/**\n * Rewrites the sentinel owned by this process, overwriting any existing file.\n */\nconst writeOwnedSentinel = async (\n sentinelFilePath: string,\n timestamp: number,\n status: SentinelStatus\n): Promise<void> => {\n try {\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n await writeFile(sentinelFilePath, serializeSentinel(timestamp, status));\n } catch {}\n};\n\nconst removeSentinel = async (sentinelFilePath: string): Promise<void> => {\n try {\n await unlink(sentinelFilePath);\n } catch {}\n};\n\n/** Delay between two attempts to enter the sentinel critical section. */\nconst MUTEX_POLL_INTERVAL_MS = 10;\n\n/**\n * A critical-section mutex older than this was left behind by a process that\n * died while holding it, and can be taken over.\n */\nconst MUTEX_STALE_MS = 10 * 1000;\n\n/** Mutex directories owned by this process, released on exit like sentinels. */\nconst ownedMutexDirPaths = new Set<string>();\n\n/**\n * Serializes the \"read the sentinel, decide, replace it\" sequence across\n * processes so it behaves as a compare-and-swap.\n *\n * Without it, two contenders reading the same stale sentinel could both remove\n * it, and the slower one would delete the `running` sentinel the faster one\n * had just created — letting two callbacks run at once. A directory is used\n * because `mkdir` is atomic on every platform.\n */\nconst withSentinelMutex = async <TResult>(\n sentinelFilePath: string,\n criticalSection: () => Promise<TResult>\n): Promise<TResult> => {\n const mutexDirPath = `${sentinelFilePath}.mutex`;\n\n while (true) {\n try {\n await mkdir(dirname(sentinelFilePath), { recursive: true });\n // Non-recursive on purpose: `recursive` swallows EEXIST\n await mkdir(mutexDirPath);\n break;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n\n // The parent directory was removed between the two `mkdir` calls (e.g. a\n // concurrent output-directory clean): recreate it and retry.\n if (code === 'ENOENT') continue;\n if (code !== 'EEXIST') throw error;\n\n try {\n const mutexStats = await stat(mutexDirPath);\n\n if (Date.now() - mutexStats.mtime.getTime() > MUTEX_STALE_MS) {\n await rmdir(mutexDirPath).catch(() => {});\n continue;\n }\n } catch {\n // The holder released it in the meantime: retry right away\n continue;\n }\n\n await delay(MUTEX_POLL_INTERVAL_MS);\n }\n }\n\n ownedMutexDirPaths.add(mutexDirPath);\n\n try {\n return await criticalSection();\n } finally {\n ownedMutexDirPaths.delete(mutexDirPath);\n await rmdir(mutexDirPath).catch(() => {});\n }\n};\n\n/** Outcome of one pass through the sentinel critical section. */\ntype AcquisitionOutcome = 'acquired' | 'cached' | 'wait';\n\n/**\n * Ensures a callback function runs only once within a specified time window across multiple processes.\n * Uses a sentinel file to coordinate execution and prevent duplicate work.\n *\n * Processes that lose the race for the sentinel wait for the owner to finish\n * rather than running a competing copy of the callback — concurrent runs would\n * otherwise write to (and clean) the same output directory at the same time.\n *\n * @param sentinelFilePath - Path to the sentinel file used for coordination\n * @param callback - The function to execute (should be async)\n * @param options - The options for the runOnce function\n *\n * @example\n * ```typescript\n * await runOnce(\n * '/tmp/intlayer-sentinel',\n * async ({ renewLock }) => {\n * await cleanOutputDir(configuration); // may delete the sentinel\n * await renewLock();\n * await prepareIntlayer();\n * },\n * { cacheTimeoutMs: 30 * 1000 } // 30 seconds cache\n * );\n * ```\n *\n * @throws {Error} When there are unexpected filesystem errors\n */\nexport const runOnce = async (\n sentinelFilePath: string,\n callback: (context: RunOnceContext) => void | Promise<void>,\n options?: RunOnceOptions\n) => {\n const { onIsCached, cacheTimeoutMs, forceRun, lockWaitTimeoutMs } = {\n ...DEFAULT_RUN_ONCE_OPTIONS,\n ...(options ?? {}),\n };\n const currentTimestamp = Date.now();\n const waitDeadline = currentTimestamp + lockWaitTimeoutMs;\n\n // Acquisition loop: read the sentinel, then either return early (fresh cache),\n // wait for the current owner, or take the lock. Every branch either returns or\n // makes progress, so the loop always terminates.\n while (true) {\n const outcome = await withSentinelMutex(\n sentinelFilePath,\n async (): Promise<AcquisitionOutcome> => {\n const sentinelState = await readSentinelState(sentinelFilePath);\n\n if (sentinelState) {\n const sentinelAge = Date.now() - sentinelState.mtimeMs;\n\n if (sentinelState.status === 'running') {\n const isAbandoned =\n sentinelAge > lockWaitTimeoutMs ||\n !isOwnerProcessAlive(sentinelState.pid);\n\n if (!isAbandoned && Date.now() < waitDeadline) return 'wait';\n // The owner died or overran the timeout: reclaim the sentinel below.\n } else {\n const isCacheValid =\n !forceRun &&\n sentinelAge <= cacheTimeoutMs &&\n sentinelState.version === packageJson.version;\n\n if (isCacheValid) return 'cached';\n }\n\n await removeSentinel(sentinelFilePath);\n }\n\n const hasAcquiredSentinel = await acquireSentinel(\n sentinelFilePath,\n currentTimestamp\n );\n\n return hasAcquiredSentinel ? 'acquired' : 'wait';\n }\n );\n\n if (outcome === 'cached') {\n await onIsCached?.();\n return;\n }\n\n if (outcome === 'acquired') break;\n\n // Another process owns the sentinel: wait for it, then look again. The\n // delay also guarantees the loop yields, so it can never turn into a busy\n // wait.\n await delay(LOCK_POLL_INTERVAL_MS);\n }\n\n ownedSentinelFilePaths.add(sentinelFilePath);\n\n const renewLock = () =>\n writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'running');\n\n try {\n await callback({ renewLock });\n\n // Mark the run as finished, re-creating the sentinel if the callback\n // deleted it (e.g. by cleaning the output directory).\n await writeOwnedSentinel(sentinelFilePath, currentTimestamp, 'done');\n } catch {\n await removeSentinel(sentinelFilePath); // Remove sentinel file if an error occurs\n } finally {\n ownedSentinelFilePaths.delete(sentinelFilePath);\n }\n};\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
3
- const require_utils_runParallel_wmic = require('./wmic.cjs');
4
3
  const require_utils_runParallel_ps = require('./ps.cjs');
4
+ const require_utils_runParallel_wmic = require('./wmic.cjs');
5
5
  let node_os = require("node:os");
6
6
  node_os = require_runtime.__toESM(node_os);
7
7
 
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let node_path = require("node:path");
2
3
  let node_fs = require("node:fs");
3
4
  let node_fs_promises = require("node:fs/promises");
4
- let node_path = require("node:path");
5
5
 
6
6
  //#region src/utils/withFileLock.ts
7
7
  const DEFAULT_OPTIONS = {
@@ -3,21 +3,21 @@ const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
3
3
  const require_utils_formatter = require('./utils/formatter.cjs');
4
4
  const require_utils_getFormatFromExtension = require('./utils/getFormatFromExtension.cjs');
5
5
  const require_utils_parseContentDeclarationFileName = require('./utils/parseContentDeclarationFileName.cjs');
6
- const require_handleAdditionalContentDeclarationFile = require('./handleAdditionalContentDeclarationFile.cjs');
6
+ const require_prepareIntlayer = require('./prepareIntlayer.cjs');
7
+ const require_writeContentDeclaration_writeContentDeclaration = require('./writeContentDeclaration/writeContentDeclaration.cjs');
7
8
  const require_handleContentDeclarationFileChange = require('./handleContentDeclarationFileChange.cjs');
9
+ const require_handleAdditionalContentDeclarationFile = require('./handleAdditionalContentDeclarationFile.cjs');
8
10
  const require_handleContentDeclarationFileMoved = require('./handleContentDeclarationFileMoved.cjs');
9
11
  const require_handleUnlinkedContentDeclarationFile = require('./handleUnlinkedContentDeclarationFile.cjs');
10
- const require_prepareIntlayer = require('./prepareIntlayer.cjs');
11
- const require_writeContentDeclaration_writeContentDeclaration = require('./writeContentDeclaration/writeContentDeclaration.cjs');
12
- let node_fs = require("node:fs");
13
- let node_fs_promises = require("node:fs/promises");
14
12
  let node_path = require("node:path");
15
13
  let _intlayer_config_colors = require("@intlayer/config/colors");
16
14
  _intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
17
- let _intlayer_config_file = require("@intlayer/config/file");
18
15
  let _intlayer_config_logger = require("@intlayer/config/logger");
19
16
  let _intlayer_config_node = require("@intlayer/config/node");
20
17
  let _intlayer_config_utils = require("@intlayer/config/utils");
18
+ let node_fs = require("node:fs");
19
+ let node_fs_promises = require("node:fs/promises");
20
+ let _intlayer_config_file = require("@intlayer/config/file");
21
21
 
22
22
  //#region src/watcher.ts
23
23
  const pendingUnlinks = /* @__PURE__ */ new Map();
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_writeFileIfChanged = require('../writeFileIfChanged.cjs');
3
3
  const require_writeConfiguration_generateConfigurationContent = require('./generateConfigurationContent.cjs');
4
- let node_fs_promises = require("node:fs/promises");
5
4
  let node_path = require("node:path");
5
+ let node_fs_promises = require("node:fs/promises");
6
6
 
7
7
  //#region src/writeConfiguration/index.ts
8
8
  const isCachedConfigurationUpToDate = async (configuration) => {
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
- let node_fs = require("node:fs");
4
3
  let node_path = require("node:path");
5
4
  let _intlayer_config_logger = require("@intlayer/config/logger");
6
- let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
7
5
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
8
6
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
7
+ let node_fs = require("node:fs");
8
+ let _intlayer_core_interpreter = require("@intlayer/core/interpreter");
9
9
 
10
10
  //#region src/writeContentDeclaration/processContentDeclarationContent.ts
11
11
  /**
@@ -1,9 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_utils_babelParser = require('../utils/babelParser.cjs');
4
- let _intlayer_core_dictionaryManipulator = require("@intlayer/core/dictionaryManipulator");
5
4
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
6
5
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
6
+ let _intlayer_core_dictionaryManipulator = require("@intlayer/core/dictionaryManipulator");
7
7
  let recast = require("recast");
8
8
  recast = require_runtime.__toESM(recast);
9
9
 
@@ -1,18 +1,18 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
- const require_utils_readDictionariesFromDisk = require('../utils/readDictionariesFromDisk.cjs');
3
2
  const require_utils_getFormatFromExtension = require('../utils/getFormatFromExtension.cjs');
4
3
  const require_detectFormatCommand = require('../detectFormatCommand.cjs');
4
+ const require_utils_readDictionariesFromDisk = require('../utils/readDictionariesFromDisk.cjs');
5
5
  const require_writeContentDeclaration_processContentDeclarationContent = require('./processContentDeclarationContent.cjs');
6
6
  const require_writeContentDeclaration_transformJSONFile = require('./transformJSONFile.cjs');
7
7
  const require_writeContentDeclaration_writeJSFile = require('./writeJSFile.cjs');
8
8
  const require_writeContentDeclaration_writeMarkdownFile = require('./writeMarkdownFile.cjs');
9
9
  const require_writeContentDeclaration_writeYamlFile = require('./writeYamlFile.cjs');
10
- let node_fs = require("node:fs");
11
- let node_fs_promises = require("node:fs/promises");
12
10
  let node_path = require("node:path");
13
11
  let _intlayer_config_defaultValues = require("@intlayer/config/defaultValues");
14
- let _intlayer_core_plugins = require("@intlayer/core/plugins");
12
+ let node_fs = require("node:fs");
13
+ let node_fs_promises = require("node:fs/promises");
15
14
  let node_child_process = require("node:child_process");
15
+ let _intlayer_core_plugins = require("@intlayer/core/plugins");
16
16
  let node_util = require("node:util");
17
17
 
18
18
  //#region src/writeContentDeclaration/writeContentDeclaration.ts
@@ -1,12 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_utils_getFormatFromExtension = require('../utils/getFormatFromExtension.cjs');
3
- const require_writeContentDeclaration_transformJSFile = require('./transformJSFile.cjs');
4
3
  const require_detectFormatCommand = require('../detectFormatCommand.cjs');
4
+ const require_writeContentDeclaration_transformJSFile = require('./transformJSFile.cjs');
5
5
  const require_getContentDeclarationFileTemplate_getContentDeclarationFileTemplate = require('../getContentDeclarationFileTemplate/getContentDeclarationFileTemplate.cjs');
6
- let node_fs = require("node:fs");
7
- let node_fs_promises = require("node:fs/promises");
8
6
  let node_path = require("node:path");
9
7
  let _intlayer_config_logger = require("@intlayer/config/logger");
8
+ let node_fs = require("node:fs");
9
+ let node_fs_promises = require("node:fs/promises");
10
10
  let node_child_process = require("node:child_process");
11
11
 
12
12
  //#region src/writeContentDeclaration/writeJSFile.ts
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_detectFormatCommand = require('../detectFormatCommand.cjs');
3
- let node_fs_promises = require("node:fs/promises");
4
3
  let node_path = require("node:path");
5
4
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
5
+ let node_fs_promises = require("node:fs/promises");
6
6
  let node_child_process = require("node:child_process");
7
7
 
8
8
  //#region src/writeContentDeclaration/writeMarkdownFile.ts
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_detectFormatCommand = require('../detectFormatCommand.cjs');
3
- let node_fs_promises = require("node:fs/promises");
4
3
  let node_path = require("node:path");
4
+ let node_fs_promises = require("node:fs/promises");
5
5
  let node_child_process = require("node:child_process");
6
6
  let _intlayer_core_utils = require("@intlayer/core/utils");
7
7
 
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let node_path = require("node:path");
2
3
  let node_fs = require("node:fs");
3
4
  let node_fs_promises = require("node:fs/promises");
4
- let node_path = require("node:path");
5
5
  let node_crypto = require("node:crypto");
6
6
 
7
7
  //#region src/writeFileIfChanged.ts
@@ -1,5 +1,5 @@
1
- import { existsSync, readFileSync } from "node:fs";
2
1
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
2
+ import { existsSync, readFileSync } from "node:fs";
3
3
  import { fileURLToPath } from "node:url";
4
4
 
5
5
  //#region \0utils:asset
@@ -1,5 +1,7 @@
1
1
  import { readDictionariesFromDisk } from "./utils/readDictionariesFromDisk.mjs";
2
2
  import { buildDictionary } from "./buildIntlayerDictionary/buildIntlayerDictionary.mjs";
3
+ import { processContentDeclaration } from "./buildIntlayerDictionary/processContentDeclaration.mjs";
4
+ import { cleanOutputDir } from "./cleanOutputDir.mjs";
3
5
  import { generateDictionaryListContent } from "./createDictionaryEntryPoint/generateDictionaryListContent.mjs";
4
6
  import { getBuiltDictionariesPath } from "./createDictionaryEntryPoint/getBuiltDictionariesPath.mjs";
5
7
  import { getBuiltDynamicDictionariesPath } from "./createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.mjs";
@@ -9,13 +11,11 @@ import { getBuiltUnmergedDictionariesPath } from "./createDictionaryEntryPoint/g
9
11
  import { createDictionaryEntryPoint } from "./createDictionaryEntryPoint/createDictionaryEntryPoint.mjs";
10
12
  import { createModuleAugmentation, formatDomains, formatRewriteRules, getTypeName } from "./createType/createModuleAugmentation.mjs";
11
13
  import { createTypes, generateTypeScriptType } from "./createType/createType.mjs";
12
- import { processContentDeclaration } from "./buildIntlayerDictionary/processContentDeclaration.mjs";
13
- import { ensureIntlayerBundle, formatLocalDictionaries, loadContentDeclaration, loadContentDeclarations } from "./loadDictionaries/loadContentDeclaration.mjs";
14
- import { loadLocalDictionaries } from "./loadDictionaries/loadLocalDictionaries.mjs";
15
14
  import { formatDictionaries, formatDictionariesOutput, formatDictionary, formatDictionaryOutput } from "./formatDictionary.mjs";
15
+ import { ensureIntlayerBundle, formatLocalDictionaries, loadContentDeclaration, loadContentDeclarations } from "./loadDictionaries/loadContentDeclaration.mjs";
16
16
  import { formatDistantDictionaries, loadRemoteDictionaries } from "./loadDictionaries/loadRemoteDictionaries.mjs";
17
17
  import { loadDictionaries } from "./loadDictionaries/loadDictionaries.mjs";
18
- import { cleanOutputDir } from "./cleanOutputDir.mjs";
18
+ import { loadLocalDictionaries } from "./loadDictionaries/loadLocalDictionaries.mjs";
19
19
  import { isCachedConfigurationUpToDate, writeConfiguration } from "./writeConfiguration/index.mjs";
20
20
  import { prepareIntlayer } from "./prepareIntlayer.mjs";
21
21
  import { detectExportedComponentName } from "./writeContentDeclaration/detectExportedComponentName.mjs";
@@ -1,11 +1,11 @@
1
1
  import { parallelize } from "../utils/parallelize.mjs";
2
2
  import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
3
3
  import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
4
- import { mkdir } from "node:fs/promises";
5
4
  import { resolve } from "node:path";
6
5
  import { colorizePath } from "@intlayer/config/logger";
7
- import { assertPathWithin } from "@intlayer/config/utils";
8
6
  import { DYNAMIC_DICTIONARIES_JSON_SUBDIR, DYNAMIC_ENTRY_LOADER_MAP_IDENTIFIER, OUTPUT_FORMAT } from "@intlayer/config/defaultValues";
7
+ import { assertPathWithin } from "@intlayer/config/utils";
8
+ import { mkdir } from "node:fs/promises";
9
9
  import { COMPOSITE_ID_SEPARATOR, QUALIFIER_DYNAMIC_TYPES_KEY, reconstructQualifiedEntry } from "@intlayer/core/dictionaryManipulator";
10
10
  import { getPerLocaleDictionary } from "@intlayer/core/plugins";
11
11
 
@@ -1,11 +1,11 @@
1
+ import { getPathHash } from "../utils/getPathHash.mjs";
1
2
  import { parallelize } from "../utils/parallelize.mjs";
2
3
  import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
3
- import { getPathHash } from "../utils/getPathHash.mjs";
4
- import { mkdir } from "node:fs/promises";
5
4
  import { relative, resolve } from "node:path";
6
5
  import { colorizePath } from "@intlayer/config/logger";
7
- import { assertPathWithin, normalizePath } from "@intlayer/config/utils";
8
6
  import { OUTPUT_FORMAT } from "@intlayer/config/defaultValues";
7
+ import { assertPathWithin, normalizePath } from "@intlayer/config/utils";
8
+ import { mkdir } from "node:fs/promises";
9
9
 
10
10
  //#region src/buildIntlayerDictionary/writeFetchDictionary.ts
11
11
  /**
@@ -1,9 +1,9 @@
1
1
  import { parallelize } from "../utils/parallelize.mjs";
2
2
  import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
3
- import { mkdir } from "node:fs/promises";
4
3
  import { resolve } from "node:path";
5
4
  import { colorizePath } from "@intlayer/config/logger";
6
5
  import { assertPathWithin } from "@intlayer/config/utils";
6
+ import { mkdir } from "node:fs/promises";
7
7
  import { mergeQualifiedDictionaries, normalizeDictionaries } from "@intlayer/core/dictionaryManipulator";
8
8
 
9
9
  //#region src/buildIntlayerDictionary/writeMergedDictionary.ts
@@ -1,11 +1,11 @@
1
+ import { getPathHash } from "../utils/getPathHash.mjs";
1
2
  import { parallelize } from "../utils/parallelize.mjs";
2
3
  import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
3
- import { getPathHash } from "../utils/getPathHash.mjs";
4
- import { mkdir } from "node:fs/promises";
5
4
  import { resolve } from "node:path";
6
5
  import { colorizePath } from "@intlayer/config/logger";
7
- import { assertPathWithin } from "@intlayer/config/utils";
8
6
  import { OUTPUT_FORMAT } from "@intlayer/config/defaultValues";
7
+ import { assertPathWithin } from "@intlayer/config/utils";
8
+ import { mkdir } from "node:fs/promises";
9
9
 
10
10
  //#region src/buildIntlayerDictionary/writeNestedDictionary.ts
11
11
  /**
@@ -1,11 +1,11 @@
1
1
  import { parallelize } from "../utils/parallelize.mjs";
2
- import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
3
2
  import { filterInvalidDictionaries } from "../filterInvalidDictionaries.mjs";
3
+ import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
4
4
  import { groupDictionariesByKey } from "./writeUnmergedDictionary.mjs";
5
5
  import { formatDistantDictionaries } from "../loadDictionaries/loadRemoteDictionaries.mjs";
6
- import { mkdir } from "node:fs/promises";
7
6
  import { resolve } from "node:path";
8
7
  import { colorizePath, x } from "@intlayer/config/logger";
8
+ import { mkdir } from "node:fs/promises";
9
9
  import { orderDictionaries } from "@intlayer/core/dictionaryManipulator";
10
10
 
11
11
  //#region src/buildIntlayerDictionary/writeRemoteDictionary.ts
@@ -1,10 +1,10 @@
1
1
  import { parallelize } from "../utils/parallelize.mjs";
2
- import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
3
2
  import { filterInvalidDictionaries } from "../filterInvalidDictionaries.mjs";
4
- import { mkdir } from "node:fs/promises";
3
+ import { writeJsonIfChanged } from "../writeJsonIfChanged.mjs";
5
4
  import { resolve } from "node:path";
6
5
  import { colorizePath, x } from "@intlayer/config/logger";
7
6
  import { assertPathWithin } from "@intlayer/config/utils";
7
+ import { mkdir } from "node:fs/promises";
8
8
  import { orderDictionaries } from "@intlayer/core/dictionaryManipulator";
9
9
 
10
10
  //#region src/buildIntlayerDictionary/writeUnmergedDictionary.ts
@@ -1,6 +1,6 @@
1
+ import { getAppLogger } from "@intlayer/config/logger";
1
2
  import { existsSync } from "node:fs";
2
3
  import { rm } from "node:fs/promises";
3
- import { getAppLogger } from "@intlayer/config/logger";
4
4
 
5
5
  //#region src/cleanOutputDir.ts
6
6
  const cleanOutputDir = async (configuration) => {
@@ -1,10 +1,10 @@
1
1
  import { readDictionariesFromDisk } from "./utils/readDictionariesFromDisk.mjs";
2
2
  import { writeJsonIfChanged } from "./writeJsonIfChanged.mjs";
3
3
  import { createDictionaryEntryPoint } from "./createDictionaryEntryPoint/createDictionaryEntryPoint.mjs";
4
- import { readFile, rm } from "node:fs/promises";
5
4
  import { join, normalize, relative } from "node:path";
6
5
  import { colorizeKey, colorizePath, getAppLogger } from "@intlayer/config/logger";
7
6
  import fg from "fast-glob";
7
+ import { readFile, rm } from "node:fs/promises";
8
8
  import { normalizePath } from "@intlayer/config/client";
9
9
 
10
10
  //#region src/cleanRemovedContentDeclaration.ts