@intlayer/engine 9.0.0-canary.13 → 9.0.0-canary.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/createType/createModuleAugmentation.cjs +1 -1
- package/dist/cjs/createType/createModuleAugmentation.cjs.map +1 -1
- package/dist/cjs/createType/createType.cjs +2 -1
- package/dist/cjs/createType/createType.cjs.map +1 -1
- package/dist/cjs/init/index.cjs +2 -1
- package/dist/cjs/init/index.cjs.map +1 -1
- package/dist/cjs/init/utils/configManipulation.cjs +39 -5
- package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
- package/dist/cjs/init/utils/githubActions.cjs +3 -0
- package/dist/cjs/init/utils/githubActions.cjs.map +1 -1
- package/dist/cjs/init/utils/index.cjs +1 -0
- package/dist/cjs/init/utils/packageManager.cjs +8 -0
- package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
- package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +2 -2
- package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs.map +1 -1
- package/dist/cjs/prepareIntlayer.cjs +11 -7
- package/dist/cjs/prepareIntlayer.cjs.map +1 -1
- package/dist/cjs/syncPluginKit/createFileAdapter.cjs +119 -0
- package/dist/cjs/syncPluginKit/createFileAdapter.cjs.map +1 -0
- package/dist/cjs/syncPluginKit/createSyncPlugin.cjs +154 -0
- package/dist/cjs/syncPluginKit/createSyncPlugin.cjs.map +1 -0
- package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs +37 -0
- package/dist/cjs/syncPluginKit/extractKeyAndLocaleFromPath.cjs.map +1 -0
- package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs +20 -0
- package/dist/cjs/syncPluginKit/filePathPatternHelpers.cjs.map +1 -0
- package/dist/cjs/syncPluginKit/index.cjs +11 -0
- package/dist/cjs/syncPluginKit/types.cjs +0 -0
- package/dist/cjs/utils/runParallel/index.cjs +2 -2
- package/dist/cjs/utils/runParallel/index.cjs.map +1 -1
- package/dist/cjs/watcher.cjs +2 -3
- package/dist/cjs/watcher.cjs.map +1 -1
- package/dist/cjs/writeFileIfChanged.cjs +41 -17
- package/dist/cjs/writeFileIfChanged.cjs.map +1 -1
- package/dist/esm/createType/createModuleAugmentation.mjs +1 -1
- package/dist/esm/createType/createModuleAugmentation.mjs.map +1 -1
- package/dist/esm/createType/createType.mjs +3 -2
- package/dist/esm/createType/createType.mjs.map +1 -1
- package/dist/esm/init/index.mjs +3 -2
- package/dist/esm/init/index.mjs.map +1 -1
- package/dist/esm/init/utils/configManipulation.mjs +39 -6
- package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
- package/dist/esm/init/utils/githubActions.mjs +3 -0
- package/dist/esm/init/utils/githubActions.mjs.map +1 -1
- package/dist/esm/init/utils/index.mjs +2 -2
- package/dist/esm/init/utils/packageManager.mjs +8 -0
- package/dist/esm/init/utils/packageManager.mjs.map +1 -1
- package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +2 -2
- package/dist/esm/loadDictionaries/loadContentDeclaration.mjs.map +1 -1
- package/dist/esm/prepareIntlayer.mjs +11 -7
- package/dist/esm/prepareIntlayer.mjs.map +1 -1
- package/dist/esm/syncPluginKit/createFileAdapter.mjs +115 -0
- package/dist/esm/syncPluginKit/createFileAdapter.mjs.map +1 -0
- package/dist/esm/syncPluginKit/createSyncPlugin.mjs +152 -0
- package/dist/esm/syncPluginKit/createSyncPlugin.mjs.map +1 -0
- package/dist/esm/syncPluginKit/extractKeyAndLocaleFromPath.mjs +35 -0
- package/dist/esm/syncPluginKit/extractKeyAndLocaleFromPath.mjs.map +1 -0
- package/dist/esm/syncPluginKit/filePathPatternHelpers.mjs +18 -0
- package/dist/esm/syncPluginKit/filePathPatternHelpers.mjs.map +1 -0
- package/dist/esm/syncPluginKit/index.mjs +6 -0
- package/dist/esm/syncPluginKit/types.mjs +0 -0
- package/dist/esm/utils/runParallel/index.mjs +2 -2
- package/dist/esm/utils/runParallel/index.mjs.map +1 -1
- package/dist/esm/watcher.mjs +2 -3
- package/dist/esm/watcher.mjs.map +1 -1
- package/dist/esm/writeFileIfChanged.mjs +44 -20
- package/dist/esm/writeFileIfChanged.mjs.map +1 -1
- package/dist/types/createType/createType.d.ts.map +1 -1
- package/dist/types/init/index.d.ts.map +1 -1
- package/dist/types/init/utils/configManipulation.d.ts +9 -1
- package/dist/types/init/utils/configManipulation.d.ts.map +1 -1
- package/dist/types/init/utils/githubActions.d.ts.map +1 -1
- package/dist/types/init/utils/index.d.ts +2 -2
- package/dist/types/init/utils/packageManager.d.ts.map +1 -1
- package/dist/types/syncPluginKit/createFileAdapter.d.ts +51 -0
- package/dist/types/syncPluginKit/createFileAdapter.d.ts.map +1 -0
- package/dist/types/syncPluginKit/createSyncPlugin.d.ts +18 -0
- package/dist/types/syncPluginKit/createSyncPlugin.d.ts.map +1 -0
- package/dist/types/syncPluginKit/extractKeyAndLocaleFromPath.d.ts +20 -0
- package/dist/types/syncPluginKit/extractKeyAndLocaleFromPath.d.ts.map +1 -0
- package/dist/types/syncPluginKit/filePathPatternHelpers.d.ts +16 -0
- package/dist/types/syncPluginKit/filePathPatternHelpers.d.ts.map +1 -0
- package/dist/types/syncPluginKit/index.d.ts +6 -0
- package/dist/types/syncPluginKit/types.d.ts +149 -0
- package/dist/types/syncPluginKit/types.d.ts.map +1 -0
- package/dist/types/utils/runParallel/index.d.ts +6 -1
- package/dist/types/utils/runParallel/index.d.ts.map +1 -1
- package/dist/types/watcher.d.ts.map +1 -1
- package/dist/types/writeFileIfChanged.d.ts +30 -6
- package/dist/types/writeFileIfChanged.d.ts.map +1 -1
- package/package.json +24 -8
package/dist/esm/watcher.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.mjs","names":["fsWatch"],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync, watch as fsWatch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport { formatPath } from './utils';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n persistent?: boolean;\n};\n\n// awaitWriteFinish equivalent: debounce per path until the file is stable\nconst STABILITY_THRESHOLD = 1000;\n\nconst createStabilityDebounce = () => {\n const pending = new Map<string, NodeJS.Timeout>();\n return (path: string, handler: () => void) => {\n const existing = pending.get(path);\n if (existing) clearTimeout(existing);\n pending.set(\n path,\n setTimeout(() => {\n pending.delete(path);\n handler();\n }, STABILITY_THRESHOLD)\n );\n };\n};\n\n// Initialize @parcel/watcher (non-persistent until subscribed)\nexport const watch = async (options?: WatchOptions) => {\n const { subscribe } = await import('@parcel/watcher');\n\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedMainDir = normalizePath(mainDir);\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n const subscriptions: { unsubscribe: () => Promise<void> }[] = [];\n\n const scheduleStable = createStabilityDebounce();\n\n // ── mainDir watcher (depth 0) ──────────────────────────────────────────────\n // Detects broken or missing entry-point files inside .intlayer/main\n if (existsSync(mainDir)) {\n const mainDirSub = await subscribe(normalizedMainDir, (err, events) => {\n if (err || isProcessing) return;\n\n for (const event of events) {\n const eventPath = normalizePath(event.path);\n // depth-0 filter: only files directly inside mainDir\n const rel = eventPath.slice(normalizedMainDir.length + 1);\n if (!rel || rel.includes('/')) continue;\n // Temp files written by the bundler (write-then-rename) are build-internal;\n // their deletion must not trigger a clean rebuild.\n if (rel.endsWith('.tmp')) continue;\n\n if (event.type === 'update') {\n processEvent(async () => {\n clearModuleCache(event.path);\n try {\n const fileUrl = pathToFileURL(event.path).href;\n await import(`${fileUrl}?update=${Date.now()}`);\n } catch {\n appLogger(\n `Entry point ${basename(event.path)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n } else if (event.type === 'delete') {\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(event.path)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n });\n }\n }\n });\n subscriptions.push(mainDirSub);\n }\n\n // ── baseDir watcher (depth 0) — detect .intlayer directory removal ─────────\n // Native fs.watch is non-recursive and ideal for single-directory depth-0 detection.\n const intlayerDirName = basename(normalizedIntlayerDir);\n const fsDirWatcher = fsWatch(\n baseDir,\n { persistent: isWatchMode },\n (eventType, filename) => {\n if (isProcessing || !filename) return;\n if (filename !== intlayerDirName) return;\n\n const fullPath = normalizePath(resolve(baseDir, filename));\n if (fullPath !== normalizedIntlayerDir) return;\n\n if (eventType === 'rename' && !existsSync(normalizedIntlayerDir)) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n }\n );\n subscriptions.push({\n unsubscribe: async () => {\n fsDirWatcher.close();\n },\n });\n\n // ── main content watcher ───────────────────────────────────────────────────\n // Ignore patterns for @parcel/watcher (micromatch globs)\n const ignorePatterns = excludedSegments.map((s) => `**/${s}/**`);\n\n const contentDirs = contentDir\n .map((dir) => normalizePath(dir))\n .filter(existsSync);\n\n // Collect unique directories to subscribe to (dirs only, not file paths)\n const dirsToWatch = new Set<string>(contentDirs);\n if (normalizedConfigPath) {\n dirsToWatch.add(normalizePath(dirname(normalizedConfigPath)));\n }\n\n const contentHandler = (\n err: Error | null,\n events: Array<{ type: string; path: string }>\n ) => {\n if (err) {\n appLogger(`Watcher error: ${err}`, { level: 'error' });\n appLogger('Restarting watcher');\n prepareIntlayer(configuration);\n return;\n }\n\n for (const event of events) {\n const filePath = event.path;\n const path = normalizePath(filePath);\n\n const isConfigFile =\n normalizedConfigPath && path === normalizedConfigPath;\n\n if (!isConfigFile) {\n // Must originate from a watched content directory\n const isInContentDir = contentDirs.some(\n (d) => path.startsWith(`${d}/`) || path === d\n );\n if (!isInContentDir) continue;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n continue;\n\n if (!fileExtensions.some((extension) => path.endsWith(extension)))\n continue;\n }\n\n if (event.type === 'create') {\n const fileName = basename(filePath);\n\n // Move detection must happen synchronously before any debounce\n let isMove = false;\n let matchedOldPath: string | undefined;\n\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n if (isMove && matchedOldPath) {\n processEvent(async () => {\n await handleContentDeclarationFileMoved(\n matchedOldPath!,\n filePath,\n configuration\n );\n });\n } else {\n // Debounce: wait for write to finish before reading the file\n scheduleStable(path, () => {\n processEvent(async () => {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n if (isEmpty) {\n const extensionPattern = fileExtensions\n .map((ext) => ext.replace(/\\./g, '\\\\.'))\n .join('|');\n const name = fileName.replace(\n new RegExp(`(${extensionPattern})$`),\n ''\n );\n\n await writeContentDeclaration(\n { key: name, content: {}, filePath },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(\n filePath,\n configuration\n );\n });\n });\n }\n } else if (event.type === 'update') {\n scheduleStable(path, () => {\n processEvent(async () => {\n if (isConfigFile) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(filePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n });\n });\n } else if (event.type === 'delete') {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'create' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n }\n }\n };\n\n for (const dir of dirsToWatch) {\n const sub = await subscribe(dir, contentHandler, {\n ignore: ignorePatterns,\n });\n\n subscriptions.push(sub);\n }\n\n return subscriptions;\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n // Only enter watch mode when the caller explicitly opts in via `persistent`.\n // `configuration.content.watch` is the dev-mode signal consumed by bundler\n // plugins (e.g. vite-intlayer's `configureServer`); it must not coerce\n // `intlayer build` (which passes `persistent: false`) into a persistent\n // watcher, since that prevents the build command from ever exiting.\n if (options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"watcher.mjs","names":["fsWatch"],"sources":["../../src/watcher.ts"],"sourcesContent":["import { existsSync, watch as fsWatch } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport { basename, dirname, resolve } from 'node:path';\nimport * as ANSIColor from '@intlayer/config/colors';\nimport { transpileTSToCJS } from '@intlayer/config/file';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n getConfigurationAndFilePath,\n} from '@intlayer/config/node';\nimport {\n clearAllCache,\n clearDiskCacheMemory,\n clearModuleCache,\n normalizePath,\n} from '@intlayer/config/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { handleAdditionalContentDeclarationFile } from './handleAdditionalContentDeclarationFile';\nimport { handleContentDeclarationFileChange } from './handleContentDeclarationFileChange';\nimport { handleContentDeclarationFileMoved } from './handleContentDeclarationFileMoved';\nimport { handleUnlinkedContentDeclarationFile } from './handleUnlinkedContentDeclarationFile';\nimport { prepareIntlayer } from './prepareIntlayer';\nimport { formatPath } from './utils';\nimport { writeContentDeclaration } from './writeContentDeclaration';\n\n// Map to track files that were recently unlinked: oldPath -> { timer, timestamp }\nconst pendingUnlinks = new Map<\n string,\n { timer: NodeJS.Timeout; oldPath: string }\n>();\n\n// Array-based sequential task queue — no Promise chain accumulation, no race conditions\nconst taskQueue: (() => Promise<void>)[] = [];\nlet isProcessing = false;\n\nconst processQueue = async () => {\n if (isProcessing) return;\n isProcessing = true;\n while (taskQueue.length > 0) {\n const task = taskQueue.shift()!;\n try {\n await task();\n } catch (error) {\n console.error(error);\n }\n }\n isProcessing = false;\n};\n\nconst processEvent = (task: () => Promise<void>) => {\n taskQueue.push(task);\n processQueue();\n};\n\ntype WatchOptions = {\n configuration?: IntlayerConfig;\n configOptions?: GetConfigurationOptions;\n skipPrepare?: boolean;\n persistent?: boolean;\n};\n\n// awaitWriteFinish equivalent: debounce per path until the file is stable\nconst STABILITY_THRESHOLD = 1000;\n\nconst createStabilityDebounce = () => {\n const pending = new Map<string, NodeJS.Timeout>();\n return (path: string, handler: () => void) => {\n const existing = pending.get(path);\n if (existing) clearTimeout(existing);\n pending.set(\n path,\n setTimeout(() => {\n pending.delete(path);\n handler();\n }, STABILITY_THRESHOLD)\n );\n };\n};\n\n// Initialize @parcel/watcher (non-persistent until subscribed)\nexport const watch = async (options?: WatchOptions) => {\n const { subscribe } = await import('@parcel/watcher');\n\n const configResult = getConfigurationAndFilePath(options?.configOptions);\n const configurationFilePath = configResult.configurationFilePath;\n let configuration: IntlayerConfig =\n options?.configuration ?? configResult.configuration;\n const appLogger = getAppLogger(configuration);\n\n const {\n watch: isWatchMode,\n fileExtensions,\n contentDir,\n excludedPath,\n } = configuration.content;\n\n if (!configuration.content.watch) return;\n\n appLogger('Watching Intlayer content declarations');\n\n if (configuration.build.optimize === true) {\n appLogger(\n [\n `Build optimization is forced to ${colorize('true', ANSIColor.GREY)}, but watching is enabled too.`,\n 'It may lead to dev mode performance degradation as well as import errors.',\n 'Its recommended to keep the',\n colorize('`build.optimized`', ANSIColor.BLUE),\n 'option',\n colorize('undefined', ANSIColor.GREY),\n 'to get the best dev mode experience',\n ],\n {\n level: 'warn',\n }\n );\n }\n\n // Strip glob markers from excludedPath entries to get plain segments (e.g. 'node_modules')\n const excludedSegments = excludedPath.map((segment) =>\n segment.replace(/^\\*\\*\\//, '').replace(/\\/\\*\\*$/, '')\n );\n\n const normalizedConfigPath = configurationFilePath\n ? normalizePath(configurationFilePath)\n : null;\n\n const { mainDir, baseDir } = configuration.system;\n const normalizedMainDir = normalizePath(mainDir);\n const normalizedIntlayerDir = normalizePath(dirname(mainDir));\n\n const subscriptions: { unsubscribe: () => Promise<void> }[] = [];\n\n const scheduleStable = createStabilityDebounce();\n\n // ── mainDir watcher (depth 0) ──────────────────────────────────────────────\n // Detects broken or missing entry-point files inside .intlayer/main\n if (existsSync(mainDir)) {\n const mainDirSub = await subscribe(normalizedMainDir, (err, events) => {\n if (err || isProcessing) return;\n\n for (const event of events) {\n const eventPath = normalizePath(event.path);\n // depth-0 filter: only files directly inside mainDir\n const rel = eventPath.slice(normalizedMainDir.length + 1);\n if (!rel || rel.includes('/')) continue;\n // Temp files written by the bundler (write-then-rename) are build-internal;\n // their deletion must not trigger a clean rebuild.\n if (rel.endsWith('.tmp')) continue;\n\n if (event.type === 'update') {\n processEvent(async () => {\n try {\n // Validate that the regenerated entry point — and the relative\n // dictionary graph it imports — still resolves, by bundling it\n // in-memory with esbuild (via the shared, freshness-checked\n // transpile cache). This replaces a cache-busting dynamic\n // `import()`, which leaked a permanent record into Node's ESM\n // registry on every rebuild since that registry is never evicted.\n const entryCode = await readFile(event.path, 'utf-8');\n await transpileTSToCJS(entryCode, event.path);\n } catch {\n appLogger(\n `Entry point ${basename(event.path)} failed to load, running clean rebuild...`,\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n }\n });\n } else if (event.type === 'delete') {\n processEvent(async () => {\n appLogger(\n [\n 'Entry point',\n formatPath(basename(event.path)),\n 'was removed, running clean rebuild...',\n ],\n { level: 'warn' }\n );\n await prepareIntlayer(configuration, {\n clean: true,\n forceRun: true,\n });\n });\n }\n }\n });\n subscriptions.push(mainDirSub);\n }\n\n // ── baseDir watcher (depth 0) — detect .intlayer directory removal ─────────\n // Native fs.watch is non-recursive and ideal for single-directory depth-0 detection.\n const intlayerDirName = basename(normalizedIntlayerDir);\n const fsDirWatcher = fsWatch(\n baseDir,\n { persistent: isWatchMode },\n (eventType, filename) => {\n if (isProcessing || !filename) return;\n if (filename !== intlayerDirName) return;\n\n const fullPath = normalizePath(resolve(baseDir, filename));\n if (fullPath !== normalizedIntlayerDir) return;\n\n if (eventType === 'rename' && !existsSync(normalizedIntlayerDir)) {\n appLogger([\n formatPath('.intlayer'),\n 'directory removed, running clean rebuild...',\n ]);\n processEvent(() =>\n prepareIntlayer(configuration, { clean: true, forceRun: true })\n );\n }\n }\n );\n subscriptions.push({\n unsubscribe: async () => {\n fsDirWatcher.close();\n },\n });\n\n // ── main content watcher ───────────────────────────────────────────────────\n // Ignore patterns for @parcel/watcher (micromatch globs)\n const ignorePatterns = excludedSegments.map((s) => `**/${s}/**`);\n\n const contentDirs = contentDir\n .map((dir) => normalizePath(dir))\n .filter(existsSync);\n\n // Collect unique directories to subscribe to (dirs only, not file paths)\n const dirsToWatch = new Set<string>(contentDirs);\n if (normalizedConfigPath) {\n dirsToWatch.add(normalizePath(dirname(normalizedConfigPath)));\n }\n\n const contentHandler = (\n err: Error | null,\n events: Array<{ type: string; path: string }>\n ) => {\n if (err) {\n appLogger(`Watcher error: ${err}`, { level: 'error' });\n appLogger('Restarting watcher');\n prepareIntlayer(configuration);\n return;\n }\n\n for (const event of events) {\n const filePath = event.path;\n const path = normalizePath(filePath);\n\n const isConfigFile =\n normalizedConfigPath && path === normalizedConfigPath;\n\n if (!isConfigFile) {\n // Must originate from a watched content directory\n const isInContentDir = contentDirs.some(\n (d) => path.startsWith(`${d}/`) || path === d\n );\n if (!isInContentDir) continue;\n\n if (excludedSegments.some((segment) => path.includes(`/${segment}`)))\n continue;\n\n if (!fileExtensions.some((extension) => path.endsWith(extension)))\n continue;\n }\n\n if (event.type === 'create') {\n const fileName = basename(filePath);\n\n // Move detection must happen synchronously before any debounce\n let isMove = false;\n let matchedOldPath: string | undefined;\n\n for (const [oldPath] of pendingUnlinks) {\n if (basename(oldPath) === fileName) {\n matchedOldPath = oldPath;\n break;\n }\n }\n\n if (!matchedOldPath && pendingUnlinks.size === 1) {\n matchedOldPath = pendingUnlinks.keys().next().value;\n }\n\n if (matchedOldPath) {\n const pending = pendingUnlinks.get(matchedOldPath);\n if (pending) {\n clearTimeout(pending.timer);\n pendingUnlinks.delete(matchedOldPath);\n }\n isMove = true;\n appLogger(`File moved from ${matchedOldPath} to ${filePath}`);\n }\n\n if (isMove && matchedOldPath) {\n processEvent(async () => {\n await handleContentDeclarationFileMoved(\n matchedOldPath!,\n filePath,\n configuration\n );\n });\n } else {\n // Debounce: wait for write to finish before reading the file\n scheduleStable(path, () => {\n processEvent(async () => {\n const fileContent = await readFile(filePath, 'utf-8');\n const isEmpty = fileContent === '';\n\n if (isEmpty) {\n const extensionPattern = fileExtensions\n .map((ext) => ext.replace(/\\./g, '\\\\.'))\n .join('|');\n const name = fileName.replace(\n new RegExp(`(${extensionPattern})$`),\n ''\n );\n\n await writeContentDeclaration(\n { key: name, content: {}, filePath },\n configuration\n );\n }\n\n await handleAdditionalContentDeclarationFile(\n filePath,\n configuration\n );\n });\n });\n }\n } else if (event.type === 'update') {\n scheduleStable(path, () => {\n processEvent(async () => {\n if (isConfigFile) {\n appLogger('Configuration file changed, repreparing Intlayer');\n\n clearModuleCache(filePath);\n clearAllCache();\n\n const { configuration: newConfiguration } =\n getConfigurationAndFilePath(options?.configOptions);\n\n configuration = options?.configuration ?? newConfiguration;\n\n await prepareIntlayer(configuration, { clean: false });\n } else {\n // Clear module cache for the changed file to avoid stale require() results\n clearModuleCache(filePath);\n // Evict in-memory caches so loadContentDeclaration picks up fresh content\n clearAllCache();\n clearDiskCacheMemory();\n await handleContentDeclarationFileChange(filePath, configuration);\n }\n });\n });\n } else if (event.type === 'delete') {\n // Delay unlink processing to see if an 'add' event occurs (indicating a move)\n const timer = setTimeout(async () => {\n // If timer fires, the file was genuinely removed\n pendingUnlinks.delete(filePath);\n processEvent(async () =>\n handleUnlinkedContentDeclarationFile(filePath, configuration)\n );\n }, 200); // 200ms window to catch the 'create' event\n\n pendingUnlinks.set(filePath, { timer, oldPath: filePath });\n }\n }\n };\n\n for (const dir of dirsToWatch) {\n const sub = await subscribe(dir, contentHandler, {\n ignore: ignorePatterns,\n });\n\n subscriptions.push(sub);\n }\n\n return subscriptions;\n};\n\nexport const buildAndWatchIntlayer = async (options?: WatchOptions) => {\n const { skipPrepare, ...rest } = options ?? {};\n const configuration =\n options?.configuration ?? getConfiguration(options?.configOptions);\n\n if (!skipPrepare) {\n await prepareIntlayer(configuration, { forceRun: true });\n }\n\n // Only enter watch mode when the caller explicitly opts in via `persistent`.\n // `configuration.content.watch` is the dev-mode signal consumed by bundler\n // plugins (e.g. vite-intlayer's `configureServer`); it must not coerce\n // `intlayer build` (which passes `persistent: false`) into a persistent\n // watcher, since that prevents the build command from ever exiting.\n if (options?.persistent) {\n await watch({ ...rest, configuration });\n }\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { chmod, mkdir, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
1
|
+
import { chmod, mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
2
2
|
import { basename, join } from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { rmSync } from "node:fs";
|
|
5
5
|
|
|
6
6
|
//#region src/writeFileIfChanged.ts
|
|
7
7
|
const activeTempFiles = /* @__PURE__ */ new Set();
|
|
@@ -10,28 +10,52 @@ process.on("exit", () => {
|
|
|
10
10
|
rmSync(file, { force: true });
|
|
11
11
|
} catch {}
|
|
12
12
|
});
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Permission bits a freshly created file receives on this system. Detected once
|
|
15
|
+
* from the first temp file we actually write (`process.umask()` with no
|
|
16
|
+
* argument is deprecated and thread-unsafe) and cached, so the atomic path can
|
|
17
|
+
* skip restoring the mode whenever the source file already uses the default
|
|
18
|
+
* mode — which is the case for essentially every generated file.
|
|
19
|
+
*/
|
|
20
|
+
let defaultFileMode;
|
|
21
|
+
/**
|
|
22
|
+
* Write `data` to `path` only when it differs from the file already on disk,
|
|
23
|
+
* preserving the existing file's permission mode.
|
|
24
|
+
*
|
|
25
|
+
* The whole file is read back and byte-compared because the files written here
|
|
26
|
+
* (dictionaries, entry points, types) are small, so reading beats streaming a
|
|
27
|
+
* hash. When the content is unchanged the write is skipped entirely, which both
|
|
28
|
+
* avoids inode churn and prevents downstream watchers from rebuilding.
|
|
29
|
+
*
|
|
30
|
+
* @returns `true` when the file was written, `false` when it was already up to date.
|
|
31
|
+
*/
|
|
32
|
+
const writeFileIfChanged = async (path, data, { encoding = "utf8", tempDir, atomic = true } = {}) => {
|
|
33
|
+
const newData = Buffer.from(data, encoding);
|
|
34
|
+
let existingData = null;
|
|
35
|
+
try {
|
|
36
|
+
existingData = await readFile(path);
|
|
37
|
+
} catch {}
|
|
38
|
+
if (existingData?.equals(newData)) return false;
|
|
39
|
+
if (!atomic) {
|
|
40
|
+
await writeFile(path, newData);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
let modeToRestore;
|
|
44
|
+
if (existingData !== null) try {
|
|
45
|
+
modeToRestore = (await stat(path)).mode & 511;
|
|
46
|
+
} catch {}
|
|
24
47
|
if (tempDir) await mkdir(tempDir, { recursive: true });
|
|
25
48
|
const tempFileName = `${basename(path)}.${Date.now()}-${randomBytes(4).toString("hex")}.tmp`;
|
|
26
49
|
const tempPath = tempDir ? join(tempDir, tempFileName) : `${path}.${tempFileName}`;
|
|
27
50
|
activeTempFiles.add(tempPath);
|
|
28
51
|
try {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
await writeFile(tempPath, newData);
|
|
53
|
+
if (modeToRestore !== void 0) {
|
|
54
|
+
if (defaultFileMode === void 0) try {
|
|
55
|
+
defaultFileMode = (await stat(tempPath)).mode & 511;
|
|
56
|
+
} catch {}
|
|
57
|
+
if (modeToRestore !== defaultFileMode) await chmod(tempPath, modeToRestore);
|
|
58
|
+
}
|
|
35
59
|
await rename(tempPath, path);
|
|
36
60
|
} catch (error) {
|
|
37
61
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"writeFileIfChanged.mjs","names":[],"sources":["../../src/writeFileIfChanged.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"writeFileIfChanged.mjs","names":[],"sources":["../../src/writeFileIfChanged.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { rmSync } from 'node:fs';\nimport {\n chmod,\n mkdir,\n readFile,\n rename,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { basename, join } from 'node:path';\n\nconst activeTempFiles = new Set<string>();\n\n// Synchronous cleanup on process exit\nprocess.on('exit', () => {\n for (const file of activeTempFiles) {\n try {\n rmSync(file, { force: true });\n } catch {}\n }\n});\n\n/**\n * Permission bits a freshly created file receives on this system. Detected once\n * from the first temp file we actually write (`process.umask()` with no\n * argument is deprecated and thread-unsafe) and cached, so the atomic path can\n * skip restoring the mode whenever the source file already uses the default\n * mode — which is the case for essentially every generated file.\n */\nlet defaultFileMode: number | undefined;\n\n/**\n * Options for {@link writeFileIfChanged}.\n */\nexport type WriteFileIfChangedOptions = {\n /** Encoding used to turn `data` into bytes. Defaults to `'utf8'`. */\n encoding?: BufferEncoding;\n /** Directory to hold the temporary file used for the atomic swap. */\n tempDir?: string;\n /**\n * Write atomically via a temp file + `rename` so readers never observe a\n * half-written file. This creates a fresh inode on every write, which roughly\n * doubles the cost of a changed write compared to overwriting in place. Set to\n * `false` for callers whose consumers tolerate torn reads to write directly.\n * Defaults to `true`.\n */\n atomic?: boolean;\n};\n\n/**\n * Write `data` to `path` only when it differs from the file already on disk,\n * preserving the existing file's permission mode.\n *\n * The whole file is read back and byte-compared because the files written here\n * (dictionaries, entry points, types) are small, so reading beats streaming a\n * hash. When the content is unchanged the write is skipped entirely, which both\n * avoids inode churn and prevents downstream watchers from rebuilding.\n *\n * @returns `true` when the file was written, `false` when it was already up to date.\n */\nexport const writeFileIfChanged = async (\n path: string,\n data: string,\n { encoding = 'utf8', tempDir, atomic = true }: WriteFileIfChangedOptions = {}\n): Promise<boolean> => {\n const newData = Buffer.from(data, encoding);\n\n // Read the current content first: the common case is an unchanged file, and\n // this single read is the whole fast path (no stat/chmod needed to bail out).\n let existingData: Buffer | null = null;\n try {\n existingData = await readFile(path);\n } catch {}\n\n if (existingData?.equals(newData)) {\n return false;\n }\n\n // Fast path: overwrite in place. Truncating an existing file keeps its inode,\n // so its permission mode is preserved automatically (no chmod needed). This\n // skips the temp-file inode churn at the cost of exposing readers to a\n // partially written file.\n if (!atomic) {\n await writeFile(path, newData);\n return true;\n }\n\n // The atomic swap replaces the inode, so the existing mode is not preserved\n // and must be reapplied. Only a file that already exists has a mode to keep.\n let modeToRestore: number | undefined;\n if (existingData !== null) {\n try {\n modeToRestore = (await stat(path)).mode & 0o777;\n } catch {}\n }\n\n if (tempDir) {\n await mkdir(tempDir, { recursive: true });\n }\n\n const tempFileName = `${basename(path)}.${Date.now()}-${randomBytes(4).toString('hex')}.tmp`;\n const tempPath = tempDir\n ? join(tempDir, tempFileName)\n : `${path}.${tempFileName}`;\n activeTempFiles.add(tempPath);\n\n try {\n await writeFile(tempPath, newData);\n\n if (modeToRestore !== undefined) {\n // Learn the ambient default mode once from a real temp file, then only\n // chmod when the source file used a non-default mode.\n if (defaultFileMode === undefined) {\n try {\n defaultFileMode = (await stat(tempPath)).mode & 0o777;\n } catch {}\n }\n if (modeToRestore !== defaultFileMode) {\n await chmod(tempPath, modeToRestore);\n }\n }\n\n await rename(tempPath, path);\n } catch (error) {\n try {\n await rm(tempPath, { force: true });\n } catch {}\n throw error;\n } finally {\n activeTempFiles.delete(tempPath);\n }\n\n return true;\n};\n"],"mappings":";;;;;;AAaA,MAAM,kCAAkB,IAAI,KAAa;AAGzC,QAAQ,GAAG,cAAc;AACvB,MAAK,MAAM,QAAQ,gBACjB,KAAI;AACF,SAAO,MAAM,EAAE,OAAO,MAAM,CAAC;SACvB;EAEV;;;;;;;;AASF,IAAI;;;;;;;;;;;;AA+BJ,MAAa,qBAAqB,OAChC,MACA,MACA,EAAE,WAAW,QAAQ,SAAS,SAAS,SAAoC,EAAE,KACxD;CACrB,MAAM,UAAU,OAAO,KAAK,MAAM,SAAS;CAI3C,IAAI,eAA8B;AAClC,KAAI;AACF,iBAAe,MAAM,SAAS,KAAK;SAC7B;AAER,KAAI,cAAc,OAAO,QAAQ,CAC/B,QAAO;AAOT,KAAI,CAAC,QAAQ;AACX,QAAM,UAAU,MAAM,QAAQ;AAC9B,SAAO;;CAKT,IAAI;AACJ,KAAI,iBAAiB,KACnB,KAAI;AACF,mBAAiB,MAAM,KAAK,KAAK,EAAE,OAAO;SACpC;AAGV,KAAI,QACF,OAAM,MAAM,SAAS,EAAE,WAAW,MAAM,CAAC;CAG3C,MAAM,eAAe,GAAG,SAAS,KAAK,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,YAAY,EAAE,CAAC,SAAS,MAAM,CAAC;CACvF,MAAM,WAAW,UACb,KAAK,SAAS,aAAa,GAC3B,GAAG,KAAK,GAAG;AACf,iBAAgB,IAAI,SAAS;AAE7B,KAAI;AACF,QAAM,UAAU,UAAU,QAAQ;AAElC,MAAI,kBAAkB,QAAW;AAG/B,OAAI,oBAAoB,OACtB,KAAI;AACF,uBAAmB,MAAM,KAAK,SAAS,EAAE,OAAO;WAC1C;AAEV,OAAI,kBAAkB,gBACpB,OAAM,MAAM,UAAU,cAAc;;AAIxC,QAAM,OAAO,UAAU,KAAK;UACrB,OAAO;AACd,MAAI;AACF,SAAM,GAAG,UAAU,EAAE,OAAO,MAAM,CAAC;UAC7B;AACR,QAAM;WACE;AACR,kBAAgB,OAAO,SAAS;;AAGlC,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createType.d.ts","names":[],"sources":["../../../src/createType/createType.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"createType.d.ts","names":[],"sources":["../../../src/createType/createType.ts"],"mappings":";;;;cAUa,sBAAA,GACX,UAAA,EAAY,UAAA,GAAa,wBAAA;;AAD3B;;cAUa,WAAA,GACX,YAAA,GAAe,UAAA,GAAa,wBAAA,KAC5B,aAAA,EAAe,cAAA,KACd,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/init/index.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/init/index.ts"],"mappings":";;;;;AA4LA;;;cAAa,wBAAA,GACX,YAAA,EAAc,MAAA;;AAsBhB;;;;;AAQA;;;KARY,eAAA;;;;KAQA,WAAA;EACV,WAAA,YAEA;EAAA,eAAA;EAMA;;;EAFA,iBAAA,YAqBA;EAnBA,iBAAA,YA0BA;EAxBA,KAAA;EA+BA;;;;EA1BA,gBAAA;EA2gCD;;;;;EArgCC,gBAAA;EA0BuE;;;;;EApBvE,WAAA,GAAc,WAAA;;;;;;;EAOd,gBAAA,GAAmB,MAAA;;;;;;;EAOnB,eAAA,GAAkB,eAAA;AAAA;;;;cAMP,YAAA,GAAsB,OAAA,UAAiB,OAAA,GAAU,WAAA,KAAW,OAAA"}
|
|
@@ -30,6 +30,14 @@ declare const setIntlayerConfigCompilerOutput: (content: string, extension: stri
|
|
|
30
30
|
* (JSON cannot reference `process.env`).
|
|
31
31
|
*/
|
|
32
32
|
declare const enableIntlayerEditorConfig: (content: string) => string;
|
|
33
|
+
/**
|
|
34
|
+
* Detects whether a Vite config already wires in an Intlayer plugin — either the
|
|
35
|
+
* base `vite-intlayer` plugin or one of the compat adapters (e.g.
|
|
36
|
+
* `reactI18nextVitePlugin` from `@intlayer/react-i18next/plugin`). The compat
|
|
37
|
+
* plugins internally wrap `intlayer()`, so a standalone `intlayer()` must not be
|
|
38
|
+
* appended when one is already present, otherwise the plugin runs twice.
|
|
39
|
+
*/
|
|
40
|
+
declare const hasIntlayerVitePlugin: (content: string) => boolean;
|
|
33
41
|
declare const updateViteConfig: (content: string, extension: string) => string;
|
|
34
42
|
declare const updateAstroConfig: (content: string, extension: string) => string;
|
|
35
43
|
declare const updateNextConfig: (content: string, extension: string) => string;
|
|
@@ -104,5 +112,5 @@ declare const updateNextConfigForNextIntl: (content: string, extension: string)
|
|
|
104
112
|
*/
|
|
105
113
|
declare const updateIntlayerConfigWithSyncPlugin: (content: string, extension: string, syncConfig: CompatSyncConfig) => string;
|
|
106
114
|
//#endregion
|
|
107
|
-
export { RoutingMode, enableIntlayerEditorConfig, getMetroConfigTemplate, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n };
|
|
115
|
+
export { RoutingMode, enableIntlayerEditorConfig, getMetroConfigTemplate, hasIntlayerVitePlugin, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n };
|
|
108
116
|
//# sourceMappingURL=configManipulation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configManipulation.d.ts","names":[],"sources":["../../../../src/init/utils/configManipulation.ts"],"mappings":";;;;;KAYY,WAAA,GAAc,aAAA;AAA1B;;;;;AA0FA;;AA1FA,cA0Fa,4BAAA,GACX,OAAA,UACA,SAAA,UACA,IAAA,EAAM,WAAA;;;;;;;;AA0CR;cAAa,+BAAA,GACX,OAAA,UACA,SAAA,UACA,cAAA;;;;;;;;AAyCF;cAAa,0BAAA,GAA8B,OAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"configManipulation.d.ts","names":[],"sources":["../../../../src/init/utils/configManipulation.ts"],"mappings":";;;;;KAYY,WAAA,GAAc,aAAA;AAA1B;;;;;AA0FA;;AA1FA,cA0Fa,4BAAA,GACX,OAAA,UACA,SAAA,UACA,IAAA,EAAM,WAAA;;;;;;;;AA0CR;cAAa,+BAAA,GACX,OAAA,UACA,SAAA,UACA,cAAA;;;;;;;;AAyCF;cAAa,0BAAA,GAA8B,OAAA;;;;AAmN3C;;;;cAAa,qBAAA,GAAyB,OAAA;AAAA,cAIzB,gBAAA,GACX,OAAA,UACA,SAAA;AAAA,cAmBW,iBAAA,GACX,OAAA,UACA,SAAA;AAAA,cAmBW,gBAAA,GACX,OAAA,UACA,SAAA;;;AAvBF;;;;;AAqBA;;;;;cA4Ea,iBAAA,GACX,OAAA,UACA,SAAA;;;;;AA0EF;;cAAa,sBAAA,GAA0B,MAAA;AAAA,cAgB1B,gBAAA,GAAoB,OAAA;;AAAjC;;;cA6Da,0BAAA,GACX,OAAA,UACA,SAAA;;AAFF;;;;cA+Ba,+BAAA,GACX,OAAA,UACA,SAAA,UACA,YAAA,EAAc,sBAAA;AAHhB;;;;;;;;;AAAA,cAoCa,mCAAA,GACX,OAAA,UACA,UAAA,UACA,iBAAA,UACA,eAAA;AAJF;;;;AAAA,cAwGa,gCAAA,GACX,OAAA,UACA,SAAA;;;;;cAaW,6BAAA,GAAiC,OAAA;AAf9C;;;;AAAA,cA8Ea,8BAAA,GACX,OAAA,UACA,SAAA;AAjEF;;;;;AA+DA;AA/DA,cAgFa,2BAAA,GACX,OAAA,UACA,SAAA;;;;AAFF;;cAiQa,kCAAA,GACX,OAAA,UACA,SAAA,UACA,UAAA,EAAY,gBAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"githubActions.d.ts","names":[],"sources":["../../../../src/init/utils/githubActions.ts"],"mappings":";;;;KAGY,kBAAA;EAAA,qFAEV,QAAA;EAEA,OAAA;AAAA;
|
|
1
|
+
{"version":3,"file":"githubActions.d.ts","names":[],"sources":["../../../../src/init/utils/githubActions.ts"],"mappings":";;;;KAGY,kBAAA;EAAA,qFAEV,QAAA;EAEA,OAAA;AAAA;AA4KF;AAAA,cAAa,yBAAA;AAAA,cACA,yBAAA;;;AAAb;;cAMa,kBAAA,GACX,cAAA,EAAgB,cAAA,KACf,kBAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CompatSyncConfig, CompatVitePluginConfig, DetectMissingPackagesOptions, IntlayerPackageAnalysis, PackageManager, detectMissingIntlayerPackages, detectOutdatedIntlayerPackages, detectPackageManager, getInstalledPackageVersion, installPackages, isIntlayerPackageName, normalizeVersion, upgradePackages } from "./packageManager.js";
|
|
2
|
-
import { RoutingMode, enableIntlayerEditorConfig, getMetroConfigTemplate, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n } from "./configManipulation.js";
|
|
2
|
+
import { RoutingMode, enableIntlayerEditorConfig, getMetroConfigTemplate, hasIntlayerVitePlugin, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n } from "./configManipulation.js";
|
|
3
3
|
import { ensureNamedImport, firstInsertIndex, isModuleScopeBinding } from "./astImports.js";
|
|
4
4
|
import { JsonLocalePattern, JsonLocalePatternType, LinguiCatalogPattern, NextIntlMessagesPattern, detectJsonLocalePattern, detectLinguiCatalogPattern, detectNextIntlMessagesPattern, ensureDirectory, exists, readFileFromRoot, writeFileToRoot } from "./fileSystem.js";
|
|
5
5
|
import { GITHUB_FILL_WORKFLOW_PATH, GITHUB_TEST_WORKFLOW_PATH, GithubWorkflowFile, getGithubWorkflows } from "./githubActions.js";
|
|
@@ -7,4 +7,4 @@ import { parseJSONWithComments } from "./jsonParser.js";
|
|
|
7
7
|
import { NEXT_INTLAYER_BABEL_CONFIG_CONTENT, setupNextCompilerBabelConfig } from "./nextCompilerBabel.js";
|
|
8
8
|
import { findTsConfigFiles } from "./tsConfig.js";
|
|
9
9
|
import { isVersionAtLeast } from "./version.js";
|
|
10
|
-
export { CompatSyncConfig, CompatVitePluginConfig, DetectMissingPackagesOptions, GITHUB_FILL_WORKFLOW_PATH, GITHUB_TEST_WORKFLOW_PATH, GithubWorkflowFile, IntlayerPackageAnalysis, JsonLocalePattern, JsonLocalePatternType, LinguiCatalogPattern, NEXT_INTLAYER_BABEL_CONFIG_CONTENT, NextIntlMessagesPattern, PackageManager, RoutingMode, detectJsonLocalePattern, detectLinguiCatalogPattern, detectMissingIntlayerPackages, detectNextIntlMessagesPattern, detectOutdatedIntlayerPackages, detectPackageManager, enableIntlayerEditorConfig, ensureDirectory, ensureNamedImport, exists, findTsConfigFiles, firstInsertIndex, getGithubWorkflows, getInstalledPackageVersion, getMetroConfigTemplate, installPackages, isIntlayerPackageName, isModuleScopeBinding, isVersionAtLeast, normalizeVersion, parseJSONWithComments, readFileFromRoot, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, setupNextCompilerBabelConfig, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n, upgradePackages, writeFileToRoot };
|
|
10
|
+
export { CompatSyncConfig, CompatVitePluginConfig, DetectMissingPackagesOptions, GITHUB_FILL_WORKFLOW_PATH, GITHUB_TEST_WORKFLOW_PATH, GithubWorkflowFile, IntlayerPackageAnalysis, JsonLocalePattern, JsonLocalePatternType, LinguiCatalogPattern, NEXT_INTLAYER_BABEL_CONFIG_CONTENT, NextIntlMessagesPattern, PackageManager, RoutingMode, detectJsonLocalePattern, detectLinguiCatalogPattern, detectMissingIntlayerPackages, detectNextIntlMessagesPattern, detectOutdatedIntlayerPackages, detectPackageManager, enableIntlayerEditorConfig, ensureDirectory, ensureNamedImport, exists, findTsConfigFiles, firstInsertIndex, getGithubWorkflows, getInstalledPackageVersion, getMetroConfigTemplate, hasIntlayerVitePlugin, installPackages, isIntlayerPackageName, isModuleScopeBinding, isVersionAtLeast, normalizeVersion, parseJSONWithComments, readFileFromRoot, replaceViteConfigPluginImportSource, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode, setupNextCompilerBabelConfig, updateAstroConfig, updateIntlayerConfigWithSyncPlugin, updateMetroConfig, updateNextConfig, updateNextConfigForNextI18next, updateNextConfigForNextIntl, updateNextConfigForNextTranslate, updateNuxtConfig, updateNuxtConfigForNuxtjsI18n, updateViteConfig, updateViteConfigForCompatPlugin, updateViteConfigForVueI18n, upgradePackages, writeFileToRoot };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageManager.d.ts","names":[],"sources":["../../../../src/init/utils/packageManager.ts"],"mappings":";;KAMY,cAAA;;;;;KAMA,gBAAA;EAAgB;;;;;;EAO1B,MAAA;EAyBS;;AAQX;;EA5BE,MAAA;EA4BgC;;;;EAvBhC,cAAA;EAuCE;;;AAKJ;;;;;;;;;;;EA7BE,SAAA;AAAA;;;;;AA+FF;KAvFY,sBAAA;oFAEV,kBAAA,UA2FA;EAzFA,mBAAA;EAgGmB;;;AAGrB;;;;EA3FE,kBAAA;IA8FC,iDA5FC,UAAA,
|
|
1
|
+
{"version":3,"file":"packageManager.d.ts","names":[],"sources":["../../../../src/init/utils/packageManager.ts"],"mappings":";;KAMY,cAAA;;;;;KAMA,gBAAA;EAAgB;;;;;;EAO1B,MAAA;EAyBS;;AAQX;;EA5BE,MAAA;EA4BgC;;;;EAvBhC,cAAA;EAuCE;;;AAKJ;;;;;;;;;;;EA7BE,SAAA;AAAA;;;;;AA+FF;KAvFY,sBAAA;oFAEV,kBAAA,UA2FA;EAzFA,mBAAA;EAgGmB;;;AAGrB;;;;EA3FE,kBAAA;IA8FC,iDA5FC,UAAA,UA2aH;IAzaG,iBAAA;EAAA;AAAA;;KAKQ,uBAAA;EAoaX,mEAlaC,iBAAA,YAwaW;EAtaX,oBAAA;;;;;;EAMA,gBAAA,EAAkB,gBAAA;EAoalB;;;AAcF;;EA5aE,sBAAA,EAAwB,sBAAA;AAAA;;AAwb1B;;;cAjba,oBAAA,GAAwB,OAAA,aAAkB,cAAA;;AA4bvD;;;;;KAjZY,4BAAA;EA4bX;;;;;EAtbC,mBAAA;EAuaA;;;AAsBF;;;EAtbE,gBAAA,GAAmB,MAAA;AAAA;AAAA,cAGR,6BAAA,GACX,eAAA,EAAiB,MAAA,kBACjB,OAAA,GAAS,4BAAA,KACR,uBAAA;;;;;cAqVU,eAAA,GACX,OAAA,UACA,QAAA,YACA,cAAA,EAAgB,cAAA,EAChB,KAAA;;;;;;;;;cAcW,qBAAA,GAAyB,WAAA;;;;;;;;cAYzB,gBAAA,GAAoB,OAAA;;;;;;cAWpB,0BAAA,GACX,OAAA,UACA,WAAA;;;;;;;cAuBW,8BAAA,GACX,OAAA,UACA,YAAA,EAAc,MAAA,kBACd,aAAA;;;;;;cAsBW,eAAA,GACX,OAAA,UACA,QAAA,YACA,cAAA,EAAgB,cAAA,EAChB,aAAA,UACA,KAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ContentAdapter, FormatCodec, SyncContent, SyncPluginContext } from "./types.js";
|
|
2
|
+
import { FilePathPattern } from "@intlayer/types/filePathPattern";
|
|
3
|
+
|
|
4
|
+
//#region src/syncPluginKit/createFileAdapter.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Discovery strategy of the file adapter:
|
|
7
|
+
* - `strict`: keep only files whose path rebuilds identically from the source
|
|
8
|
+
* pattern, and fabricate entries for missing locales/keys so every declared
|
|
9
|
+
* locale has a write-back target (sync plugins).
|
|
10
|
+
* - `inclusive`: keep every glob match without fabricating missing entries
|
|
11
|
+
* (read-only load plugins, whose patterns may contain free `**` globs).
|
|
12
|
+
*/
|
|
13
|
+
type FileAdapterDiscovery = 'strict' | 'inclusive';
|
|
14
|
+
type CreateFileAdapterOptions = {
|
|
15
|
+
/**
|
|
16
|
+
* Location of the files, as a static string, a templated string
|
|
17
|
+
* (e.g. `./messages/{{locale}}/{{key}}.json`) or a function building the
|
|
18
|
+
* path from the key and locale.
|
|
19
|
+
*/
|
|
20
|
+
source: FilePathPattern;
|
|
21
|
+
/**
|
|
22
|
+
* Format of the files: string payload ↔ structured content.
|
|
23
|
+
*/
|
|
24
|
+
codec: FormatCodec;
|
|
25
|
+
/**
|
|
26
|
+
* Optional override of how one file is read and parsed. Defaults to a plain
|
|
27
|
+
* utf-8 read followed by `codec.parse`, returning `undefined` for missing or
|
|
28
|
+
* unreadable files. Adapters needing richer loading (e.g. JSON5 or
|
|
29
|
+
* transpiled TS sources) provide their own implementation here.
|
|
30
|
+
*/
|
|
31
|
+
readEntry?: (absoluteFilePath: string, context: SyncPluginContext) => Promise<SyncContent | undefined>;
|
|
32
|
+
/**
|
|
33
|
+
* Discovery strategy. Defaults to `'strict'`.
|
|
34
|
+
*/
|
|
35
|
+
discovery?: FileAdapterDiscovery;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Create a filesystem {@link ContentAdapter} for `createSyncPlugin`.
|
|
39
|
+
*
|
|
40
|
+
* Handles glob discovery of the source pattern, key/locale extraction from
|
|
41
|
+
* paths, base-directory resolution, and change-detected atomic writes.
|
|
42
|
+
*/
|
|
43
|
+
declare const createFileAdapter: (options: CreateFileAdapterOptions) => ContentAdapter;
|
|
44
|
+
/**
|
|
45
|
+
* Default `readEntry` implementation: plain utf-8 read followed by the given
|
|
46
|
+
* parser. Returns `undefined` for missing or unreadable files.
|
|
47
|
+
*/
|
|
48
|
+
declare const createFileReader: (parse: (raw: string) => SyncContent) => (absoluteFilePath: string) => Promise<SyncContent | undefined>;
|
|
49
|
+
//#endregion
|
|
50
|
+
export { CreateFileAdapterOptions, FileAdapterDiscovery, createFileAdapter, createFileReader };
|
|
51
|
+
//# sourceMappingURL=createFileAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createFileAdapter.d.ts","names":[],"sources":["../../../src/syncPluginKit/createFileAdapter.ts"],"mappings":";;;;;;AAyBA;;;;;AAEA;KAFY,oBAAA;AAAA,KAEA,wBAAA;EAMF;;;;;EAAR,MAAA,EAAQ,eAAA;EAqBwB;;;EAhBhC,KAAA,EAAO,WAAA;EAAP;;;;;;EAQA,SAAA,IACE,gBAAA,UACA,OAAA,EAAS,iBAAA,KACN,OAAA,CAAQ,WAAA;EAAA;;;EAKb,SAAA,GAAY,oBAAA;AAAA;AAYd;;;;;;AAAA,cAAa,iBAAA,GACX,OAAA,EAAS,wBAAA,KACR,cAAA;;;AAwNH;;cAAa,gBAAA,GACV,KAAA,GAAQ,GAAA,aAAgB,WAAA,MAClB,gBAAA,aAA2B,OAAA,CAAQ,WAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CreateSyncPluginOptions } from "./types.js";
|
|
2
|
+
import { Plugin } from "@intlayer/types/plugin";
|
|
3
|
+
|
|
4
|
+
//#region src/syncPluginKit/createSyncPlugin.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Build an Intlayer {@link Plugin} from a transport adapter.
|
|
7
|
+
*
|
|
8
|
+
* The factory implements the three plugin hooks once — ingestion
|
|
9
|
+
* (`loadDictionaries`), content-declaration reformatting (`formatOutput`) and
|
|
10
|
+
* write-back (`afterBuild`) — so adapters only describe *where* content lives
|
|
11
|
+
* (filesystem, TMS such as Crowdin, extra CMS…) and codecs only describe the
|
|
12
|
+
* payload format. Write-back only processes dictionaries whose `location`
|
|
13
|
+
* matches this plugin instance, so adapters never see foreign content.
|
|
14
|
+
*/
|
|
15
|
+
declare const createSyncPlugin: (options: CreateSyncPluginOptions) => Plugin;
|
|
16
|
+
//#endregion
|
|
17
|
+
export { createSyncPlugin };
|
|
18
|
+
//# sourceMappingURL=createSyncPlugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSyncPlugin.d.ts","names":[],"sources":["../../../src/syncPluginKit/createSyncPlugin.ts"],"mappings":";;;;;;AAuCA;;;;;;;;cAAa,gBAAA,GAAoB,OAAA,EAAS,uBAAA,KAA0B,MAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Locale } from "@intlayer/types/allLocales";
|
|
2
|
+
|
|
3
|
+
//#region src/syncPluginKit/extractKeyAndLocaleFromPath.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Extract the dictionary key and locale of a file path by matching it against
|
|
6
|
+
* a mask pattern where `{{__KEY__}}` and `{{__LOCALE__}}` mark the positions
|
|
7
|
+
* of the key and locale segments.
|
|
8
|
+
*
|
|
9
|
+
* Returns `null` when the path does not match the mask, or when the mask
|
|
10
|
+
* contains no placeholder at all (no named capture group can be produced).
|
|
11
|
+
* Missing placeholders fall back to `'index'` for the key and to
|
|
12
|
+
* `defaultLocale` for the locale.
|
|
13
|
+
*/
|
|
14
|
+
declare const extractKeyAndLocaleFromPath: (filePath: string, maskPattern: string, locales: Locale[], defaultLocale: Locale) => {
|
|
15
|
+
key: string;
|
|
16
|
+
locale: Locale;
|
|
17
|
+
} | null;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { extractKeyAndLocaleFromPath };
|
|
20
|
+
//# sourceMappingURL=extractKeyAndLocaleFromPath.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractKeyAndLocaleFromPath.d.ts","names":[],"sources":["../../../src/syncPluginKit/extractKeyAndLocaleFromPath.ts"],"mappings":";;;;;AAeA;;;;;;;;cAAa,2BAAA,GACX,QAAA,UACA,WAAA,UACA,OAAA,EAAS,MAAA,IACT,aAAA,EAAe,MAAA;EACZ,GAAA;EAAa,MAAA,EAAQ,MAAA;AAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FilePathPatternContext } from "@intlayer/types/filePathPattern";
|
|
2
|
+
|
|
3
|
+
//#region src/syncPluginKit/filePathPatternHelpers.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Build the context handed to `parseFilePathPattern` from the only two
|
|
6
|
+
* variables sync plugins resolve: the dictionary key and the locale.
|
|
7
|
+
*
|
|
8
|
+
* `FilePathPatternContext` declares extra fields (`fileName`, `extension`,
|
|
9
|
+
* `format`…) that only apply to content-declaration paths; sync-plugin
|
|
10
|
+
* patterns never reference them, so this single cast keeps the partial
|
|
11
|
+
* context in one audited place instead of scattering `as any` at call sites.
|
|
12
|
+
*/
|
|
13
|
+
declare const buildFilePathPatternContext: (key: string, locale?: string) => FilePathPatternContext;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { buildFilePathPatternContext };
|
|
16
|
+
//# sourceMappingURL=filePathPatternHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filePathPatternHelpers.d.ts","names":[],"sources":["../../../src/syncPluginKit/filePathPatternHelpers.ts"],"mappings":";;;;;AAWA;;;;;;;cAAa,2BAAA,GACX,GAAA,UACA,MAAA,cACC,sBAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ContentAdapter, ContentEntry, ContentTarget, CreateSyncPluginOptions, FormatCodec, SyncContent, SyncDirection, SyncPluginContext } from "./types.js";
|
|
2
|
+
import { CreateFileAdapterOptions, FileAdapterDiscovery, createFileAdapter, createFileReader } from "./createFileAdapter.js";
|
|
3
|
+
import { createSyncPlugin } from "./createSyncPlugin.js";
|
|
4
|
+
import { extractKeyAndLocaleFromPath } from "./extractKeyAndLocaleFromPath.js";
|
|
5
|
+
import { buildFilePathPatternContext } from "./filePathPatternHelpers.js";
|
|
6
|
+
export { type ContentAdapter, type ContentEntry, type ContentTarget, type CreateFileAdapterOptions, type CreateSyncPluginOptions, type FileAdapterDiscovery, type FormatCodec, type SyncContent, type SyncDirection, type SyncPluginContext, buildFilePathPatternContext, createFileAdapter, createFileReader, createSyncPlugin, extractKeyAndLocaleFromPath };
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { IntlayerConfig } from "@intlayer/types/config";
|
|
2
|
+
import { DictionaryFormat } from "@intlayer/types/dictionary";
|
|
3
|
+
import { Locale } from "@intlayer/types/allLocales";
|
|
4
|
+
|
|
5
|
+
//#region src/syncPluginKit/types.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Structured dictionary content handled by sync plugins.
|
|
8
|
+
*/
|
|
9
|
+
type SyncContent = Record<string, unknown>;
|
|
10
|
+
/**
|
|
11
|
+
* Context handed to every {@link ContentAdapter} call.
|
|
12
|
+
*/
|
|
13
|
+
type SyncPluginContext = {
|
|
14
|
+
configuration: IntlayerConfig;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* One translatable resource discovered in the external system.
|
|
18
|
+
*/
|
|
19
|
+
type ContentEntry = {
|
|
20
|
+
/** Dictionary key the entry maps to. */key: string; /** Locale of the entry content. */
|
|
21
|
+
locale: Locale;
|
|
22
|
+
/**
|
|
23
|
+
* Transport-specific identifier of the entry: an absolute file path for the
|
|
24
|
+
* file adapter, a remote resource identifier for API-backed adapters.
|
|
25
|
+
*/
|
|
26
|
+
uri: string;
|
|
27
|
+
/**
|
|
28
|
+
* Absolute file path when the entry lives on the local filesystem.
|
|
29
|
+
* Leave undefined for remote entries (CMS, TMS…): the generated dictionary
|
|
30
|
+
* then carries no `filePath` and file-based hooks are skipped for it.
|
|
31
|
+
*/
|
|
32
|
+
filePath?: string;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Identifies where content must be written back by a {@link ContentAdapter}.
|
|
36
|
+
*/
|
|
37
|
+
type ContentTarget = {
|
|
38
|
+
key: string;
|
|
39
|
+
locale: Locale;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Transport layer of a sync plugin: where the entries live and how to
|
|
43
|
+
* enumerate, read and persist them (filesystem, TMS such as Crowdin, extra
|
|
44
|
+
* CMS…). Format concerns belong to {@link FormatCodec}, orchestration to
|
|
45
|
+
* `createSyncPlugin`.
|
|
46
|
+
*/
|
|
47
|
+
type ContentAdapter = {
|
|
48
|
+
/**
|
|
49
|
+
* Enumerate every entry available in the external system.
|
|
50
|
+
*/
|
|
51
|
+
list: (context: SyncPluginContext) => Promise<ContentEntry[]>;
|
|
52
|
+
/**
|
|
53
|
+
* Read and parse one entry.
|
|
54
|
+
* Return `undefined` when the entry is missing or unreadable — the plugin
|
|
55
|
+
* treats it as empty content instead of failing the build.
|
|
56
|
+
*/
|
|
57
|
+
read: (entry: ContentEntry, context: SyncPluginContext) => Promise<SyncContent | undefined>;
|
|
58
|
+
/**
|
|
59
|
+
* Serialize and persist the content of one key/locale back to the external
|
|
60
|
+
* system. Only called for plugins created with `direction: 'both'`.
|
|
61
|
+
*/
|
|
62
|
+
write: (target: ContentTarget, content: SyncContent, context: SyncPluginContext) => Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Resolve the canonical URI of a key/locale.
|
|
65
|
+
* Used by the plugin to verify ownership before reformatting a content
|
|
66
|
+
* declaration in the `formatOutput` hook. Optional: adapters without a
|
|
67
|
+
* local-file identity (remote systems) can omit it.
|
|
68
|
+
*/
|
|
69
|
+
resolveUri?: (target: ContentTarget, context: SyncPluginContext) => Promise<string>;
|
|
70
|
+
/**
|
|
71
|
+
* Template describing where entries live, with `{{key}}` / `{{locale}}`
|
|
72
|
+
* markers kept verbatim. Used as the `fill` field of generated dictionaries
|
|
73
|
+
* so Intlayer knows where translations flow back.
|
|
74
|
+
*/
|
|
75
|
+
getFillPattern?: (context: SyncPluginContext) => Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Human-readable description of the adapter source, used in log messages
|
|
78
|
+
* (e.g. the file path pattern for the file adapter).
|
|
79
|
+
*/
|
|
80
|
+
describeSource?: (context: SyncPluginContext) => Promise<string>;
|
|
81
|
+
/**
|
|
82
|
+
* Default value for the `splitKeys` behavior when the plugin options do not
|
|
83
|
+
* set it explicitly (e.g. the file adapter splits when the source pattern
|
|
84
|
+
* has no `{{key}}` segment).
|
|
85
|
+
*/
|
|
86
|
+
detectSplitKeys?: () => Promise<boolean>;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Format layer of a sync plugin: how a raw string payload maps to structured
|
|
90
|
+
* dictionary content and back (JSON, PO, XLIFF…).
|
|
91
|
+
*/
|
|
92
|
+
type FormatCodec = {
|
|
93
|
+
/**
|
|
94
|
+
* Parse a raw payload into dictionary content.
|
|
95
|
+
* May throw on malformed payloads — callers treat a throw as empty content.
|
|
96
|
+
*/
|
|
97
|
+
parse: (raw: string) => SyncContent;
|
|
98
|
+
/**
|
|
99
|
+
* Serialize dictionary content into the target format.
|
|
100
|
+
*/
|
|
101
|
+
serialize: (content: SyncContent, context: {
|
|
102
|
+
locale: Locale;
|
|
103
|
+
}) => string;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Direction of the synchronization:
|
|
107
|
+
* - `pull`: only ingest external content as dictionaries (read-only).
|
|
108
|
+
* - `both`: ingest and write the merged build output back to the source.
|
|
109
|
+
*/
|
|
110
|
+
type SyncDirection = 'pull' | 'both';
|
|
111
|
+
/**
|
|
112
|
+
* Options of `createSyncPlugin`.
|
|
113
|
+
*/
|
|
114
|
+
type CreateSyncPluginOptions = {
|
|
115
|
+
/** Plugin name reported to the Intlayer engine (e.g. `sync-json`). */name: string; /** Transport used to enumerate, read and write entries. */
|
|
116
|
+
adapter: ContentAdapter;
|
|
117
|
+
/**
|
|
118
|
+
* Synchronization direction. Defaults to `'both'`.
|
|
119
|
+
* With `'pull'` the plugin only implements `loadDictionaries`.
|
|
120
|
+
*/
|
|
121
|
+
direction?: SyncDirection;
|
|
122
|
+
/**
|
|
123
|
+
* Identifier of the plugin instance stored on each generated dictionary.
|
|
124
|
+
* Dictionaries are routed back to their owning plugin instance through this
|
|
125
|
+
* value during write-back, so it must be unique per instance.
|
|
126
|
+
*/
|
|
127
|
+
location: string;
|
|
128
|
+
/**
|
|
129
|
+
* Priority of the generated dictionaries when merging with other sources
|
|
130
|
+
* (`.content` files have priority 0). Defaults to 0.
|
|
131
|
+
*/
|
|
132
|
+
priority?: number; /** Content format of the dictionaries (e.g. `'icu'`, `'po'`). */
|
|
133
|
+
format?: DictionaryFormat;
|
|
134
|
+
/**
|
|
135
|
+
* Whether each top-level key of an entry becomes its own dictionary instead
|
|
136
|
+
* of a single dictionary holding the whole entry (the `next-intl` /
|
|
137
|
+
* `react-intl` namespace model). When omitted, falls back to
|
|
138
|
+
* {@link ContentAdapter.detectSplitKeys}, then to `false`.
|
|
139
|
+
*/
|
|
140
|
+
splitKeys?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Fixed locale applied to every generated dictionary, overriding the locale
|
|
143
|
+
* discovered per entry.
|
|
144
|
+
*/
|
|
145
|
+
localeOverride?: Locale;
|
|
146
|
+
};
|
|
147
|
+
//#endregion
|
|
148
|
+
export { ContentAdapter, ContentEntry, ContentTarget, CreateSyncPluginOptions, FormatCodec, SyncContent, SyncDirection, SyncPluginContext };
|
|
149
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/syncPluginKit/types.ts"],"mappings":";;;;;;;AAOA;KAAY,WAAA,GAAc,MAAA;;;;KAKd,iBAAA;EACV,aAAA,EAAe,cAAA;AAAA;;;AAMjB;KAAY,YAAA;0CAEV,GAAA;EAEA,MAAA,EAAQ,MAAA;EAAA;;;;EAKR,GAAA;EAYU;;;;;EANV,QAAA;AAAA;;;AAiBF;KAXY,aAAA;EACV,GAAA;EACA,MAAA,EAAQ,MAAA;AAAA;;;;;;;KASE,cAAA;EAuBC;;;EAnBX,IAAA,GAAO,OAAA,EAAS,iBAAA,KAAsB,OAAA,CAAQ,YAAA;EA+BzC;;;;;EAxBL,IAAA,GACE,KAAA,EAAO,YAAA,EACP,OAAA,EAAS,iBAAA,KACN,OAAA,CAAQ,WAAA;EAyCkB;;;;EAnC/B,KAAA,GACE,MAAA,EAAQ,aAAA,EACR,OAAA,EAAS,WAAA,EACT,OAAA,EAAS,iBAAA,KACN,OAAA;EApBiC;;;;;;EA4BtC,UAAA,IACE,MAAA,EAAQ,aAAA,EACR,OAAA,EAAS,iBAAA,KACN,OAAA;EArBA;;;;;EA4BL,cAAA,IAAkB,OAAA,EAAS,iBAAA,KAAsB,OAAA;EApB/C;;;;EA0BF,cAAA,IAAkB,OAAA,EAAS,iBAAA,KAAsB,OAAA;EAfvC;;;;;EAsBV,eAAA,SAAwB,OAAA;AAAA;;;;;KAOd,WAAA;EAduC;;;;EAmBjD,KAAA,GAAQ,GAAA,aAAgB,WAAA;EALd;;;EAUV,SAAA,GAAY,OAAA,EAAS,WAAA,EAAa,OAAA;IAAW,MAAA,EAAQ,MAAA;EAAA;AAAA;;;;;;KAQ3C,aAAA;;;;KAKA,uBAAA;EAbmD,sEAe7D,IAAA,UAPU;EAUV,OAAA,EAAS,cAAA;;;;AALX;EAWE,SAAA,GAAY,aAAA;;;;;;EAOZ,QAAA;EAuBuB;;;;EAjBvB,QAAA,WAbY;EAgBZ,MAAA,GAAS,gBAAA;EAHT;;;;;;EAWA,SAAA;EAMuB;;;;EAAvB,cAAA,GAAiB,MAAA;AAAA"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
//#region src/utils/runParallel/index.d.ts
|
|
2
2
|
type ParallelHandle = {
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Terminate the child and its whole process group.
|
|
5
|
+
* @param signal Signal to send (default `SIGTERM`). Pass `SIGKILL` to force-kill
|
|
6
|
+
* a child that ignores graceful termination.
|
|
7
|
+
*/
|
|
8
|
+
kill: (signal?: NodeJS.Signals) => void;
|
|
4
9
|
result: Promise<any>;
|
|
5
10
|
commandText: string;
|
|
6
11
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/utils/runParallel/index.ts"],"mappings":";KAIY,cAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../../src/utils/runParallel/index.ts"],"mappings":";KAIY,cAAA;EAAA;;;;;EAMV,IAAA,GAAO,MAAA,GAAS,MAAA,CAAO,OAAA;EACvB,MAAA,EAAQ,OAAA;EACR,WAAA;AAAA;;;;;cAOW,WAAA,GAAe,IAAA,yBAA2B,cAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watcher.d.ts","names":[],"sources":["../../src/watcher.ts"],"mappings":";;;;KAuDK,YAAA;EACH,aAAA,GAAgB,cAAA;EAChB,aAAA,GAAgB,uBAAA;EAChB,WAAA;EACA,UAAA;AAAA;AAAA,cAsBW,KAAA,GAAe,OAAA,GAAU,YAAA,KAAY,OAAA;qBAkDN,OAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","names":[],"sources":["../../src/watcher.ts"],"mappings":";;;;KAuDK,YAAA;EACH,aAAA,GAAgB,cAAA;EAChB,aAAA,GAAgB,uBAAA;EAChB,WAAA;EACA,UAAA;AAAA;AAAA,cAsBW,KAAA,GAAe,OAAA,GAAU,YAAA,KAAY,OAAA;qBAkDN,OAAA;AAAA;AAAA,cA8P/B,qBAAA,GAA+B,OAAA,GAAU,YAAA,KAAY,OAAA"}
|