@intlayer/cli 9.5.3 → 9.5.4
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/README.md +8 -8
- package/dist/cjs/editor.cjs +1 -1
- package/dist/cjs/extract.cjs +2 -2
- package/dist/cjs/extract.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +1 -1
- package/dist/cjs/fill/listTranslationsTasks.cjs +2 -2
- package/dist/cjs/fill/listTranslationsTasks.cjs.map +1 -1
- package/dist/cjs/fill/translateDictionary.cjs +4 -4
- package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
- package/dist/cjs/getTargetDictionary.cjs +2 -2
- package/dist/cjs/getTargetDictionary.cjs.map +1 -1
- package/dist/cjs/index.cjs +9 -9
- package/dist/cjs/init.cjs +1 -1
- package/dist/cjs/listContentDeclaration.cjs +2 -2
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +2 -2
- package/dist/cjs/liveSync.cjs.map +1 -1
- package/dist/cjs/pull.cjs +4 -4
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/push.cjs +3 -3
- package/dist/cjs/push/push.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +1 -1
- package/dist/cjs/test/listMissingTranslations.cjs +2 -2
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
- package/dist/cjs/translateDoc/translateFile.cjs +1 -1
- package/dist/cjs/utils/checkAccess.cjs +1 -1
- package/dist/cjs/utils/getOutputFilePath.cjs +1 -1
- package/dist/esm/editor.mjs +1 -1
- package/dist/esm/extract.mjs +1 -1
- package/dist/esm/extract.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +1 -1
- package/dist/esm/fill/listTranslationsTasks.mjs +1 -1
- package/dist/esm/fill/listTranslationsTasks.mjs.map +1 -1
- package/dist/esm/fill/translateDictionary.mjs +3 -3
- package/dist/esm/fill/translateDictionary.mjs.map +1 -1
- package/dist/esm/getTargetDictionary.mjs +1 -1
- package/dist/esm/getTargetDictionary.mjs.map +1 -1
- package/dist/esm/index.mjs +9 -9
- package/dist/esm/init.mjs +1 -1
- package/dist/esm/listContentDeclaration.mjs +1 -1
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +1 -1
- package/dist/esm/liveSync.mjs.map +1 -1
- package/dist/esm/pull.mjs +3 -3
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/push.mjs +2 -2
- package/dist/esm/push/push.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +1 -1
- package/dist/esm/test/listMissingTranslations.mjs +1 -1
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
- package/dist/esm/translateDoc/translateFile.mjs +1 -1
- package/dist/esm/utils/checkAccess.mjs +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs +1 -1
- package/package.json +12 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"liveSync.cjs","names":["getAppLogger","buildDictionary","getConfiguration","runParallel","IntlayerEventListener","colorize","ANSIColors","createServer","getDictionaries","getLocalizedContent","getUnmergedDictionaries","packageJson"],"sources":["../../src/liveSync.ts"],"sourcesContent":["import { createServer } from 'node:http';\n// @ts-ignore: @intlayer/backend is not built yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport packageJson from '@intlayer/config/package.json' with { type: 'json' };\nimport { getLocalizedContent } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { buildDictionary } from '@intlayer/engine/build';\nimport { type ParallelHandle, runParallel } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { IntlayerEventListener } from './IntlayerEventListener';\n\ntype LiveSyncOptions = {\n with?: string | string[];\n configOptions?: GetConfigurationOptions;\n};\n\nconst writeDictionary = async (\n dictionary: DictionaryAPI,\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n appLogger(`Writing dictionary ${dictionary.key}`);\n await buildDictionary([dictionary], configuration);\n};\n\nexport const liveSync = async (options?: LiveSyncOptions) => {\n const configuration = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n\n const { liveSyncPort, liveSyncURL } = configuration.editor;\n\n let parallelProcess: ParallelHandle | null = null;\n let eventListener: IntlayerEventListener | null = null;\n let _isHotReloadConnected = false;\n let _connectionStatus = 'disconnected'; // 'connected', 'connecting', 'reconnecting', 'disconnected', 'error'\n\n // Start the parallel process if provided\n if (options?.with) {\n parallelProcess = runParallel(options.with);\n // Handle the promise to avoid unhandled rejection\n parallelProcess.result.catch(() => {\n // Parallel process failed or was terminated\n });\n }\n\n // Initialize the event listener for hot reload if configured\n if (\n configuration.editor.liveSync &&\n configuration.editor.backendURL &&\n configuration.editor.clientId &&\n configuration.editor.clientSecret\n ) {\n eventListener = new IntlayerEventListener(configuration);\n _connectionStatus = 'connecting';\n\n // Set up connection callbacks\n eventListener.onConnectionOpen = () => {\n _connectionStatus = 'connected';\n _isHotReloadConnected = true;\n appLogger('Live sync connection established');\n };\n\n eventListener.onConnectionError = (error) => {\n _connectionStatus = 'error';\n _isHotReloadConnected = false;\n const errorEvent = error as any;\n appLogger(\n `Live sync connection error: ${errorEvent.message ?? 'Unknown error'}`,\n {\n level: 'warn',\n }\n );\n\n // If this is a \"terminated: other side closed\" error, it's likely a server restart\n if (\n errorEvent.message?.includes('terminated') ||\n errorEvent.message?.includes('closed')\n ) {\n appLogger(\n 'Server connection was terminated, automatic reconnection will be attempted...',\n {\n level: 'info',\n }\n );\n _connectionStatus = 'reconnecting';\n }\n };\n\n // Set up dictionary change callbacks\n eventListener.onDictionaryAdded = (dictionary) =>\n writeDictionary(dictionary, configuration);\n eventListener.onDictionaryChange = (dictionary) =>\n writeDictionary(dictionary, configuration);\n eventListener.onDictionaryDeleted = (dictionary) =>\n writeDictionary(dictionary, configuration);\n\n try {\n await eventListener.initialize();\n } catch (error) {\n _connectionStatus = 'error';\n _isHotReloadConnected = false;\n appLogger('Failed to initialize IntlayerEventListener:', {\n level: 'error',\n });\n appLogger(\n `Error: ${error instanceof Error ? error.message : String(error)}`,\n {\n level: 'error',\n }\n );\n }\n } else if (!configuration.editor.liveSync) {\n appLogger(\n `Hot reload is ${colorize('disabled', ANSIColors.RED)}. Please enable it in the configuration (editor.liveSync).`\n );\n } else if (\n !configuration.editor.clientId ||\n !configuration.editor.clientSecret\n ) {\n appLogger(\n 'Missing client credentials for hot reload. Please configure clientId and clientSecret'\n );\n }\n\n const server = createServer(async (req, res) => {\n // Handle CORS preflight requests\n if (req.method === 'OPTIONS') {\n res.writeHead(200, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n\n res.end();\n return;\n }\n\n if (req.url?.startsWith('/dictionaries')) {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n const dictionaries = getDictionaries(configuration);\n\n const prefix = '/dictionaries/';\n if (req.url.startsWith(prefix)) {\n const [key, locale] = decodeURIComponent(req.url)\n .slice(prefix.length)\n .split('/');\n\n if (!key) {\n res.writeHead(404);\n res.end('Not Found');\n return;\n }\n\n const dictionary = dictionaries[key] ?? null;\n\n if (!dictionary) {\n res.writeHead(404);\n res.end('Not Found');\n return;\n }\n\n if (locale) {\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n const sourceLocaleContent = getLocalizedContent(\n dictionary.content,\n locale,\n {\n dictionaryKey: key,\n keyPath: [],\n }\n );\n\n res.end(JSON.stringify(sourceLocaleContent));\n return;\n }\n\n res.end(JSON.stringify(dictionary));\n return;\n }\n\n res.end(JSON.stringify(dictionaries));\n return;\n }\n\n if (req.url?.startsWith('/unmerged_dictionaries')) {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n const unmergedDictionaries = getUnmergedDictionaries(configuration);\n\n const prefix = '/unmerged_dictionaries/';\n if (req.url.startsWith(prefix)) {\n const key = decodeURIComponent(req.url.slice(prefix.length));\n const one = unmergedDictionaries[key] ?? null;\n\n res.end(JSON.stringify(one));\n return;\n }\n\n res.end(JSON.stringify(unmergedDictionaries));\n return;\n }\n\n if (req.url === '/configuration') {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n res.end(JSON.stringify(configuration));\n return;\n }\n\n if (req.url === '/health') {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n });\n res.end(JSON.stringify({ status: 'ok' }));\n return;\n }\n\n res.end('Not found');\n return;\n });\n\n const getLiveSyncParam = () => {\n if (!configuration.editor.liveSync) return '\\x1b[31m✗ Disabled\\x1b[0m';\n\n return '\\x1b[32m✓ Enabled\\x1b[0m';\n };\n server.listen(liveSyncPort, () => {\n console.log(`\n \\x1b[1;90mINTLAYER v${packageJson.version}\\x1b[0m\n \n Live server running at: \\x1b[90m${liveSyncURL}\\x1b[0m\n - Backend URL: \\x1b[90m${configuration.editor.backendURL ?? '-'}\\x1b[0m\n - Live sync: ${getLiveSyncParam()}\n - Parallel process: ${options?.with ? `\\x1b[90m${Array.isArray(options.with) ? options.with.join(' ') : options.with}\\x1b[0m` : '-'}\n - Access key: ${configuration.editor.clientId ?? '-'}\n `);\n });\n\n // Cleanup function to terminate child process and event listener when the main process exits\n const cleanup = () => {\n // Clean up event listener\n if (eventListener) {\n appLogger('Closing SSE connection...');\n eventListener.cleanup();\n }\n\n if (parallelProcess) {\n parallelProcess.kill();\n }\n\n server.close(() => {\n appLogger('Live sync server stopped');\n process.exit(0);\n });\n };\n\n // Handle process termination signals\n process.on('SIGINT', cleanup);\n process.on('SIGTERM', cleanup);\n process.on('exit', cleanup);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"liveSync.cjs","names":["getAppLogger","buildDictionary","getConfiguration","runParallel","IntlayerEventListener","colorize","ANSIColors","createServer","getDictionaries","getLocalizedContent","getUnmergedDictionaries","packageJson"],"sources":["../../src/liveSync.ts"],"sourcesContent":["import { createServer } from 'node:http';\n// @ts-ignore: @intlayer/backend is not built yet\nimport type { DictionaryAPI } from '@intlayer/backend';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport packageJson from '@intlayer/config/package.json' with { type: 'json' };\nimport { getLocalizedContent } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { buildDictionary } from '@intlayer/engine/build';\nimport { type ParallelHandle, runParallel } from '@intlayer/engine/utils';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { IntlayerEventListener } from './IntlayerEventListener';\n\ntype LiveSyncOptions = {\n with?: string | string[];\n configOptions?: GetConfigurationOptions;\n};\n\nconst writeDictionary = async (\n dictionary: DictionaryAPI,\n configuration: IntlayerConfig\n) => {\n const appLogger = getAppLogger(configuration);\n appLogger(`Writing dictionary ${dictionary.key}`);\n await buildDictionary([dictionary], configuration);\n};\n\nexport const liveSync = async (options?: LiveSyncOptions) => {\n const configuration = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(configuration);\n\n const { liveSyncPort, liveSyncURL } = configuration.editor;\n\n let parallelProcess: ParallelHandle | null = null;\n let eventListener: IntlayerEventListener | null = null;\n let _isHotReloadConnected = false;\n let _connectionStatus = 'disconnected'; // 'connected', 'connecting', 'reconnecting', 'disconnected', 'error'\n\n // Start the parallel process if provided\n if (options?.with) {\n parallelProcess = runParallel(options.with);\n // Handle the promise to avoid unhandled rejection\n parallelProcess.result.catch(() => {\n // Parallel process failed or was terminated\n });\n }\n\n // Initialize the event listener for hot reload if configured\n if (\n configuration.editor.liveSync &&\n configuration.editor.backendURL &&\n configuration.editor.clientId &&\n configuration.editor.clientSecret\n ) {\n eventListener = new IntlayerEventListener(configuration);\n _connectionStatus = 'connecting';\n\n // Set up connection callbacks\n eventListener.onConnectionOpen = () => {\n _connectionStatus = 'connected';\n _isHotReloadConnected = true;\n appLogger('Live sync connection established');\n };\n\n eventListener.onConnectionError = (error) => {\n _connectionStatus = 'error';\n _isHotReloadConnected = false;\n const errorEvent = error as any;\n appLogger(\n `Live sync connection error: ${errorEvent.message ?? 'Unknown error'}`,\n {\n level: 'warn',\n }\n );\n\n // If this is a \"terminated: other side closed\" error, it's likely a server restart\n if (\n errorEvent.message?.includes('terminated') ||\n errorEvent.message?.includes('closed')\n ) {\n appLogger(\n 'Server connection was terminated, automatic reconnection will be attempted...',\n {\n level: 'info',\n }\n );\n _connectionStatus = 'reconnecting';\n }\n };\n\n // Set up dictionary change callbacks\n eventListener.onDictionaryAdded = (dictionary) =>\n writeDictionary(dictionary, configuration);\n eventListener.onDictionaryChange = (dictionary) =>\n writeDictionary(dictionary, configuration);\n eventListener.onDictionaryDeleted = (dictionary) =>\n writeDictionary(dictionary, configuration);\n\n try {\n await eventListener.initialize();\n } catch (error) {\n _connectionStatus = 'error';\n _isHotReloadConnected = false;\n appLogger('Failed to initialize IntlayerEventListener:', {\n level: 'error',\n });\n appLogger(\n `Error: ${error instanceof Error ? error.message : String(error)}`,\n {\n level: 'error',\n }\n );\n }\n } else if (!configuration.editor.liveSync) {\n appLogger(\n `Hot reload is ${colorize('disabled', ANSIColors.RED)}. Please enable it in the configuration (editor.liveSync).`\n );\n } else if (\n !configuration.editor.clientId ||\n !configuration.editor.clientSecret\n ) {\n appLogger(\n 'Missing client credentials for hot reload. Please configure clientId and clientSecret'\n );\n }\n\n const server = createServer(async (req, res) => {\n // Handle CORS preflight requests\n if (req.method === 'OPTIONS') {\n res.writeHead(200, {\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n\n res.end();\n return;\n }\n\n if (req.url?.startsWith('/dictionaries')) {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n const dictionaries = getDictionaries(configuration);\n\n const prefix = '/dictionaries/';\n if (req.url.startsWith(prefix)) {\n const [key, locale] = decodeURIComponent(req.url)\n .slice(prefix.length)\n .split('/');\n\n if (!key) {\n res.writeHead(404);\n res.end('Not Found');\n return;\n }\n\n const dictionary = dictionaries[key] ?? null;\n\n if (!dictionary) {\n res.writeHead(404);\n res.end('Not Found');\n return;\n }\n\n if (locale) {\n // @ts-ignore Type instantiation is excessively deep and possibly infinite\n const sourceLocaleContent = getLocalizedContent(\n dictionary.content,\n locale,\n {\n dictionaryKey: key,\n keyPath: [],\n }\n );\n\n res.end(JSON.stringify(sourceLocaleContent));\n return;\n }\n\n res.end(JSON.stringify(dictionary));\n return;\n }\n\n res.end(JSON.stringify(dictionaries));\n return;\n }\n\n if (req.url?.startsWith('/unmerged_dictionaries')) {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n const unmergedDictionaries = getUnmergedDictionaries(configuration);\n\n const prefix = '/unmerged_dictionaries/';\n if (req.url.startsWith(prefix)) {\n const key = decodeURIComponent(req.url.slice(prefix.length));\n const one = unmergedDictionaries[key] ?? null;\n\n res.end(JSON.stringify(one));\n return;\n }\n\n res.end(JSON.stringify(unmergedDictionaries));\n return;\n }\n\n if (req.url === '/configuration') {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n 'Access-Control-Allow-Origin': '*',\n 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type, Authorization',\n });\n res.end(JSON.stringify(configuration));\n return;\n }\n\n if (req.url === '/health') {\n res.writeHead(200, {\n 'Content-Type': 'application/json; charset=utf-8',\n });\n res.end(JSON.stringify({ status: 'ok' }));\n return;\n }\n\n res.end('Not found');\n return;\n });\n\n const getLiveSyncParam = () => {\n if (!configuration.editor.liveSync) return '\\x1b[31m✗ Disabled\\x1b[0m';\n\n return '\\x1b[32m✓ Enabled\\x1b[0m';\n };\n server.listen(liveSyncPort, () => {\n console.log(`\n \\x1b[1;90mINTLAYER v${packageJson.version}\\x1b[0m\n \n Live server running at: \\x1b[90m${liveSyncURL}\\x1b[0m\n - Backend URL: \\x1b[90m${configuration.editor.backendURL ?? '-'}\\x1b[0m\n - Live sync: ${getLiveSyncParam()}\n - Parallel process: ${options?.with ? `\\x1b[90m${Array.isArray(options.with) ? options.with.join(' ') : options.with}\\x1b[0m` : '-'}\n - Access key: ${configuration.editor.clientId ?? '-'}\n `);\n });\n\n // Cleanup function to terminate child process and event listener when the main process exits\n const cleanup = () => {\n // Clean up event listener\n if (eventListener) {\n appLogger('Closing SSE connection...');\n eventListener.cleanup();\n }\n\n if (parallelProcess) {\n parallelProcess.kill();\n }\n\n server.close(() => {\n appLogger('Live sync server stopped');\n process.exit(0);\n });\n };\n\n // Handle process termination signals\n process.on('SIGINT', cleanup);\n process.on('SIGTERM', cleanup);\n process.on('exit', cleanup);\n};\n"],"mappings":"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"}
|
package/dist/cjs/pull.cjs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
|
+
const require_push_pullLog = require('./push/pullLog.cjs');
|
|
3
4
|
const require_utils_checkAccess = require('./utils/checkAccess.cjs');
|
|
4
5
|
const require_utils_selectCmsEnvironment = require('./utils/selectCmsEnvironment.cjs');
|
|
5
|
-
const require_push_pullLog = require('./push/pullLog.cjs');
|
|
6
6
|
let node_fs = require("node:fs");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
9
9
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
10
10
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
11
11
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
12
|
+
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
13
|
+
let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
|
|
12
14
|
let _intlayer_engine_build = require("@intlayer/engine/build");
|
|
13
15
|
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
14
16
|
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
15
|
-
let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
|
|
16
|
-
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
17
17
|
|
|
18
18
|
//#region src/pull.ts
|
|
19
19
|
/**
|
|
@@ -28,7 +28,7 @@ const pull = async (options) => {
|
|
|
28
28
|
if (!await require_utils_checkAccess.checkCMSAuth(config)) return;
|
|
29
29
|
const intlayerAPI = await require_utils_checkAccess.getAuthenticatedAPI(config);
|
|
30
30
|
await require_utils_selectCmsEnvironment.selectCmsEnvironment(options?.configOptions?.env, intlayerAPI, config);
|
|
31
|
-
const unmergedDictionariesRecord = (0,
|
|
31
|
+
const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(config);
|
|
32
32
|
const getDictionariesUpdateTimestampResult = await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();
|
|
33
33
|
if (!getDictionariesUpdateTimestampResult.data) throw new Error("No distant dictionaries found");
|
|
34
34
|
let distantDictionariesUpdateTimeStamp = getDictionariesUpdateTimestampResult.data;
|
package/dist/cjs/pull.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.cjs","names":["getConfiguration","getAppLogger","checkCMSAuth","getAuthenticatedAPI","selectCmsEnvironment","getUnmergedDictionaries","join","getProjectRequire","existsSync","PullLogger","writeContentDeclaration","parallelize","ANSIColors"],"sources":["../../src/pull.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport {\n type DictionaryStatus,\n writeContentDeclaration,\n} from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { parallelize } from '@intlayer/engine/utils';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { PullLogger, type PullStatus } from './push/pullLog';\nimport { checkCMSAuth, getAuthenticatedAPI } from './utils/checkAccess';\nimport { selectCmsEnvironment } from './utils/selectCmsEnvironment';\n\ntype PullOptions = {\n dictionaries?: string[];\n newDictionariesPath?: string;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionaryKey: string;\n status: DictionaryStatus | 'pending' | 'fetching' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n/**\n * Fetch distant dictionaries and write them locally,\n * with progress indicators and concurrency control.\n */\nexport const pull = async (options?: PullOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n try {\n logConfigDetails(options?.configOptions);\n\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = await getAuthenticatedAPI(config);\n\n await selectCmsEnvironment(\n options?.configOptions?.env,\n intlayerAPI,\n config\n );\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n // Get remote update timestamps map\n const getDictionariesUpdateTimestampResult =\n await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();\n\n if (!getDictionariesUpdateTimestampResult.data) {\n throw new Error('No distant dictionaries found');\n }\n\n let distantDictionariesUpdateTimeStamp: Record<string, any> =\n getDictionariesUpdateTimestampResult.data;\n\n // Optional filtering by requested dictionaries\n if (options?.dictionaries) {\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) =>\n options.dictionaries?.includes(key)\n )\n );\n }\n\n // Filter by location\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) => {\n const localDictionaries = unmergedDictionariesRecord[key];\n const location =\n localDictionaries?.[0]?.location ??\n config.dictionary?.location ??\n 'remote';\n\n return location === 'remote' || location === 'hybrid';\n })\n );\n\n // Load local cached remote dictionaries (if any)\n const remoteDictionariesPath = join(\n config.system.mainDir,\n 'remote_dictionaries.cjs'\n );\n const requireFunction = config.build?.require ?? getProjectRequire();\n const remoteDictionariesRecord: Record<string, any> = existsSync(\n remoteDictionariesPath\n )\n ? (requireFunction(remoteDictionariesPath) as any)\n : {};\n\n // Determine which keys need fetching by comparing updatedAt with local cache\n const entries = Object.entries(distantDictionariesUpdateTimeStamp);\n const keysToFetch = entries\n .filter(([key, remoteUpdatedAtValue]) => {\n if (!remoteUpdatedAtValue) return true;\n\n const remoteUpdatedAt =\n typeof remoteUpdatedAtValue === 'object'\n ? (remoteUpdatedAtValue as any).updatedAt\n : remoteUpdatedAtValue;\n\n const local = (remoteDictionariesRecord as any)[key];\n if (!local) return true;\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n if (typeof localUpdatedAt !== 'number') return true;\n return remoteUpdatedAt > localUpdatedAt;\n })\n .map(([key]) => key);\n\n const cachedKeys = entries\n .filter(([key, remoteUpdatedAtValue]) => {\n const remoteUpdatedAt =\n typeof remoteUpdatedAtValue === 'object'\n ? (remoteUpdatedAtValue as any).updatedAt\n : remoteUpdatedAtValue;\n\n const local = (remoteDictionariesRecord as any)[key];\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n return (\n typeof localUpdatedAt === 'number' &&\n typeof remoteUpdatedAt === 'number' &&\n localUpdatedAt >= remoteUpdatedAt\n );\n })\n .map(([key]) => key);\n\n // Check if dictionaries list is empty\n if (entries.length === 0) {\n appLogger('No dictionaries to fetch', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Fetching dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = [\n ...cachedKeys.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'imported' as DictionaryStatus,\n })),\n ...keysToFetch.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'pending' as const,\n })),\n ];\n\n // Initialize aggregated logger\n const logger = new PullLogger();\n logger.update(\n dictionariesStatuses.map<PullStatus>((s) => ({\n dictionaryKey: s.dictionaryKey,\n status: s.status,\n }))\n );\n\n const successfullyFetchedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n const isCached =\n statusObj.status === 'imported' || statusObj.status === 'up-to-date';\n\n if (!isCached) {\n statusObj.status = 'fetching';\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'fetching' },\n ]);\n }\n\n try {\n let sourceDictionary: Dictionary | undefined;\n\n if (isCached) {\n sourceDictionary = remoteDictionariesRecord[\n statusObj.dictionaryKey\n ] as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n // Fetch the dictionary\n const getDictionaryResult =\n await intlayerAPI.dictionary.getDictionary(statusObj.dictionaryKey);\n\n sourceDictionary = getDictionaryResult.data as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n throw new Error(\n `Dictionary ${statusObj.dictionaryKey} not found on remote`\n );\n }\n\n // Check if there is a local version of this dictionary that is hybrid\n const localDictionaries =\n unmergedDictionariesRecord[statusObj.dictionaryKey];\n const localAndRemoteDictionary = localDictionaries?.find(\n (d) => d.location === 'hybrid'\n );\n\n if (localAndRemoteDictionary) {\n // We want to preserve the local properties but use the remote content\n sourceDictionary = {\n ...sourceDictionary,\n location: 'hybrid',\n filePath: localAndRemoteDictionary.filePath,\n localId: localAndRemoteDictionary.localId,\n };\n }\n\n // Now, write the dictionary to local file\n const { status } = await writeContentDeclaration(\n sourceDictionary,\n config,\n options\n );\n\n statusObj.status = status;\n logger.update([{ dictionaryKey: statusObj.dictionaryKey, status }]);\n\n successfullyFetchedDictionaries.push(sourceDictionary);\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error fetching dictionary ${statusObj.dictionaryKey}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with concurrency limit\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n // Per-dictionary summary\n const iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n case 'reimported in JSON':\n case 'new content file':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n };\n\n const colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n return ANSIColors.GREEN;\n case 'reimported in JSON':\n case 'new content file':\n return ANSIColors.YELLOW;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n };\n\n for (const s of dictionariesStatuses) {\n const icon = iconFor(s.status);\n const color = colorFor(s.status);\n appLogger(\n ` - ${s.dictionaryKey} ${ANSIColors.GREY}[${color}${icon} ${s.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,OAAO,OAAO,YAAyC;CAClE,MAAM,aAASA,wCAAiB,SAAS,aAAa;CACtD,MAAM,gBAAYC,sCAAa,MAAM;CAErC,IAAI;EACF,2CAAiB,SAAS,aAAa;EAIvC,IAAI,CAAC,MAFoBC,uCAAa,MAAM,GAE3B;EAEjB,MAAM,cAAc,MAAMC,8CAAoB,MAAM;EAEpD,MAAMC,wDACJ,SAAS,eAAe,KACxB,aACA,MACF;EAEA,MAAM,iCAA6BC,+DAAwB,MAAM;EAGjE,MAAM,uCACJ,MAAM,YAAY,WAAW,+BAA+B;EAE9D,IAAI,CAAC,qCAAqC,MACxC,MAAM,IAAI,MAAM,+BAA+B;EAGjD,IAAI,qCACF,qCAAqC;EAGvC,IAAI,SAAS,cACX,qCAAqC,OAAO,YAC1C,OAAO,QAAQ,kCAAkC,CAAC,CAAC,QAAQ,CAAC,SAC1D,QAAQ,cAAc,SAAS,GAAG,CACpC,CACF;EAIF,qCAAqC,OAAO,YAC1C,OAAO,QAAQ,kCAAkC,CAAC,CAAC,QAAQ,CAAC,SAAS;GAEnE,MAAM,WADoB,2BAA2B,IAElC,GAAG,EAAE,EAAE,YACxB,OAAO,YAAY,YACnB;GAEF,OAAO,aAAa,YAAY,aAAa;EAC/C,CAAC,CACH;EAGA,MAAM,6BAAyBC,gBAC7B,OAAO,OAAO,SACd,yBACF;EACA,MAAM,kBAAkB,OAAO,OAAO,eAAWC,0CAAkB;EACnE,MAAM,+BAAgDC,oBACpD,sBACF,IACK,gBAAgB,sBAAsB,IACvC,CAAC;EAGL,MAAM,UAAU,OAAO,QAAQ,kCAAkC;EACjE,MAAM,cAAc,QACjB,QAAQ,CAAC,KAAK,0BAA0B;GACvC,IAAI,CAAC,sBAAsB,OAAO;GAElC,MAAM,kBACJ,OAAO,yBAAyB,WAC3B,qBAA6B,YAC9B;GAEN,MAAM,QAAS,yBAAiC;GAChD,IAAI,CAAC,OAAO,OAAO;GACnB,MAAM,oBAAqB,OAAe;GAI1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GACR,IAAI,OAAO,mBAAmB,UAAU,OAAO;GAC/C,OAAO,kBAAkB;EAC3B,CAAC,CAAC,CACD,KAAK,CAAC,SAAS,GAAG;EAErB,MAAM,aAAa,QAChB,QAAQ,CAAC,KAAK,0BAA0B;GACvC,MAAM,kBACJ,OAAO,yBAAyB,WAC3B,qBAA6B,YAC9B;GAGN,MAAM,oBADS,yBAAiC,IAChB,EAAU;GAI1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GACR,OACE,OAAO,mBAAmB,YAC1B,OAAO,oBAAoB,YAC3B,kBAAkB;EAEtB,CAAC,CAAC,CACD,KAAK,CAAC,SAAS,GAAG;EAGrB,IAAI,QAAQ,WAAW,GAAG;GACxB,UAAU,4BAA4B,EACpC,OAAO,QACT,CAAC;GACD;EACF;EAEA,UAAU,wBAAwB;EAGlC,MAAM,uBAA6C,CACjD,GAAG,WAAW,KAAK,mBAAmB;GACpC;GACA,QAAQ;EACV,EAAE,GACF,GAAG,YAAY,KAAK,mBAAmB;GACrC;GACA,QAAQ;EACV,EAAE,CACJ;EAGA,MAAM,SAAS,IAAIC,gCAAW;EAC9B,OAAO,OACL,qBAAqB,KAAiB,OAAO;GAC3C,eAAe,EAAE;GACjB,QAAQ,EAAE;EACZ,EAAE,CACJ;EAEA,MAAM,kCAAgD,CAAC;EAEvD,MAAM,oBAAoB,OACxB,cACkB;GAClB,MAAM,WACJ,UAAU,WAAW,cAAc,UAAU,WAAW;GAE1D,IAAI,CAAC,UAAU;IACb,UAAU,SAAS;IACnB,OAAO,OAAO,CACZ;KAAE,eAAe,UAAU;KAAe,QAAQ;IAAW,CAC/D,CAAC;GACH;GAEA,IAAI;IACF,IAAI;IAEJ,IAAI,UACF,mBAAmB,yBACjB,UAAU;IAId,IAAI,CAAC,kBAKH,oBAAmB,MAFX,YAAY,WAAW,cAAc,UAAU,aAAa,EAE9B,CAAC;IAGzC,IAAI,CAAC,kBACH,MAAM,IAAI,MACR,cAAc,UAAU,cAAc,qBACxC;IAMF,MAAM,2BADJ,2BAA2B,UAAU,cACW,EAAE,MACjD,MAAM,EAAE,aAAa,QACxB;IAEA,IAAI,0BAEF,mBAAmB;KACjB,GAAG;KACH,UAAU;KACV,UAAU,yBAAyB;KACnC,SAAS,yBAAyB;IACpC;IAIF,MAAM,EAAE,WAAW,UAAMC,gDACvB,kBACA,QACA,OACF;IAEA,UAAU,SAAS;IACnB,OAAO,OAAO,CAAC;KAAE,eAAe,UAAU;KAAe;IAAO,CAAC,CAAC;IAElE,gCAAgC,KAAK,gBAAgB;GACvD,SAAS,OAAO;IACd,UAAU,SAAS;IACnB,UAAU,QAAQ;IAClB,UAAU,eAAe,6BAA6B,UAAU,cAAc,IAAI;IAClF,OAAO,OAAO,CACZ;KAAE,eAAe,UAAU;KAAe,QAAQ;IAAQ,CAC5D,CAAC;GACH;EACF;EAGA,UAAMC,oCAAY,sBAAsB,mBAAmB,CAAC;EAG5D,OAAO,OAAO;EAGd,MAAM,WAAW,WAAyC;GACxD,QAAQ,QAAR;IACE,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK,oBACH,OAAO;IACT,KAAK,SACH,OAAO;IACT,SACE,OAAO;GACX;EACF;EAEA,MAAM,YAAY,WAAyC;GACzD,QAAQ,QAAR;IACE,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK,cACH,OAAOC,wBAAW;IACpB,KAAK;IACL,KAAK,oBACH,OAAOA,wBAAW;IACpB,KAAK,SACH,OAAOA,wBAAW;IACpB,SACE,OAAOA,wBAAW;GACtB;EACF;EAEA,KAAK,MAAM,KAAK,sBAAsB;GACpC,MAAM,OAAO,QAAQ,EAAE,MAAM;GAC7B,MAAM,QAAQ,SAAS,EAAE,MAAM;GAC/B,UACE,MAAM,EAAE,cAAc,GAAGA,wBAAW,KAAK,GAAG,QAAQ,KAAK,GAAG,EAAE,SAASA,wBAAW,KAAK,GAAGA,wBAAW,OACvG;EACF;EAGA,KAAK,MAAM,aAAa,sBACtB,IAAI,UAAU,cACZ,UAAU,UAAU,cAAc,EAChC,OAAO,QACT,CAAC;CAGP,SAAS,OAAO;EACd,UAAU,OAAO,EACf,OAAO,QACT,CAAC;CACH;AACF"}
|
|
1
|
+
{"version":3,"file":"pull.cjs","names":["getConfiguration","getAppLogger","checkCMSAuth","getAuthenticatedAPI","selectCmsEnvironment","getUnmergedDictionaries","join","getProjectRequire","existsSync","PullLogger","writeContentDeclaration","parallelize","ANSIColors"],"sources":["../../src/pull.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getProjectRequire } from '@intlayer/config/utils';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport {\n type DictionaryStatus,\n writeContentDeclaration,\n} from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { parallelize } from '@intlayer/engine/utils';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { PullLogger, type PullStatus } from './push/pullLog';\nimport { checkCMSAuth, getAuthenticatedAPI } from './utils/checkAccess';\nimport { selectCmsEnvironment } from './utils/selectCmsEnvironment';\n\ntype PullOptions = {\n dictionaries?: string[];\n newDictionariesPath?: string;\n configOptions?: GetConfigurationOptions;\n};\n\ntype DictionariesStatus = {\n dictionaryKey: string;\n status: DictionaryStatus | 'pending' | 'fetching' | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n/**\n * Fetch distant dictionaries and write them locally,\n * with progress indicators and concurrency control.\n */\nexport const pull = async (options?: PullOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n try {\n logConfigDetails(options?.configOptions);\n\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = await getAuthenticatedAPI(config);\n\n await selectCmsEnvironment(\n options?.configOptions?.env,\n intlayerAPI,\n config\n );\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n\n // Get remote update timestamps map\n const getDictionariesUpdateTimestampResult =\n await intlayerAPI.dictionary.getDictionariesUpdateTimestamp();\n\n if (!getDictionariesUpdateTimestampResult.data) {\n throw new Error('No distant dictionaries found');\n }\n\n let distantDictionariesUpdateTimeStamp: Record<string, any> =\n getDictionariesUpdateTimestampResult.data;\n\n // Optional filtering by requested dictionaries\n if (options?.dictionaries) {\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) =>\n options.dictionaries?.includes(key)\n )\n );\n }\n\n // Filter by location\n distantDictionariesUpdateTimeStamp = Object.fromEntries(\n Object.entries(distantDictionariesUpdateTimeStamp).filter(([key]) => {\n const localDictionaries = unmergedDictionariesRecord[key];\n const location =\n localDictionaries?.[0]?.location ??\n config.dictionary?.location ??\n 'remote';\n\n return location === 'remote' || location === 'hybrid';\n })\n );\n\n // Load local cached remote dictionaries (if any)\n const remoteDictionariesPath = join(\n config.system.mainDir,\n 'remote_dictionaries.cjs'\n );\n const requireFunction = config.build?.require ?? getProjectRequire();\n const remoteDictionariesRecord: Record<string, any> = existsSync(\n remoteDictionariesPath\n )\n ? (requireFunction(remoteDictionariesPath) as any)\n : {};\n\n // Determine which keys need fetching by comparing updatedAt with local cache\n const entries = Object.entries(distantDictionariesUpdateTimeStamp);\n const keysToFetch = entries\n .filter(([key, remoteUpdatedAtValue]) => {\n if (!remoteUpdatedAtValue) return true;\n\n const remoteUpdatedAt =\n typeof remoteUpdatedAtValue === 'object'\n ? (remoteUpdatedAtValue as any).updatedAt\n : remoteUpdatedAtValue;\n\n const local = (remoteDictionariesRecord as any)[key];\n if (!local) return true;\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n if (typeof localUpdatedAt !== 'number') return true;\n return remoteUpdatedAt > localUpdatedAt;\n })\n .map(([key]) => key);\n\n const cachedKeys = entries\n .filter(([key, remoteUpdatedAtValue]) => {\n const remoteUpdatedAt =\n typeof remoteUpdatedAtValue === 'object'\n ? (remoteUpdatedAtValue as any).updatedAt\n : remoteUpdatedAtValue;\n\n const local = (remoteDictionariesRecord as any)[key];\n const localUpdatedAtRaw = (local as any)?.updatedAt as\n | number\n | string\n | undefined;\n const localUpdatedAt =\n typeof localUpdatedAtRaw === 'number'\n ? localUpdatedAtRaw\n : localUpdatedAtRaw\n ? new Date(localUpdatedAtRaw).getTime()\n : undefined;\n return (\n typeof localUpdatedAt === 'number' &&\n typeof remoteUpdatedAt === 'number' &&\n localUpdatedAt >= remoteUpdatedAt\n );\n })\n .map(([key]) => key);\n\n // Check if dictionaries list is empty\n if (entries.length === 0) {\n appLogger('No dictionaries to fetch', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Fetching dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = [\n ...cachedKeys.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'imported' as DictionaryStatus,\n })),\n ...keysToFetch.map((dictionaryKey) => ({\n dictionaryKey,\n status: 'pending' as const,\n })),\n ];\n\n // Initialize aggregated logger\n const logger = new PullLogger();\n logger.update(\n dictionariesStatuses.map<PullStatus>((s) => ({\n dictionaryKey: s.dictionaryKey,\n status: s.status,\n }))\n );\n\n const successfullyFetchedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n const isCached =\n statusObj.status === 'imported' || statusObj.status === 'up-to-date';\n\n if (!isCached) {\n statusObj.status = 'fetching';\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'fetching' },\n ]);\n }\n\n try {\n let sourceDictionary: Dictionary | undefined;\n\n if (isCached) {\n sourceDictionary = remoteDictionariesRecord[\n statusObj.dictionaryKey\n ] as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n // Fetch the dictionary\n const getDictionaryResult =\n await intlayerAPI.dictionary.getDictionary(statusObj.dictionaryKey);\n\n sourceDictionary = getDictionaryResult.data as Dictionary | undefined;\n }\n\n if (!sourceDictionary) {\n throw new Error(\n `Dictionary ${statusObj.dictionaryKey} not found on remote`\n );\n }\n\n // Check if there is a local version of this dictionary that is hybrid\n const localDictionaries =\n unmergedDictionariesRecord[statusObj.dictionaryKey];\n const localAndRemoteDictionary = localDictionaries?.find(\n (d) => d.location === 'hybrid'\n );\n\n if (localAndRemoteDictionary) {\n // We want to preserve the local properties but use the remote content\n sourceDictionary = {\n ...sourceDictionary,\n location: 'hybrid',\n filePath: localAndRemoteDictionary.filePath,\n localId: localAndRemoteDictionary.localId,\n };\n }\n\n // Now, write the dictionary to local file\n const { status } = await writeContentDeclaration(\n sourceDictionary,\n config,\n options\n );\n\n statusObj.status = status;\n logger.update([{ dictionaryKey: statusObj.dictionaryKey, status }]);\n\n successfullyFetchedDictionaries.push(sourceDictionary);\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error fetching dictionary ${statusObj.dictionaryKey}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionaryKey, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with concurrency limit\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n // Per-dictionary summary\n const iconFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n case 'reimported in JSON':\n case 'new content file':\n return '✔';\n case 'error':\n return '✖';\n default:\n return '⏲';\n }\n };\n\n const colorFor = (status: DictionariesStatus['status']) => {\n switch (status) {\n case 'fetched':\n case 'imported':\n case 'updated':\n case 'up-to-date':\n return ANSIColors.GREEN;\n case 'reimported in JSON':\n case 'new content file':\n return ANSIColors.YELLOW;\n case 'error':\n return ANSIColors.RED;\n default:\n return ANSIColors.BLUE;\n }\n };\n\n for (const s of dictionariesStatuses) {\n const icon = iconFor(s.status);\n const color = colorFor(s.status);\n appLogger(\n ` - ${s.dictionaryKey} ${ANSIColors.GREY}[${color}${icon} ${s.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAsCA,MAAa,OAAO,OAAO,YAAyC;CAClE,MAAM,aAASA,wCAAiB,SAAS,aAAa;CACtD,MAAM,gBAAYC,sCAAa,MAAM;CAErC,IAAI;EACF,2CAAiB,SAAS,aAAa;EAIvC,IAAI,CAAC,MAFoBC,uCAAa,MAAM,GAE3B;EAEjB,MAAM,cAAc,MAAMC,8CAAoB,MAAM;EAEpD,MAAMC,wDACJ,SAAS,eAAe,KACxB,aACA,MACF;EAEA,MAAM,iCAA6BC,+DAAwB,MAAM;EAGjE,MAAM,uCACJ,MAAM,YAAY,WAAW,+BAA+B;EAE9D,IAAI,CAAC,qCAAqC,MACxC,MAAM,IAAI,MAAM,+BAA+B;EAGjD,IAAI,qCACF,qCAAqC;EAGvC,IAAI,SAAS,cACX,qCAAqC,OAAO,YAC1C,OAAO,QAAQ,kCAAkC,CAAC,CAAC,QAAQ,CAAC,SAC1D,QAAQ,cAAc,SAAS,GAAG,CACpC,CACF;EAIF,qCAAqC,OAAO,YAC1C,OAAO,QAAQ,kCAAkC,CAAC,CAAC,QAAQ,CAAC,SAAS;GAEnE,MAAM,WADoB,2BAA2B,IAElC,GAAG,EAAE,EAAE,YACxB,OAAO,YAAY,YACnB;GAEF,OAAO,aAAa,YAAY,aAAa;EAC/C,CAAC,CACH;EAGA,MAAM,6BAAyBC,gBAC7B,OAAO,OAAO,SACd,yBACF;EACA,MAAM,kBAAkB,OAAO,OAAO,eAAWC,0CAAkB;EACnE,MAAM,+BAAgDC,oBACpD,sBACF,IACK,gBAAgB,sBAAsB,IACvC,CAAC;EAGL,MAAM,UAAU,OAAO,QAAQ,kCAAkC;EACjE,MAAM,cAAc,QACjB,QAAQ,CAAC,KAAK,0BAA0B;GACvC,IAAI,CAAC,sBAAsB,OAAO;GAElC,MAAM,kBACJ,OAAO,yBAAyB,WAC3B,qBAA6B,YAC9B;GAEN,MAAM,QAAS,yBAAiC;GAChD,IAAI,CAAC,OAAO,OAAO;GACnB,MAAM,oBAAqB,OAAe;GAI1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GACR,IAAI,OAAO,mBAAmB,UAAU,OAAO;GAC/C,OAAO,kBAAkB;EAC3B,CAAC,CAAC,CACD,KAAK,CAAC,SAAS,GAAG;EAErB,MAAM,aAAa,QAChB,QAAQ,CAAC,KAAK,0BAA0B;GACvC,MAAM,kBACJ,OAAO,yBAAyB,WAC3B,qBAA6B,YAC9B;GAGN,MAAM,oBADS,yBAAiC,IAChB,EAAU;GAI1C,MAAM,iBACJ,OAAO,sBAAsB,WACzB,oBACA,oBACE,IAAI,KAAK,iBAAiB,CAAC,CAAC,QAAQ,IACpC;GACR,OACE,OAAO,mBAAmB,YAC1B,OAAO,oBAAoB,YAC3B,kBAAkB;EAEtB,CAAC,CAAC,CACD,KAAK,CAAC,SAAS,GAAG;EAGrB,IAAI,QAAQ,WAAW,GAAG;GACxB,UAAU,4BAA4B,EACpC,OAAO,QACT,CAAC;GACD;EACF;EAEA,UAAU,wBAAwB;EAGlC,MAAM,uBAA6C,CACjD,GAAG,WAAW,KAAK,mBAAmB;GACpC;GACA,QAAQ;EACV,EAAE,GACF,GAAG,YAAY,KAAK,mBAAmB;GACrC;GACA,QAAQ;EACV,EAAE,CACJ;EAGA,MAAM,SAAS,IAAIC,gCAAW;EAC9B,OAAO,OACL,qBAAqB,KAAiB,OAAO;GAC3C,eAAe,EAAE;GACjB,QAAQ,EAAE;EACZ,EAAE,CACJ;EAEA,MAAM,kCAAgD,CAAC;EAEvD,MAAM,oBAAoB,OACxB,cACkB;GAClB,MAAM,WACJ,UAAU,WAAW,cAAc,UAAU,WAAW;GAE1D,IAAI,CAAC,UAAU;IACb,UAAU,SAAS;IACnB,OAAO,OAAO,CACZ;KAAE,eAAe,UAAU;KAAe,QAAQ;IAAW,CAC/D,CAAC;GACH;GAEA,IAAI;IACF,IAAI;IAEJ,IAAI,UACF,mBAAmB,yBACjB,UAAU;IAId,IAAI,CAAC,kBAKH,oBAAmB,MAFX,YAAY,WAAW,cAAc,UAAU,aAAa,EAE9B,CAAC;IAGzC,IAAI,CAAC,kBACH,MAAM,IAAI,MACR,cAAc,UAAU,cAAc,qBACxC;IAMF,MAAM,2BADJ,2BAA2B,UAAU,cACW,EAAE,MACjD,MAAM,EAAE,aAAa,QACxB;IAEA,IAAI,0BAEF,mBAAmB;KACjB,GAAG;KACH,UAAU;KACV,UAAU,yBAAyB;KACnC,SAAS,yBAAyB;IACpC;IAIF,MAAM,EAAE,WAAW,UAAMC,gDACvB,kBACA,QACA,OACF;IAEA,UAAU,SAAS;IACnB,OAAO,OAAO,CAAC;KAAE,eAAe,UAAU;KAAe;IAAO,CAAC,CAAC;IAElE,gCAAgC,KAAK,gBAAgB;GACvD,SAAS,OAAO;IACd,UAAU,SAAS;IACnB,UAAU,QAAQ;IAClB,UAAU,eAAe,6BAA6B,UAAU,cAAc,IAAI;IAClF,OAAO,OAAO,CACZ;KAAE,eAAe,UAAU;KAAe,QAAQ;IAAQ,CAC5D,CAAC;GACH;EACF;EAGA,UAAMC,oCAAY,sBAAsB,mBAAmB,CAAC;EAG5D,OAAO,OAAO;EAGd,MAAM,WAAW,WAAyC;GACxD,QAAQ,QAAR;IACE,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK,oBACH,OAAO;IACT,KAAK,SACH,OAAO;IACT,SACE,OAAO;GACX;EACF;EAEA,MAAM,YAAY,WAAyC;GACzD,QAAQ,QAAR;IACE,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK,cACH,OAAOC,wBAAW;IACpB,KAAK;IACL,KAAK,oBACH,OAAOA,wBAAW;IACpB,KAAK,SACH,OAAOA,wBAAW;IACpB,SACE,OAAOA,wBAAW;GACtB;EACF;EAEA,KAAK,MAAM,KAAK,sBAAsB;GACpC,MAAM,OAAO,QAAQ,EAAE,MAAM;GAC7B,MAAM,QAAQ,SAAS,EAAE,MAAM;GAC/B,UACE,MAAM,EAAE,cAAc,GAAGA,wBAAW,KAAK,GAAG,QAAQ,KAAK,GAAG,EAAE,SAASA,wBAAW,KAAK,GAAGA,wBAAW,OACvG;EACF;EAGA,KAAK,MAAM,aAAa,sBACtB,IAAI,UAAU,cACZ,UAAU,UAAU,cAAc,EAChC,OAAO,QACT,CAAC;CAGP,SAAS,OAAO;EACd,UAAU,OAAO,EACf,OAAO,QACT,CAAC;CACH;AACF"}
|
package/dist/cjs/push/push.cjs
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
const require_loadPrompts = require('../loadPrompts.cjs');
|
|
4
3
|
const require_utils_checkAccess = require('../utils/checkAccess.cjs');
|
|
5
4
|
const require_utils_selectCmsEnvironment = require('../utils/selectCmsEnvironment.cjs');
|
|
6
5
|
const require_pushLog = require('../pushLog.cjs');
|
|
6
|
+
const require_loadPrompts = require('../loadPrompts.cjs');
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
9
9
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
10
10
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
11
11
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
12
|
+
let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
|
|
12
13
|
let _intlayer_engine_build = require("@intlayer/engine/build");
|
|
13
14
|
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
14
15
|
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
15
|
-
let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
|
|
16
16
|
let node_fs_promises = require("node:fs/promises");
|
|
17
17
|
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
18
18
|
|
|
@@ -55,7 +55,7 @@ const push = async (options) => {
|
|
|
55
55
|
if (!await require_utils_checkAccess.checkCMSAuth(config)) return;
|
|
56
56
|
const intlayerAPI = await require_utils_checkAccess.getAuthenticatedAPI(config);
|
|
57
57
|
await require_utils_selectCmsEnvironment.selectCmsEnvironment(options?.configOptions?.env, intlayerAPI, config);
|
|
58
|
-
const unmergedDictionariesRecord = (0,
|
|
58
|
+
const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(config);
|
|
59
59
|
const allDictionaries = Object.values(unmergedDictionariesRecord).flat();
|
|
60
60
|
const selectedCustomLocations = Array.from(new Set(allDictionaries.map((dictionary) => dictionary.location).filter((location) => location && ![
|
|
61
61
|
"remote",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.cjs","names":["ANSIColors","getConfiguration","getAppLogger","prepareIntlayer","checkCMSAuth","getAuthenticatedAPI","selectCmsEnvironment","getUnmergedDictionaries","colorize","listGitFiles","join","PushLogger","writeContentDeclaration","parallelize","colorizeKey","loadPrompts","fsPromises","formatPath"],"sources":["../../../src/push/push.ts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/engine/build';\nimport {\n type ListGitFilesOptions,\n listGitFiles,\n logConfigDetails,\n} from '@intlayer/engine/cli';\nimport { formatPath, parallelize } from '@intlayer/engine/utils';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { getUnmergedDictionaries } from '@intlayer/unmerged-dictionaries-entry';\nimport { loadPrompts } from '../loadPrompts';\nimport { PushLogger, type PushStatus } from '../pushLog';\nimport { checkCMSAuth, getAuthenticatedAPI } from '../utils/checkAccess';\nimport { selectCmsEnvironment } from '../utils/selectCmsEnvironment';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status:\n | 'pending'\n | 'pushing'\n | 'modified'\n | 'pushed'\n | 'up-to-date'\n | 'unknown'\n | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n// Print per-dictionary summary similar to loadDictionaries\nconst statusIconsAndColors = {\n pushed: { icon: '✔', color: ANSIColors.GREEN },\n modified: { icon: '✔', color: ANSIColors.GREEN },\n 'up-to-date': { icon: '=', color: ANSIColors.GREY },\n error: { icon: '✖', color: ANSIColors.RED },\n default: { icon: '⏲', color: ANSIColors.BLUE },\n};\n\nconst getIconAndColor = (status: DictionariesStatus['status']) => {\n return (\n statusIconsAndColors[status as keyof typeof statusIconsAndColors] ??\n statusIconsAndColors.default\n );\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(config);\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n try {\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = await getAuthenticatedAPI(config);\n\n await selectCmsEnvironment(\n options?.configOptions?.env,\n intlayerAPI,\n config\n );\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n const allDictionaries = Object.values(unmergedDictionariesRecord).flat();\n\n const customLocations = Array.from(\n new Set(\n allDictionaries\n .map((dictionary) => dictionary.location)\n .filter(\n (location) =>\n location && !['remote', 'local', 'hybrid'].includes(location)\n )\n )\n ) as string[];\n\n // Include all custom locations automatically — no interactive prompt needed.\n const selectedCustomLocations: string[] = customLocations;\n\n let dictionaries: Dictionary[] = allDictionaries.filter((dictionary) => {\n const location =\n dictionary.location ?? config.dictionary?.location ?? 'local';\n\n return (\n location === 'remote' ||\n location === 'hybrid' ||\n selectedCustomLocations.includes(location)\n );\n });\n\n // Check if the dictionaries list is empty after filtering by location\n if (dictionaries.length === 0) {\n appLogger(\n `No dictionaries found to push. Only dictionaries with location ${colorize('remote', ANSIColors.BLUE, ANSIColors.RESET)}, ${colorize('hybrid', ANSIColors.BLUE, ANSIColors.RESET)} or selected custom locations are pushed.`,\n { level: 'warn' }\n );\n appLogger(\n `You can set the location in your dictionary file (e.g. ${colorize(\"{ key: 'my-key', location: 'hybrid', ... }\", ANSIColors.BLUE, ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${colorize(\"{ dictionary: { location: 'hybrid' } }\", ANSIColors.BLUE, ANSIColors.RESET)}).`,\n { level: 'info' }\n );\n return;\n }\n\n const existingDictionariesKeys: string[] = Object.keys(\n unmergedDictionariesRecord\n );\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries?.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n\n dictionaries = dictionaries.filter((dictionary) =>\n gitFiles.includes(\n join(config.system.baseDir, dictionary.filePath ?? '')\n )\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];\n const newDictionaries = pushResult.data?.newDictionaries ?? [];\n const upToDateDictionaries =\n pushResult.data?.upToDateDictionaries ?? [];\n\n const allDictionaries = [\n ...updatedDictionaries,\n ...newDictionaries,\n ...upToDateDictionaries,\n ];\n\n for (const remoteDictionaryData of allDictionaries) {\n const localDictionary = unmergedDictionariesRecord[\n remoteDictionaryData.key\n ]?.find(\n (dictionary) => dictionary.localId === remoteDictionaryData.localId\n );\n\n if (!localDictionary) continue;\n\n await writeContentDeclaration(\n { ...localDictionary, id: remoteDictionaryData.id },\n config\n );\n }\n\n if (\n updatedDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (\n newDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else if (\n upToDateDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'up-to-date';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'up-to-date' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n for (const dictionaryStatus of dictionariesStatuses) {\n const { icon, color } = getIconAndColor(dictionaryStatus.status);\n appLogger(\n ` - ${colorizeKey(dictionaryStatus.dictionary.key)} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const remoteDictionaries = successfullyPushedDictionaries.filter(\n (dictionary) => dictionary.location === 'remote'\n );\n const remoteDictionariesKeys = remoteDictionaries.map(\n (dictionary) => dictionary.key\n );\n\n if (remoteDictionaries.length > 0) {\n const { confirm, isCancel } = await loadPrompts();\n\n const shouldDelete = await confirm({\n message: `Do you want to delete the local dictionaries that were successfully pushed? ${colorize('(Dictionaries:', ANSIColors.GREY, ANSIColors.RESET)} ${colorizeKey(remoteDictionariesKeys)}${colorize(')', ANSIColors.GREY, ANSIColors.RESET)}`,\n initialValue: false,\n });\n\n if (isCancel(shouldDelete)) {\n return;\n }\n\n if (shouldDelete) {\n await deleteLocalDictionaries(remoteDictionaries, options);\n }\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} does not have a file path`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"push.cjs","names":["ANSIColors","getConfiguration","getAppLogger","prepareIntlayer","checkCMSAuth","getAuthenticatedAPI","selectCmsEnvironment","getUnmergedDictionaries","colorize","listGitFiles","join","PushLogger","writeContentDeclaration","parallelize","colorizeKey","loadPrompts","fsPromises","formatPath"],"sources":["../../../src/push/push.ts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport {\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/engine/build';\nimport {\n type ListGitFilesOptions,\n listGitFiles,\n logConfigDetails,\n} from '@intlayer/engine/cli';\nimport { formatPath, parallelize } from '@intlayer/engine/utils';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { loadPrompts } from '../loadPrompts';\nimport { PushLogger, type PushStatus } from '../pushLog';\nimport { checkCMSAuth, getAuthenticatedAPI } from '../utils/checkAccess';\nimport { selectCmsEnvironment } from '../utils/selectCmsEnvironment';\n\ntype PushOptions = {\n deleteLocaleDictionary?: boolean;\n keepLocaleDictionary?: boolean;\n dictionaries?: string[];\n gitOptions?: ListGitFilesOptions;\n configOptions?: GetConfigurationOptions;\n build?: boolean;\n};\n\ntype DictionariesStatus = {\n dictionary: Dictionary;\n status:\n | 'pending'\n | 'pushing'\n | 'modified'\n | 'pushed'\n | 'up-to-date'\n | 'unknown'\n | 'error';\n error?: Error;\n errorMessage?: string;\n};\n\n// Print per-dictionary summary similar to loadDictionaries\nconst statusIconsAndColors = {\n pushed: { icon: '✔', color: ANSIColors.GREEN },\n modified: { icon: '✔', color: ANSIColors.GREEN },\n 'up-to-date': { icon: '=', color: ANSIColors.GREY },\n error: { icon: '✖', color: ANSIColors.RED },\n default: { icon: '⏲', color: ANSIColors.BLUE },\n};\n\nconst getIconAndColor = (status: DictionariesStatus['status']) => {\n return (\n statusIconsAndColors[status as keyof typeof statusIconsAndColors] ??\n statusIconsAndColors.default\n );\n};\n\n/**\n * Get all local dictionaries and push them simultaneously.\n */\nexport const push = async (options?: PushOptions): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(config);\n\n if (options?.build === true) {\n await prepareIntlayer(config, { forceRun: true });\n } else if (typeof options?.build === 'undefined') {\n await prepareIntlayer(config);\n }\n\n try {\n const hasCMSAuth = await checkCMSAuth(config);\n\n if (!hasCMSAuth) return;\n\n const intlayerAPI = await getAuthenticatedAPI(config);\n\n await selectCmsEnvironment(\n options?.configOptions?.env,\n intlayerAPI,\n config\n );\n\n const unmergedDictionariesRecord = getUnmergedDictionaries(config);\n const allDictionaries = Object.values(unmergedDictionariesRecord).flat();\n\n const customLocations = Array.from(\n new Set(\n allDictionaries\n .map((dictionary) => dictionary.location)\n .filter(\n (location) =>\n location && !['remote', 'local', 'hybrid'].includes(location)\n )\n )\n ) as string[];\n\n // Include all custom locations automatically — no interactive prompt needed.\n const selectedCustomLocations: string[] = customLocations;\n\n let dictionaries: Dictionary[] = allDictionaries.filter((dictionary) => {\n const location =\n dictionary.location ?? config.dictionary?.location ?? 'local';\n\n return (\n location === 'remote' ||\n location === 'hybrid' ||\n selectedCustomLocations.includes(location)\n );\n });\n\n // Check if the dictionaries list is empty after filtering by location\n if (dictionaries.length === 0) {\n appLogger(\n `No dictionaries found to push. Only dictionaries with location ${colorize('remote', ANSIColors.BLUE, ANSIColors.RESET)}, ${colorize('hybrid', ANSIColors.BLUE, ANSIColors.RESET)} or selected custom locations are pushed.`,\n { level: 'warn' }\n );\n appLogger(\n `You can set the location in your dictionary file (e.g. ${colorize(\"{ key: 'my-key', location: 'hybrid', ... }\", ANSIColors.BLUE, ANSIColors.RESET)} or globally in your intlayer.config.ts file (e.g. ${colorize(\"{ dictionary: { location: 'hybrid' } }\", ANSIColors.BLUE, ANSIColors.RESET)}).`,\n { level: 'info' }\n );\n return;\n }\n\n const existingDictionariesKeys: string[] = Object.keys(\n unmergedDictionariesRecord\n );\n\n if (options?.dictionaries) {\n // Check if the provided dictionaries exist\n const noneExistingDictionariesOption = options.dictionaries.filter(\n (dictionaryId) => !existingDictionariesKeys.includes(dictionaryId)\n );\n\n if (noneExistingDictionariesOption.length > 0) {\n appLogger(\n `The following dictionaries do not exist: ${noneExistingDictionariesOption.join(\n ', '\n )} and have been ignored.`,\n {\n level: 'error',\n }\n );\n }\n\n // Filter the dictionaries from the provided list of IDs\n dictionaries = dictionaries.filter((dictionary) =>\n options.dictionaries?.includes(dictionary.key)\n );\n }\n\n if (options?.gitOptions) {\n const gitFiles = await listGitFiles(options.gitOptions);\n\n dictionaries = dictionaries.filter((dictionary) =>\n gitFiles.includes(\n join(config.system.baseDir, dictionary.filePath ?? '')\n )\n );\n }\n\n // Check if the dictionaries list is empty\n if (dictionaries.length === 0) {\n appLogger('No local dictionaries found', {\n level: 'error',\n });\n return;\n }\n\n appLogger('Pushing dictionaries:');\n\n // Prepare dictionaries statuses\n const dictionariesStatuses: DictionariesStatus[] = dictionaries.map(\n (dictionary) => ({\n dictionary,\n status: 'pending',\n })\n );\n\n // Initialize aggregated logger similar to loadDictionaries\n const logger = new PushLogger();\n logger.update(\n dictionariesStatuses.map<PushStatus>((s) => ({\n dictionaryKey: s.dictionary.key,\n status: 'pending',\n }))\n );\n\n const successfullyPushedDictionaries: Dictionary[] = [];\n\n const processDictionary = async (\n statusObj: DictionariesStatus\n ): Promise<void> => {\n statusObj.status = 'pushing';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushing' },\n ]);\n\n try {\n const pushResult = await intlayerAPI.dictionary.pushDictionaries([\n statusObj.dictionary,\n ]);\n\n const updatedDictionaries = pushResult.data?.updatedDictionaries ?? [];\n const newDictionaries = pushResult.data?.newDictionaries ?? [];\n const upToDateDictionaries =\n pushResult.data?.upToDateDictionaries ?? [];\n\n const allDictionaries = [\n ...updatedDictionaries,\n ...newDictionaries,\n ...upToDateDictionaries,\n ];\n\n for (const remoteDictionaryData of allDictionaries) {\n const localDictionary = unmergedDictionariesRecord[\n remoteDictionaryData.key\n ]?.find(\n (dictionary) => dictionary.localId === remoteDictionaryData.localId\n );\n\n if (!localDictionary) continue;\n\n await writeContentDeclaration(\n { ...localDictionary, id: remoteDictionaryData.id },\n config\n );\n }\n\n if (\n updatedDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'modified';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'modified' },\n ]);\n } else if (\n newDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'pushed';\n successfullyPushedDictionaries.push(statusObj.dictionary);\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'pushed' },\n ]);\n } else if (\n upToDateDictionaries.some(\n (dictionary) => dictionary.key === statusObj.dictionary.key\n )\n ) {\n statusObj.status = 'up-to-date';\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'up-to-date' },\n ]);\n } else {\n statusObj.status = 'unknown';\n }\n } catch (error) {\n statusObj.status = 'error';\n statusObj.error = error as Error;\n statusObj.errorMessage = `Error pushing dictionary ${statusObj.dictionary.key}: ${error}`;\n logger.update([\n { dictionaryKey: statusObj.dictionary.key, status: 'error' },\n ]);\n }\n };\n\n // Process dictionaries in parallel with a concurrency limit (reuse parallelize)\n await parallelize(dictionariesStatuses, processDictionary, 5);\n\n // Stop the logger and render final state\n logger.finish();\n\n for (const dictionaryStatus of dictionariesStatuses) {\n const { icon, color } = getIconAndColor(dictionaryStatus.status);\n appLogger(\n ` - ${colorizeKey(dictionaryStatus.dictionary.key)} ${ANSIColors.GREY}[${color}${icon} ${dictionaryStatus.status}${ANSIColors.GREY}]${ANSIColors.RESET}`\n );\n }\n\n // Output any error messages\n for (const statusObj of dictionariesStatuses) {\n if (statusObj.errorMessage) {\n appLogger(statusObj.errorMessage, {\n level: 'error',\n });\n }\n }\n\n // Handle delete or keep options\n const deleteOption = options?.deleteLocaleDictionary;\n const keepOption = options?.keepLocaleDictionary;\n\n if (deleteOption && keepOption) {\n throw new Error(\n 'Cannot specify both --deleteLocaleDictionary and --keepLocaleDictionary options.'\n );\n }\n\n if (deleteOption) {\n // Delete only the successfully pushed dictionaries\n await deleteLocalDictionaries(successfullyPushedDictionaries, options);\n } else if (keepOption) {\n // Do nothing, keep the local dictionaries\n } else {\n // Ask the user\n const remoteDictionaries = successfullyPushedDictionaries.filter(\n (dictionary) => dictionary.location === 'remote'\n );\n const remoteDictionariesKeys = remoteDictionaries.map(\n (dictionary) => dictionary.key\n );\n\n if (remoteDictionaries.length > 0) {\n const { confirm, isCancel } = await loadPrompts();\n\n const shouldDelete = await confirm({\n message: `Do you want to delete the local dictionaries that were successfully pushed? ${colorize('(Dictionaries:', ANSIColors.GREY, ANSIColors.RESET)} ${colorizeKey(remoteDictionariesKeys)}${colorize(')', ANSIColors.GREY, ANSIColors.RESET)}`,\n initialValue: false,\n });\n\n if (isCancel(shouldDelete)) {\n return;\n }\n\n if (shouldDelete) {\n await deleteLocalDictionaries(remoteDictionaries, options);\n }\n }\n }\n } catch (error) {\n appLogger(error, {\n level: 'error',\n });\n }\n};\n\nconst deleteLocalDictionaries = async (\n dictionariesToDelete: Dictionary[],\n options?: PushOptions\n): Promise<void> => {\n const config = getConfiguration(options?.configOptions);\n const appLogger = getAppLogger(config);\n\n // Use a Set to collect all unique file paths\n const filePathsSet: Set<string> = new Set();\n\n for (const dictionary of dictionariesToDelete) {\n const { filePath } = dictionary;\n\n if (!filePath) {\n appLogger(\n `Dictionary ${colorizeKey(dictionary.key)} does not have a file path`,\n {\n level: 'error',\n }\n );\n continue;\n }\n\n filePathsSet.add(filePath);\n }\n\n for (const filePath of filePathsSet) {\n try {\n const stats = await fsPromises.lstat(filePath);\n\n if (stats.isFile()) {\n await fsPromises.unlink(filePath);\n appLogger(`Deleted file ${formatPath(filePath)}`, {});\n } else if (stats.isDirectory()) {\n appLogger(`Path is a directory ${formatPath(filePath)}, skipping.`, {});\n } else {\n appLogger(\n `Unknown file type for ${formatPath(filePath)}, skipping.`,\n {}\n );\n }\n } catch (err) {\n appLogger(`Error deleting ${formatPath(filePath)}: ${err}`, {\n level: 'error',\n });\n }\n }\n};\n"],"mappings":"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"}
|
|
@@ -10,9 +10,9 @@ let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
|
10
10
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
11
11
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
12
12
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
13
|
+
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
13
14
|
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
14
15
|
let node_fs_promises = require("node:fs/promises");
|
|
15
|
-
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
16
16
|
let _intlayer_engine_docReview = require("@intlayer/engine/docReview");
|
|
17
17
|
let _intlayer_core_localization = require("@intlayer/core/localization");
|
|
18
18
|
let _intlayer_types_locales = require("@intlayer/types/locales");
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
3
|
+
let _intlayer_dictionaries_entry_unmerged = require("@intlayer/dictionaries-entry/unmerged");
|
|
3
4
|
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
4
|
-
let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
|
|
5
5
|
let _intlayer_core_plugins = require("@intlayer/core/plugins");
|
|
6
6
|
let _intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
|
|
7
7
|
|
|
8
8
|
//#region src/test/listMissingTranslations.ts
|
|
9
9
|
const listMissingTranslationsWithConfig = (configuration) => {
|
|
10
|
-
const unmergedDictionariesRecord = (0,
|
|
10
|
+
const unmergedDictionariesRecord = (0, _intlayer_dictionaries_entry_unmerged.getUnmergedDictionaries)(configuration);
|
|
11
11
|
const mergedDictionaries = (0, _intlayer_dictionaries_entry.getDictionaries)(configuration);
|
|
12
12
|
const missingTranslations = [];
|
|
13
13
|
const { locales, requiredLocales } = configuration.internationalization;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listMissingTranslations.cjs","names":["getUnmergedDictionaries","getDictionaries","getMissingLocalesContentFromDictionary","getConfiguration"],"sources":["../../../src/test/listMissingTranslations.ts"],"sourcesContent":["import {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getMissingLocalesContentFromDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport {
|
|
1
|
+
{"version":3,"file":"listMissingTranslations.cjs","names":["getUnmergedDictionaries","getDictionaries","getMissingLocalesContentFromDictionary","getConfiguration"],"sources":["../../../src/test/listMissingTranslations.ts"],"sourcesContent":["import {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getMissingLocalesContentFromDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\n\nexport const listMissingTranslationsWithConfig = (\n configuration: IntlayerConfig\n) => {\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n const mergedDictionaries = getDictionaries(configuration);\n\n const missingTranslations: {\n key: string;\n filePath?: string;\n id?: string;\n locales: Locale[];\n }[] = [];\n\n const { locales, requiredLocales } = configuration.internationalization;\n\n // Use the union of keys from both unmerged and merged dictionaries so that\n // dictionaries compiled only as merged (no per-locale split) are still checked.\n const dictionariesKeys = new Set([\n ...Object.keys(unmergedDictionariesRecord),\n ...Object.keys(mergedDictionaries),\n ]);\n\n for (const dictionaryKey of dictionariesKeys) {\n const dictionaries: Dictionary[] =\n unmergedDictionariesRecord[dictionaryKey] ?? [];\n\n const multilingualDictionary: Dictionary[] = dictionaries.filter(\n (dictionary) => !dictionary.locale\n );\n\n // Test all by merging all dictionaries to ensure no per-locale dictionary is missing\n for (const dictionary of multilingualDictionary) {\n const missingLocales = getMissingLocalesContentFromDictionary(\n dictionary,\n locales\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionaryKey,\n id: dictionary.id,\n filePath: dictionary.filePath,\n locales: missingLocales,\n });\n }\n }\n\n const perLocaleDictionary: Dictionary[] = dictionaries.filter(\n (dictionary) => dictionary.locale\n );\n\n // If there are no unmerged dictionaries for this key, fall back to the\n // merged dictionary directly (covers the case where the dict was compiled\n // as merged-only and unmerged_dictionaries.cjs is empty for this key).\n if (dictionaries.length === 0) {\n const mergedDictionary = mergedDictionaries[dictionaryKey];\n\n if (mergedDictionary) {\n const missingLocales = getMissingLocalesContentFromDictionary(\n mergedDictionary,\n locales\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionaryKey,\n id: mergedDictionary.id,\n filePath: mergedDictionary.filePath,\n locales: missingLocales,\n });\n }\n }\n\n continue;\n }\n\n if (perLocaleDictionary.length === 0) {\n continue;\n }\n\n const mergedDictionary = mergedDictionaries[dictionaryKey];\n\n const missingLocales = getMissingLocalesContentFromDictionary(\n mergedDictionary,\n locales\n );\n\n if (missingLocales.length > 0) {\n missingTranslations.push({\n key: dictionaryKey,\n locales: missingLocales,\n });\n }\n }\n\n const missingLocalesSet = new Set(\n missingTranslations.flatMap(\n (missingTranslation) => missingTranslation.locales\n )\n );\n const missingLocales = Array.from(missingLocalesSet);\n\n const missingRequiredLocales = missingLocales.filter((locale) =>\n (requiredLocales ?? locales).includes(locale)\n );\n\n return { missingTranslations, missingLocales, missingRequiredLocales };\n};\n\nexport const listMissingTranslations = (\n configurationOptions?: GetConfigurationOptions\n) => {\n const configuration = getConfiguration(configurationOptions);\n logConfigDetails(configurationOptions);\n\n return listMissingTranslationsWithConfig(configuration);\n};\n"],"mappings":";;;;;;;;AAYA,MAAa,qCACX,kBACG;CACH,MAAM,iCAA6BA,+DAAwB,aAAa;CACxE,MAAM,yBAAqBC,8CAAgB,aAAa;CAExD,MAAM,sBAKA,CAAC;CAEP,MAAM,EAAE,SAAS,oBAAoB,cAAc;CAInD,MAAM,mCAAmB,IAAI,IAAI,CAC/B,GAAG,OAAO,KAAK,0BAA0B,GACzC,GAAG,OAAO,KAAK,kBAAkB,CACnC,CAAC;CAED,KAAK,MAAM,iBAAiB,kBAAkB;EAC5C,MAAM,eACJ,2BAA2B,kBAAkB,CAAC;EAEhD,MAAM,yBAAuC,aAAa,QACvD,eAAe,CAAC,WAAW,MAC9B;EAGA,KAAK,MAAM,cAAc,wBAAwB;GAC/C,MAAM,qBAAiBC,+DACrB,YACA,OACF;GAEA,IAAI,eAAe,SAAS,GAC1B,oBAAoB,KAAK;IACvB,KAAK;IACL,IAAI,WAAW;IACf,UAAU,WAAW;IACrB,SAAS;GACX,CAAC;EAEL;EAEA,MAAM,sBAAoC,aAAa,QACpD,eAAe,WAAW,MAC7B;EAKA,IAAI,aAAa,WAAW,GAAG;GAC7B,MAAM,mBAAmB,mBAAmB;GAE5C,IAAI,kBAAkB;IACpB,MAAM,qBAAiBA,+DACrB,kBACA,OACF;IAEA,IAAI,eAAe,SAAS,GAC1B,oBAAoB,KAAK;KACvB,KAAK;KACL,IAAI,iBAAiB;KACrB,UAAU,iBAAiB;KAC3B,SAAS;IACX,CAAC;GAEL;GAEA;EACF;EAEA,IAAI,oBAAoB,WAAW,GACjC;EAGF,MAAM,mBAAmB,mBAAmB;EAE5C,MAAM,qBAAiBA,+DACrB,kBACA,OACF;EAEA,IAAI,eAAe,SAAS,GAC1B,oBAAoB,KAAK;GACvB,KAAK;GACL,SAAS;EACX,CAAC;CAEL;CAEA,MAAM,oBAAoB,IAAI,IAC5B,oBAAoB,SACjB,uBAAuB,mBAAmB,OAC7C,CACF;CACA,MAAM,iBAAiB,MAAM,KAAK,iBAAiB;CAMnD,OAAO;EAAE;EAAqB;EAAgB,wBAJf,eAAe,QAAQ,YACnD,mBAAmB,QAAO,CAAE,SAAS,MAAM,CAGqB;CAAE;AACvE;AAEA,MAAa,2BACX,yBACG;CACH,MAAM,oBAAgBC,wCAAiB,oBAAoB;CAC3D,2CAAiB,oBAAoB;CAErC,OAAO,kCAAkC,aAAa;AACxD"}
|
|
@@ -9,9 +9,9 @@ let node_path = require("node:path");
|
|
|
9
9
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
10
10
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
11
11
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
12
|
+
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
12
13
|
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
13
14
|
let node_fs_promises = require("node:fs/promises");
|
|
14
|
-
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
15
15
|
let node_perf_hooks = require("node:perf_hooks");
|
|
16
16
|
|
|
17
17
|
//#region src/translateDoc/translateFile.ts
|
|
@@ -6,8 +6,8 @@ const require_utils_checkConfigConsistency = require('./checkConfigConsistency.c
|
|
|
6
6
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
7
7
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
8
8
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
9
|
-
let _intlayer_api = require("@intlayer/api");
|
|
10
9
|
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
10
|
+
let _intlayer_api = require("@intlayer/api");
|
|
11
11
|
|
|
12
12
|
//#region src/utils/checkAccess.ts
|
|
13
13
|
const getAuthenticatedAPI = async (configuration) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
3
2
|
let _intlayer_config_utils = require("@intlayer/config/utils");
|
|
3
|
+
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
4
4
|
|
|
5
5
|
//#region src/utils/getOutputFilePath.ts
|
|
6
6
|
/**
|
package/dist/esm/editor.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { __require } from "./_virtual/_rolldown/runtime.mjs";
|
|
2
2
|
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { isESModule } from "@intlayer/config/utils";
|
|
3
4
|
import { spawn } from "node:child_process";
|
|
4
5
|
import { createRequire } from "node:module";
|
|
5
|
-
import { isESModule } from "@intlayer/config/utils";
|
|
6
6
|
|
|
7
7
|
//#region src/editor.ts
|
|
8
8
|
const startEditor = (options) => {
|
package/dist/esm/extract.mjs
CHANGED
|
@@ -3,10 +3,10 @@ import { relative, resolve } from "node:path";
|
|
|
3
3
|
import * as ANSIColors from "@intlayer/config/colors";
|
|
4
4
|
import { colorize, getAppLogger, x } from "@intlayer/config/logger";
|
|
5
5
|
import { getConfiguration } from "@intlayer/config/node";
|
|
6
|
+
import { getUnmergedDictionaries } from "@intlayer/dictionaries-entry/unmerged";
|
|
6
7
|
import { prepareIntlayer } from "@intlayer/engine/build";
|
|
7
8
|
import { logConfigDetails } from "@intlayer/engine/cli";
|
|
8
9
|
import { buildComponentFilesList, formatPath } from "@intlayer/engine/utils";
|
|
9
|
-
import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
|
|
10
10
|
import enquirer from "enquirer";
|
|
11
11
|
|
|
12
12
|
//#region src/extract.ts
|
package/dist/esm/extract.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.mjs","names":[],"sources":["../../src/extract.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport type { PackageName } from '@intlayer/babel';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger, x } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { buildComponentFilesList, formatPath } from '@intlayer/engine/utils';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport
|
|
1
|
+
{"version":3,"file":"extract.mjs","names":[],"sources":["../../src/extract.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { relative, resolve } from 'node:path';\nimport type { PackageName } from '@intlayer/babel';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger, x } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { prepareIntlayer } from '@intlayer/engine/build';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { buildComponentFilesList, formatPath } from '@intlayer/engine/utils';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport enquirer from 'enquirer';\n\ntype ExtractOptions = {\n files?: string[];\n output?: FilePathPattern;\n configOptions?: GetConfigurationOptions;\n codeOnly?: boolean;\n declarationOnly?: boolean;\n};\n\nexport const extract = async (options: ExtractOptions) => {\n const configuration = getConfiguration(options.configOptions);\n\n logConfigDetails(options?.configOptions);\n\n const appLogger = getAppLogger(configuration);\n\n const { baseDir } = configuration.system;\n const { output } = configuration.compiler;\n\n if (!output) {\n appLogger(\n `${x} No output configuration found. Add a ${colorize('compiler.output', ANSIColors.BLUE)} in your configuration.`,\n {\n level: 'error',\n }\n );\n return;\n }\n\n const { detectPackageName, extractContent } = await import('@intlayer/babel');\n\n // Detect package\n const packageName: PackageName = detectPackageName(baseDir);\n\n let filesToExtract = options.files ?? [];\n\n if (filesToExtract.length === 0) {\n // Await all promises simultaneously\n const fileList = buildComponentFilesList(configuration);\n\n // Flatten the nested arrays and remove duplicates\n // Relative paths for selection\n const choices = fileList.map((file) => {\n const relPath = relative(baseDir, file);\n\n return {\n value: file,\n label: relPath,\n };\n });\n\n if (choices.length === 0) {\n appLogger('No extractable files found in the project.');\n return;\n }\n\n const SELECT_ALL = '__select_all__';\n\n type PromptChoice = {\n name: string;\n enabled: boolean;\n disabled?: boolean | string;\n };\n\n type PromptContext = {\n choices: PromptChoice[];\n render(): void | Promise<void>;\n state: { submitted: boolean };\n selected: PromptChoice[];\n input: string;\n options: { multiple?: boolean };\n };\n\n let selectedFiles: string[] | symbol;\n try {\n const maxLen = Math.max((process.stdout.columns || 80) - 15, 20);\n const truncatePath = (path: string) =>\n path.length > maxLen ? `...${path.slice(-(maxLen - 3))}` : path;\n\n const { files: enquirerSelectedFiles } = await enquirer.prompt<{\n files: string[];\n }>({\n type: 'autocomplete',\n name: 'files',\n message: 'Select files to extract (Type to search):',\n multiple: true,\n // @ts-ignore limit exist but is not typed\n limit: 40,\n choices: [\n { name: SELECT_ALL, message: '────── Select all ──────' },\n ...choices.map((choice) => ({\n name: choice.value,\n message: truncatePath(choice.label),\n })),\n ],\n async toggle(\n this: PromptContext,\n choice: PromptChoice,\n enabled?: boolean\n ) {\n if (!choice || choice.disabled) return;\n choice.enabled = enabled == null ? !choice.enabled : enabled;\n\n if (choice.name === SELECT_ALL) {\n this.choices\n .filter((choiceEl) => choiceEl.name !== SELECT_ALL)\n .forEach((choiceEl) => {\n choiceEl.enabled = choice.enabled;\n });\n }\n\n return this.render();\n },\n format(this: PromptContext) {\n if (this.state?.submitted && this.options?.multiple) {\n return `${this.selected.filter((s) => s.name !== SELECT_ALL).length} file(s) selected`;\n }\n return this.input ?? '';\n },\n });\n\n selectedFiles = enquirerSelectedFiles.filter(\n (file) => file !== SELECT_ALL\n );\n } catch {\n selectedFiles = Symbol('cancel');\n }\n\n if (typeof selectedFiles === 'symbol') {\n // User cancelled\n process.exit(0);\n }\n\n filesToExtract = selectedFiles as string[];\n }\n\n if (filesToExtract.length === 0) {\n appLogger('No files selected for extraction.');\n return;\n }\n\n const absoluteFiles = filesToExtract\n .map((file) => resolve(baseDir, file))\n .filter((file) => {\n if (!existsSync(file)) {\n appLogger(`File not found: ${formatPath(file)}`);\n return false;\n }\n return true;\n });\n\n if (absoluteFiles.length === 0) {\n return;\n }\n\n const unmergedDictionaries = getUnmergedDictionaries(configuration);\n\n for (const filePath of absoluteFiles) {\n try {\n await extractContent(filePath, packageName, {\n unmergedDictionaries,\n configuration,\n codeOnly: options.codeOnly,\n declarationOnly: options.declarationOnly,\n });\n } catch (error) {\n appLogger(`Failed to transform ${filePath}: ${(error as Error).message}`);\n }\n }\n\n await prepareIntlayer(configuration); // Prepare Intlayer to apply the changes\n};\n"],"mappings":";;;;;;;;;;;;AAwBA,MAAa,UAAU,OAAO,YAA4B;CACxD,MAAM,gBAAgB,iBAAiB,QAAQ,aAAa;CAE5D,iBAAiB,SAAS,aAAa;CAEvC,MAAM,YAAY,aAAa,aAAa;CAE5C,MAAM,EAAE,YAAY,cAAc;CAClC,MAAM,EAAE,WAAW,cAAc;CAEjC,IAAI,CAAC,QAAQ;EACX,UACE,GAAG,EAAE,wCAAwC,SAAS,mBAAmB,WAAW,IAAI,EAAE,0BAC1F,EACE,OAAO,QACT,CACF;EACA;CACF;CAEA,MAAM,EAAE,mBAAmB,mBAAmB,MAAM,OAAO;CAG3D,MAAM,cAA2B,kBAAkB,OAAO;CAE1D,IAAI,iBAAiB,QAAQ,SAAS,CAAC;CAEvC,IAAI,eAAe,WAAW,GAAG;EAM/B,MAAM,UAJW,wBAAwB,aAIlB,CAAC,CAAC,KAAK,SAAS;GAGrC,OAAO;IACL,OAAO;IACP,OAJc,SAAS,SAAS,IAInB;GACf;EACF,CAAC;EAED,IAAI,QAAQ,WAAW,GAAG;GACxB,UAAU,4CAA4C;GACtD;EACF;EAEA,MAAM,aAAa;EAiBnB,IAAI;EACJ,IAAI;GACF,MAAM,SAAS,KAAK,KAAK,QAAQ,OAAO,WAAW,MAAM,IAAI,EAAE;GAC/D,MAAM,gBAAgB,SACpB,KAAK,SAAS,SAAS,MAAM,KAAK,MAAM,EAAE,SAAS,EAAE,MAAM;GAE7D,MAAM,EAAE,OAAO,0BAA0B,MAAM,SAAS,OAErD;IACD,MAAM;IACN,MAAM;IACN,SAAS;IACT,UAAU;IAEV,OAAO;IACP,SAAS,CACP;KAAE,MAAM;KAAY,SAAS;IAA2B,GACxD,GAAG,QAAQ,KAAK,YAAY;KAC1B,MAAM,OAAO;KACb,SAAS,aAAa,OAAO,KAAK;IACpC,EAAE,CACJ;IACA,MAAM,OAEJ,QACA,SACA;KACA,IAAI,CAAC,UAAU,OAAO,UAAU;KAChC,OAAO,UAAU,WAAW,OAAO,CAAC,OAAO,UAAU;KAErD,IAAI,OAAO,SAAS,YAClB,KAAK,QACF,QAAQ,aAAa,SAAS,SAAS,UAAU,CAAC,CAClD,SAAS,aAAa;MACrB,SAAS,UAAU,OAAO;KAC5B,CAAC;KAGL,OAAO,KAAK,OAAO;IACrB;IACA,SAA4B;KAC1B,IAAI,KAAK,OAAO,aAAa,KAAK,SAAS,UACzC,OAAO,GAAG,KAAK,SAAS,QAAQ,MAAM,EAAE,SAAS,UAAU,CAAC,CAAC,OAAO;KAEtE,OAAO,KAAK,SAAS;IACvB;GACF,CAAC;GAED,gBAAgB,sBAAsB,QACnC,SAAS,SAAS,UACrB;EACF,QAAQ;GACN,gBAAgB,OAAO,QAAQ;EACjC;EAEA,IAAI,OAAO,kBAAkB,UAE3B,QAAQ,KAAK,CAAC;EAGhB,iBAAiB;CACnB;CAEA,IAAI,eAAe,WAAW,GAAG;EAC/B,UAAU,mCAAmC;EAC7C;CACF;CAEA,MAAM,gBAAgB,eACnB,KAAK,SAAS,QAAQ,SAAS,IAAI,CAAC,CAAC,CACrC,QAAQ,SAAS;EAChB,IAAI,CAAC,WAAW,IAAI,GAAG;GACrB,UAAU,mBAAmB,WAAW,IAAI,GAAG;GAC/C,OAAO;EACT;EACA,OAAO;CACT,CAAC;CAEH,IAAI,cAAc,WAAW,GAC3B;CAGF,MAAM,uBAAuB,wBAAwB,aAAa;CAElE,KAAK,MAAM,YAAY,eACrB,IAAI;EACF,MAAM,eAAe,UAAU,aAAa;GAC1C;GACA;GACA,UAAU,QAAQ;GAClB,iBAAiB,QAAQ;EAC3B,CAAC;CACH,SAAS,OAAO;EACd,UAAU,uBAAuB,SAAS,IAAK,MAAgB,SAAS;CAC1E;CAGF,MAAM,gBAAgB,aAAa;AACrC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { basename, dirname, isAbsolute, normalize, resolve } from "node:path";
|
|
2
2
|
import { GREY_DARK } from "@intlayer/config/colors";
|
|
3
3
|
import { colorize, colorizePath } from "@intlayer/config/logger";
|
|
4
|
-
import { getFormatFromExtension } from "@intlayer/engine/utils";
|
|
5
4
|
import { parseFilePathPattern } from "@intlayer/config/utils";
|
|
5
|
+
import { getFormatFromExtension } from "@intlayer/engine/utils";
|
|
6
6
|
|
|
7
7
|
//#region src/fill/formatAutoFilledFilePath.ts
|
|
8
8
|
const formatAutoFilledFilePath = async (autoFillField, dictionaryKey, dictionaryFilePath, baseDir, configuration, locale) => {
|
|
@@ -2,8 +2,8 @@ import { listMissingTranslationsWithConfig } from "../test/listMissingTranslatio
|
|
|
2
2
|
import { basename } from "node:path";
|
|
3
3
|
import * as ANSIColors from "@intlayer/config/colors";
|
|
4
4
|
import { colon, colorize, colorizeKey, colorizePath, getAppLogger } from "@intlayer/config/logger";
|
|
5
|
+
import { getUnmergedDictionaries } from "@intlayer/dictionaries-entry/unmerged";
|
|
5
6
|
import { formatLocale } from "@intlayer/engine/utils";
|
|
6
|
-
import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
|
|
7
7
|
import { getFilterTranslationsOnlyDictionary } from "@intlayer/core/plugins";
|
|
8
8
|
import { getDictionaries } from "@intlayer/dictionaries-entry";
|
|
9
9
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listTranslationsTasks.mjs","names":[],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getFilterTranslationsOnlyDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { formatLocale } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, LocalDictionaryId } from '@intlayer/types/dictionary';\nimport {
|
|
1
|
+
{"version":3,"file":"listTranslationsTasks.mjs","names":[],"sources":["../../../src/fill/listTranslationsTasks.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport {\n colon,\n colorize,\n colorizeKey,\n colorizePath,\n getAppLogger,\n} from '@intlayer/config/logger';\nimport { getFilterTranslationsOnlyDictionary } from '@intlayer/core/plugins';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport { getUnmergedDictionaries } from '@intlayer/dictionaries-entry/unmerged';\nimport { formatLocale } from '@intlayer/engine/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, LocalDictionaryId } from '@intlayer/types/dictionary';\nimport { listMissingTranslationsWithConfig } from '../test';\n\nexport type TranslationTask = {\n dictionaryKey: string;\n dictionaryLocalId: LocalDictionaryId;\n sourceLocale: Locale;\n targetLocales: Locale[];\n dictionaryPreset: string;\n dictionaryFilePath: string;\n};\n\nexport const listTranslationsTasks = (\n localIds: LocalDictionaryId[],\n outputLocales: Locale[],\n mode: 'complete' | 'review',\n baseLocale: Locale,\n configuration: IntlayerConfig\n): TranslationTask[] => {\n const appLogger = getAppLogger(configuration);\n\n const mergedDictionariesRecord = getDictionaries(configuration);\n const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);\n\n const allFlatDictionaries = Object.values(unmergedDictionariesRecord).flat();\n const dictionariesToProcess = allFlatDictionaries.filter((dictionary) =>\n localIds.includes(dictionary.localId!)\n );\n\n const { missingTranslations } =\n listMissingTranslationsWithConfig(configuration);\n\n const maxKeyLength = Math.max(\n ...dictionariesToProcess.map((dictionary) => dictionary.key.length)\n );\n\n const translationTasks: TranslationTask[] = [];\n\n for (const targetUnmergedDictionary of dictionariesToProcess) {\n const dictionaryPreset = colon(\n [\n ' - ',\n colorize('[', ANSIColors.GREY_DARK),\n colorizeKey(targetUnmergedDictionary.key),\n colorize(']', ANSIColors.GREY_DARK),\n ].join(''),\n { colSize: maxKeyLength + 6 }\n );\n\n const dictionaryKey = targetUnmergedDictionary.key;\n const dictionaryLocalId = targetUnmergedDictionary.localId!;\n const mainDictionaryToProcess: Dictionary | undefined =\n mergedDictionariesRecord[dictionaryKey];\n const dictionaryFilled = targetUnmergedDictionary.filled ?? false;\n\n if (dictionaryFilled === true) {\n continue;\n }\n\n const dictionaryFill =\n targetUnmergedDictionary.fill ?? configuration.dictionary?.fill ?? false;\n\n if (dictionaryFill === false) continue;\n\n const sourceLocale: Locale = (targetUnmergedDictionary.locale ??\n baseLocale) as Locale;\n\n if (!mainDictionaryToProcess) {\n appLogger(\n `${dictionaryPreset} Dictionary not found in dictionariesRecord. Skipping.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n if (!targetUnmergedDictionary.filePath) {\n appLogger(`${dictionaryPreset} Dictionary has no file path. Skipping.`, {\n level: 'warn',\n });\n continue;\n }\n\n const sourceLocaleContent = getFilterTranslationsOnlyDictionary(\n mainDictionaryToProcess,\n sourceLocale\n );\n\n if (\n Object.keys(sourceLocaleContent as Record<string, unknown>).length === 0\n ) {\n appLogger(\n `${dictionaryPreset} No content found for dictionary in source locale ${formatLocale(sourceLocale)}. Skipping translation for this dictionary.`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n /**\n * In 'complete' mode, filter only the missing locales to translate\n *\n * Skip the dictionary if there are no missing locales to translate\n */\n let outputLocalesList: Locale[] = outputLocales as Locale[];\n\n if (mode === 'complete') {\n outputLocalesList =\n missingTranslations\n .find(\n (missingTranslation) => missingTranslation.key === dictionaryKey\n )\n ?.locales.filter((locale) => outputLocales.includes(locale)) ?? [];\n }\n\n if (outputLocalesList.length === 0) {\n appLogger(\n `${dictionaryPreset} ${colorize('No locales to fill, Skipping', ANSIColors.GREY_DARK)} ${colorizePath(basename(targetUnmergedDictionary.filePath))}`,\n {\n level: 'warn',\n }\n );\n continue;\n }\n\n translationTasks.push({\n dictionaryKey,\n dictionaryLocalId,\n sourceLocale,\n targetLocales: outputLocalesList,\n dictionaryPreset,\n dictionaryFilePath: targetUnmergedDictionary.filePath,\n });\n }\n\n // Return the list of tasks to execute\n return translationTasks;\n};\n"],"mappings":";;;;;;;;;;AA2BA,MAAa,yBACX,UACA,eACA,MACA,YACA,kBACsB;CACtB,MAAM,YAAY,aAAa,aAAa;CAE5C,MAAM,2BAA2B,gBAAgB,aAAa;CAC9D,MAAM,6BAA6B,wBAAwB,aAAa;CAGxE,MAAM,wBADsB,OAAO,OAAO,0BAA0B,CAAC,CAAC,KACtB,CAAC,CAAC,QAAQ,eACxD,SAAS,SAAS,WAAW,OAAQ,CACvC;CAEA,MAAM,EAAE,wBACN,kCAAkC,aAAa;CAEjD,MAAM,eAAe,KAAK,IACxB,GAAG,sBAAsB,KAAK,eAAe,WAAW,IAAI,MAAM,CACpE;CAEA,MAAM,mBAAsC,CAAC;CAE7C,KAAK,MAAM,4BAA4B,uBAAuB;EAC5D,MAAM,mBAAmB,MACvB;GACE;GACA,SAAS,KAAK,WAAW,SAAS;GAClC,YAAY,yBAAyB,GAAG;GACxC,SAAS,KAAK,WAAW,SAAS;EACpC,CAAC,CAAC,KAAK,EAAE,GACT,EAAE,SAAS,eAAe,EAAE,CAC9B;EAEA,MAAM,gBAAgB,yBAAyB;EAC/C,MAAM,oBAAoB,yBAAyB;EACnD,MAAM,0BACJ,yBAAyB;EAG3B,KAFyB,yBAAyB,UAAU,WAEnC,MACvB;EAMF,KAFE,yBAAyB,QAAQ,cAAc,YAAY,QAAQ,WAE9C,OAAO;EAE9B,MAAM,eAAwB,yBAAyB,UACrD;EAEF,IAAI,CAAC,yBAAyB;GAC5B,UACE,GAAG,iBAAiB,yDACpB,EACE,OAAO,OACT,CACF;GACA;EACF;EAEA,IAAI,CAAC,yBAAyB,UAAU;GACtC,UAAU,GAAG,iBAAiB,0CAA0C,EACtE,OAAO,OACT,CAAC;GACD;EACF;EAEA,MAAM,sBAAsB,oCAC1B,yBACA,YACF;EAEA,IACE,OAAO,KAAK,mBAA8C,CAAC,CAAC,WAAW,GACvE;GACA,UACE,GAAG,iBAAiB,oDAAoD,aAAa,YAAY,EAAE,8CACnG,EACE,OAAO,OACT,CACF;GACA;EACF;;;;;;EAOA,IAAI,oBAA8B;EAElC,IAAI,SAAS,YACX,oBACE,oBACG,MACE,uBAAuB,mBAAmB,QAAQ,aACrD,CAAC,EACC,QAAQ,QAAQ,WAAW,cAAc,SAAS,MAAM,CAAC,KAAK,CAAC;EAGvE,IAAI,kBAAkB,WAAW,GAAG;GAClC,UACE,GAAG,iBAAiB,GAAG,SAAS,gCAAgC,WAAW,SAAS,EAAE,GAAG,aAAa,SAAS,yBAAyB,QAAQ,CAAC,KACjJ,EACE,OAAO,OACT,CACF;GACA;EACF;EAEA,iBAAiB,KAAK;GACpB;GACA;GACA;GACA,eAAe;GACf;GACA,oBAAoB,yBAAyB;EAC/C,CAAC;CACH;CAGA,OAAO;AACT"}
|
|
@@ -4,10 +4,10 @@ import { extractTranslatableContent, reinsertTranslatedContent } from "./extract
|
|
|
4
4
|
import { basename } from "node:path";
|
|
5
5
|
import * as ANSIColors from "@intlayer/config/colors";
|
|
6
6
|
import { colon, colorize, colorizeNumber, colorizePath, getAppLogger } from "@intlayer/config/logger";
|
|
7
|
+
import { retryManager } from "@intlayer/config/utils";
|
|
8
|
+
import { getUnmergedDictionaries } from "@intlayer/dictionaries-entry/unmerged";
|
|
7
9
|
import { chunkJSON, excludeObjectFormat, formatLocale, mergeChunks, reconstructFromSingleChunk, verifyIdenticObjectFormat } from "@intlayer/engine/utils";
|
|
8
|
-
import { getUnmergedDictionaries } from "@intlayer/unmerged-dictionaries-entry";
|
|
9
10
|
import { getFilterMissingTranslationsDictionary, getMultilingualDictionary, getPerLocaleDictionary, insertContentInDictionary } from "@intlayer/core/plugins";
|
|
10
|
-
import { retryManager } from "@intlayer/config/utils";
|
|
11
11
|
|
|
12
12
|
//#region src/fill/translateDictionary.ts
|
|
13
13
|
const createChunkPreset = (chunkIndex, totalChunks) => {
|
|
@@ -49,7 +49,7 @@ const translateDictionary = async (task, configuration, options) => {
|
|
|
49
49
|
};
|
|
50
50
|
return await retryManager(async () => {
|
|
51
51
|
const unmergedDictionariesRecord = getUnmergedDictionaries(configuration);
|
|
52
|
-
const baseUnmergedDictionary = unmergedDictionariesRecord[task.dictionaryKey]
|
|
52
|
+
const baseUnmergedDictionary = unmergedDictionariesRecord[task.dictionaryKey]?.find((dict) => dict.localId === task.dictionaryLocalId);
|
|
53
53
|
if (!baseUnmergedDictionary) {
|
|
54
54
|
appLogger(`${task.dictionaryPreset}Dictionary not found in unmergedDictionariesRecord. Skipping.`, { level: "warn" });
|
|
55
55
|
return {
|