@intlayer/cli 9.0.0-canary.8 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/IntlayerEventListener.cjs +1 -1
- package/dist/cjs/IntlayerEventListener.cjs.map +1 -1
- package/dist/cjs/_virtual/_utils_asset.cjs +4 -3
- package/dist/cjs/auth/login.cjs +2 -2
- package/dist/cjs/auth/login.cjs.map +1 -1
- package/dist/cjs/auth/sessionToken.cjs +0 -1
- package/dist/cjs/auth/sessionToken.cjs.map +1 -1
- package/dist/cjs/build.cjs +6 -7
- package/dist/cjs/build.cjs.map +1 -1
- package/dist/cjs/bundle.cjs +32 -1
- package/dist/cjs/bundle.cjs.map +1 -1
- package/dist/cjs/ci.cjs +96 -29
- package/dist/cjs/ci.cjs.map +1 -1
- package/dist/cjs/cli.cjs +163 -129
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/config.cjs +2 -3
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/editor.cjs +0 -1
- package/dist/cjs/editor.cjs.map +1 -1
- package/dist/cjs/extract.cjs +7 -7
- package/dist/cjs/extract.cjs.map +1 -1
- package/dist/cjs/fill/deepMergeContent.cjs.map +1 -1
- package/dist/cjs/fill/extractTranslatableContent.cjs.map +1 -1
- package/dist/cjs/fill/fill.cjs +11 -11
- package/dist/cjs/fill/fill.cjs.map +1 -1
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs +2 -3
- package/dist/cjs/fill/formatAutoFilledFilePath.cjs.map +1 -1
- package/dist/cjs/fill/formatFillData.cjs +3 -4
- package/dist/cjs/fill/formatFillData.cjs.map +1 -1
- package/dist/cjs/fill/getAvailableLocalesInDictionary.cjs.map +1 -1
- package/dist/cjs/fill/getFilterMissingContentPerLocale.cjs.map +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 +7 -7
- package/dist/cjs/fill/translateDictionary.cjs.map +1 -1
- package/dist/cjs/fill/writeFill.cjs +5 -6
- package/dist/cjs/fill/writeFill.cjs.map +1 -1
- package/dist/cjs/getTargetDictionary.cjs +2 -3
- package/dist/cjs/getTargetDictionary.cjs.map +1 -1
- package/dist/cjs/index.cjs +3 -3
- package/dist/cjs/init.cjs +171 -6
- package/dist/cjs/init.cjs.map +1 -1
- package/dist/cjs/initBuildOptimization.cjs +6 -6
- package/dist/cjs/initBuildOptimization.cjs.map +1 -1
- package/dist/cjs/initCompiler.cjs +3 -3
- package/dist/cjs/initCompiler.cjs.map +1 -1
- package/dist/cjs/initMCP.cjs +3 -3
- package/dist/cjs/initMCP.cjs.map +1 -1
- package/dist/cjs/initSkills.cjs +11 -11
- package/dist/cjs/initSkills.cjs.map +1 -1
- package/dist/cjs/listContentDeclaration.cjs +4 -5
- package/dist/cjs/listContentDeclaration.cjs.map +1 -1
- package/dist/cjs/listProjects.cjs +2 -3
- package/dist/cjs/listProjects.cjs.map +1 -1
- package/dist/cjs/liveSync.cjs +4 -4
- package/dist/cjs/liveSync.cjs.map +1 -1
- package/dist/cjs/pull.cjs +7 -7
- package/dist/cjs/pull.cjs.map +1 -1
- package/dist/cjs/push/pullLog.cjs +2 -2
- package/dist/cjs/push/pullLog.cjs.map +1 -1
- package/dist/cjs/push/push.cjs +13 -13
- package/dist/cjs/push/push.cjs.map +1 -1
- package/dist/cjs/pushConfig.cjs +2 -3
- package/dist/cjs/pushConfig.cjs.map +1 -1
- package/dist/cjs/pushLog.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDoc.cjs +16 -16
- package/dist/cjs/reviewDoc/reviewDoc.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs +11 -11
- package/dist/cjs/reviewDoc/reviewDocBlockAware.cjs.map +1 -1
- package/dist/cjs/reviewDoc/reviewDocLog.cjs +7 -8
- package/dist/cjs/reviewDoc/reviewDocLog.cjs.map +1 -1
- package/dist/cjs/scan.cjs +5 -5
- package/dist/cjs/scan.cjs.map +1 -1
- package/dist/cjs/searchDoc.cjs +2 -3
- package/dist/cjs/searchDoc.cjs.map +1 -1
- package/dist/cjs/test/listMissingTranslations.cjs +3 -4
- package/dist/cjs/test/listMissingTranslations.cjs.map +1 -1
- package/dist/cjs/test/test.cjs +11 -11
- package/dist/cjs/test/test.cjs.map +1 -1
- package/dist/cjs/translateDoc/translateDoc.cjs +6 -6
- package/dist/cjs/translateDoc/translateDoc.cjs.map +1 -1
- package/dist/cjs/translateDoc/translateFile.cjs +5 -5
- package/dist/cjs/translateDoc/translateFile.cjs.map +1 -1
- package/dist/cjs/translateDoc/validation.cjs.map +1 -1
- package/dist/cjs/utils/calculateChunks.cjs +4 -5
- package/dist/cjs/utils/calculateChunks.cjs.map +1 -1
- package/dist/cjs/utils/checkAccess.cjs.map +1 -1
- package/dist/cjs/utils/checkConfigConsistency.cjs.map +1 -1
- package/dist/cjs/utils/checkFileModifiedRange.cjs.map +1 -1
- package/dist/cjs/utils/checkLastUpdateTime.cjs +0 -1
- package/dist/cjs/utils/checkLastUpdateTime.cjs.map +1 -1
- package/dist/cjs/utils/chunkInference.cjs +0 -1
- package/dist/cjs/utils/chunkInference.cjs.map +1 -1
- package/dist/cjs/utils/fixChunkStartEndChars.cjs.map +1 -1
- package/dist/cjs/utils/formatLineRanges.cjs.map +1 -1
- package/dist/cjs/utils/formatTimeDiff.cjs.map +1 -1
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs +1 -2
- package/dist/cjs/utils/getIsFileUpdatedRecently.cjs.map +1 -1
- package/dist/cjs/utils/getOutputFilePath.cjs +2 -3
- package/dist/cjs/utils/getOutputFilePath.cjs.map +1 -1
- package/dist/cjs/utils/getParentPackageJSON.cjs +0 -1
- package/dist/cjs/utils/getParentPackageJSON.cjs.map +1 -1
- package/dist/cjs/utils/listSpecialChars.cjs.map +1 -1
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs +4 -5
- package/dist/cjs/utils/mapChunksBetweenFiles.cjs.map +1 -1
- package/dist/cjs/utils/openBrowser.cjs +0 -1
- package/dist/cjs/utils/openBrowser.cjs.map +1 -1
- package/dist/cjs/utils/reorderParagraphs.cjs.map +1 -1
- package/dist/cjs/utils/selectCmsEnvironment.cjs.map +1 -1
- package/dist/cjs/utils/setupAI.cjs.map +1 -1
- package/dist/cjs/watch.cjs +28 -9
- package/dist/cjs/watch.cjs.map +1 -1
- package/dist/esm/IntlayerEventListener.mjs +1 -0
- package/dist/esm/IntlayerEventListener.mjs.map +1 -1
- package/dist/esm/_virtual/_utils_asset.mjs +4 -2
- package/dist/esm/auth/login.mjs +1 -1
- package/dist/esm/auth/login.mjs.map +1 -1
- package/dist/esm/auth/sessionToken.mjs.map +1 -1
- package/dist/esm/build.mjs +3 -3
- package/dist/esm/build.mjs.map +1 -1
- package/dist/esm/bundle.mjs +32 -1
- package/dist/esm/bundle.mjs.map +1 -1
- package/dist/esm/ci.mjs +95 -30
- package/dist/esm/ci.mjs.map +1 -1
- package/dist/esm/cli.mjs +141 -106
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/config.mjs +1 -1
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/editor.mjs.map +1 -1
- package/dist/esm/extract.mjs +3 -3
- package/dist/esm/extract.mjs.map +1 -1
- package/dist/esm/fill/deepMergeContent.mjs.map +1 -1
- package/dist/esm/fill/extractTranslatableContent.mjs.map +1 -1
- package/dist/esm/fill/fill.mjs +3 -3
- package/dist/esm/fill/fill.mjs.map +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs +1 -1
- package/dist/esm/fill/formatAutoFilledFilePath.mjs.map +1 -1
- package/dist/esm/fill/formatFillData.mjs +1 -1
- package/dist/esm/fill/formatFillData.mjs.map +1 -1
- package/dist/esm/fill/getAvailableLocalesInDictionary.mjs.map +1 -1
- package/dist/esm/fill/getFilterMissingContentPerLocale.mjs.map +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 +1 -1
- package/dist/esm/fill/translateDictionary.mjs.map +1 -1
- package/dist/esm/fill/writeFill.mjs +2 -2
- package/dist/esm/fill/writeFill.mjs.map +1 -1
- package/dist/esm/getTargetDictionary.mjs +1 -1
- package/dist/esm/getTargetDictionary.mjs.map +1 -1
- package/dist/esm/index.mjs +3 -3
- package/dist/esm/init.mjs +167 -2
- package/dist/esm/init.mjs.map +1 -1
- package/dist/esm/initBuildOptimization.mjs +1 -1
- package/dist/esm/initBuildOptimization.mjs.map +1 -1
- package/dist/esm/initCompiler.mjs +1 -1
- package/dist/esm/initCompiler.mjs.map +1 -1
- package/dist/esm/initMCP.mjs +1 -1
- package/dist/esm/initMCP.mjs.map +1 -1
- package/dist/esm/initSkills.mjs +1 -1
- package/dist/esm/initSkills.mjs.map +1 -1
- package/dist/esm/listContentDeclaration.mjs +2 -2
- package/dist/esm/listContentDeclaration.mjs.map +1 -1
- package/dist/esm/listProjects.mjs +1 -1
- package/dist/esm/listProjects.mjs.map +1 -1
- package/dist/esm/liveSync.mjs +2 -2
- package/dist/esm/liveSync.mjs.map +1 -1
- package/dist/esm/pull.mjs +4 -4
- package/dist/esm/pull.mjs.map +1 -1
- package/dist/esm/push/pullLog.mjs +2 -2
- package/dist/esm/push/pullLog.mjs.map +1 -1
- package/dist/esm/push/push.mjs +3 -3
- package/dist/esm/push/push.mjs.map +1 -1
- package/dist/esm/pushConfig.mjs +1 -1
- package/dist/esm/pushConfig.mjs.map +1 -1
- package/dist/esm/pushLog.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDoc.mjs +3 -3
- package/dist/esm/reviewDoc/reviewDoc.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDocBlockAware.mjs +2 -2
- package/dist/esm/reviewDoc/reviewDocBlockAware.mjs.map +1 -1
- package/dist/esm/reviewDoc/reviewDocLog.mjs +2 -2
- package/dist/esm/reviewDoc/reviewDocLog.mjs.map +1 -1
- package/dist/esm/scan.mjs +1 -1
- package/dist/esm/scan.mjs.map +1 -1
- package/dist/esm/searchDoc.mjs +1 -1
- package/dist/esm/searchDoc.mjs.map +1 -1
- package/dist/esm/test/listMissingTranslations.mjs +2 -2
- package/dist/esm/test/listMissingTranslations.mjs.map +1 -1
- package/dist/esm/test/test.mjs +2 -2
- package/dist/esm/test/test.mjs.map +1 -1
- package/dist/esm/translateDoc/translateDoc.mjs +2 -2
- package/dist/esm/translateDoc/translateDoc.mjs.map +1 -1
- package/dist/esm/translateDoc/translateFile.mjs +1 -1
- package/dist/esm/translateDoc/translateFile.mjs.map +1 -1
- package/dist/esm/translateDoc/validation.mjs.map +1 -1
- package/dist/esm/utils/calculateChunks.mjs +1 -1
- package/dist/esm/utils/calculateChunks.mjs.map +1 -1
- package/dist/esm/utils/checkAccess.mjs.map +1 -1
- package/dist/esm/utils/checkConfigConsistency.mjs.map +1 -1
- package/dist/esm/utils/checkFileModifiedRange.mjs.map +1 -1
- package/dist/esm/utils/checkLastUpdateTime.mjs.map +1 -1
- package/dist/esm/utils/chunkInference.mjs.map +1 -1
- package/dist/esm/utils/fixChunkStartEndChars.mjs.map +1 -1
- package/dist/esm/utils/formatLineRanges.mjs.map +1 -1
- package/dist/esm/utils/formatTimeDiff.mjs.map +1 -1
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs +1 -1
- package/dist/esm/utils/getIsFileUpdatedRecently.mjs.map +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs +1 -1
- package/dist/esm/utils/getOutputFilePath.mjs.map +1 -1
- package/dist/esm/utils/getParentPackageJSON.mjs.map +1 -1
- package/dist/esm/utils/listSpecialChars.mjs.map +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs +1 -1
- package/dist/esm/utils/mapChunksBetweenFiles.mjs.map +1 -1
- package/dist/esm/utils/openBrowser.mjs.map +1 -1
- package/dist/esm/utils/reorderParagraphs.mjs.map +1 -1
- package/dist/esm/utils/selectCmsEnvironment.mjs.map +1 -1
- package/dist/esm/utils/setupAI.mjs.map +1 -1
- package/dist/esm/watch.mjs +25 -5
- package/dist/esm/watch.mjs.map +1 -1
- package/dist/types/IntlayerEventListener.d.ts +0 -1
- package/dist/types/IntlayerEventListener.d.ts.map +1 -1
- package/dist/types/auth/login.d.ts +0 -1
- package/dist/types/auth/login.d.ts.map +1 -1
- package/dist/types/auth/sessionToken.d.ts +0 -1
- package/dist/types/auth/sessionToken.d.ts.map +1 -1
- package/dist/types/build.d.ts +0 -1
- package/dist/types/build.d.ts.map +1 -1
- package/dist/types/bundle.d.ts +0 -1
- package/dist/types/bundle.d.ts.map +1 -1
- package/dist/types/ci.d.ts +40 -1
- package/dist/types/ci.d.ts.map +1 -1
- package/dist/types/cli.d.ts +0 -1
- package/dist/types/cli.d.ts.map +1 -1
- package/dist/types/config.d.ts +0 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/editor.d.ts.map +1 -1
- package/dist/types/extract.d.ts +0 -1
- package/dist/types/extract.d.ts.map +1 -1
- package/dist/types/fill/deepMergeContent.d.ts.map +1 -1
- package/dist/types/fill/extractTranslatableContent.d.ts.map +1 -1
- package/dist/types/fill/fill.d.ts +1 -2
- package/dist/types/fill/fill.d.ts.map +1 -1
- package/dist/types/fill/formatAutoFilledFilePath.d.ts +0 -1
- package/dist/types/fill/formatAutoFilledFilePath.d.ts.map +1 -1
- package/dist/types/fill/formatFillData.d.ts +0 -1
- package/dist/types/fill/formatFillData.d.ts.map +1 -1
- package/dist/types/fill/getAvailableLocalesInDictionary.d.ts +0 -1
- package/dist/types/fill/getAvailableLocalesInDictionary.d.ts.map +1 -1
- package/dist/types/fill/getFilterMissingContentPerLocale.d.ts +0 -1
- package/dist/types/fill/getFilterMissingContentPerLocale.d.ts.map +1 -1
- package/dist/types/fill/listTranslationsTasks.d.ts +1 -2
- package/dist/types/fill/listTranslationsTasks.d.ts.map +1 -1
- package/dist/types/fill/translateDictionary.d.ts +1 -3
- package/dist/types/fill/translateDictionary.d.ts.map +1 -1
- package/dist/types/fill/writeFill.d.ts +0 -1
- package/dist/types/fill/writeFill.d.ts.map +1 -1
- package/dist/types/getTargetDictionary.d.ts +1 -2
- package/dist/types/getTargetDictionary.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/init.d.ts +1 -2
- package/dist/types/init.d.ts.map +1 -1
- package/dist/types/initBuildOptimization.d.ts.map +1 -1
- package/dist/types/initCompiler.d.ts.map +1 -1
- package/dist/types/initMCP.d.ts +1 -2
- package/dist/types/initMCP.d.ts.map +1 -1
- package/dist/types/initSkills.d.ts +1 -2
- package/dist/types/initSkills.d.ts.map +1 -1
- package/dist/types/listContentDeclaration.d.ts +0 -1
- package/dist/types/listContentDeclaration.d.ts.map +1 -1
- package/dist/types/listProjects.d.ts +1 -2
- package/dist/types/listProjects.d.ts.map +1 -1
- package/dist/types/liveSync.d.ts +0 -1
- package/dist/types/liveSync.d.ts.map +1 -1
- package/dist/types/pull.d.ts +0 -1
- package/dist/types/pull.d.ts.map +1 -1
- package/dist/types/push/pullLog.d.ts +1 -2
- package/dist/types/push/pullLog.d.ts.map +1 -1
- package/dist/types/push/push.d.ts +1 -2
- package/dist/types/push/push.d.ts.map +1 -1
- package/dist/types/pushConfig.d.ts +0 -1
- package/dist/types/pushConfig.d.ts.map +1 -1
- package/dist/types/pushLog.d.ts.map +1 -1
- package/dist/types/reviewDoc/reviewDoc.d.ts +2 -17
- package/dist/types/reviewDoc/reviewDoc.d.ts.map +1 -1
- package/dist/types/reviewDoc/reviewDocBlockAware.d.ts +0 -1
- package/dist/types/reviewDoc/reviewDocBlockAware.d.ts.map +1 -1
- package/dist/types/reviewDoc/reviewDocLog.d.ts +1 -2
- package/dist/types/reviewDoc/reviewDocLog.d.ts.map +1 -1
- package/dist/types/scan.d.ts +3 -2
- package/dist/types/scan.d.ts.map +1 -1
- package/dist/types/searchDoc.d.ts +1 -6
- package/dist/types/searchDoc.d.ts.map +1 -1
- package/dist/types/test/listMissingTranslations.d.ts +0 -1
- package/dist/types/test/listMissingTranslations.d.ts.map +1 -1
- package/dist/types/test/test.d.ts +0 -1
- package/dist/types/test/test.d.ts.map +1 -1
- package/dist/types/translateDoc/translateDoc.d.ts +1 -16
- package/dist/types/translateDoc/translateDoc.d.ts.map +1 -1
- package/dist/types/translateDoc/translateFile.d.ts +1 -16
- package/dist/types/translateDoc/translateFile.d.ts.map +1 -1
- package/dist/types/translateDoc/types.d.ts +1 -2
- package/dist/types/translateDoc/types.d.ts.map +1 -1
- package/dist/types/translateDoc/validation.d.ts +0 -1
- package/dist/types/translateDoc/validation.d.ts.map +1 -1
- package/dist/types/utils/calculateChunks.d.ts.map +1 -1
- package/dist/types/utils/checkAccess.d.ts +0 -1
- package/dist/types/utils/checkAccess.d.ts.map +1 -1
- package/dist/types/utils/checkConfigConsistency.d.ts.map +1 -1
- package/dist/types/utils/checkFileModifiedRange.d.ts.map +1 -1
- package/dist/types/utils/checkLastUpdateTime.d.ts.map +1 -1
- package/dist/types/utils/chunkInference.d.ts +0 -1
- package/dist/types/utils/chunkInference.d.ts.map +1 -1
- package/dist/types/utils/fixChunkStartEndChars.d.ts.map +1 -1
- package/dist/types/utils/formatLineRanges.d.ts.map +1 -1
- package/dist/types/utils/formatTimeDiff.d.ts.map +1 -1
- package/dist/types/utils/getIsFileUpdatedRecently.d.ts.map +1 -1
- package/dist/types/utils/getOutputFilePath.d.ts +0 -1
- package/dist/types/utils/getOutputFilePath.d.ts.map +1 -1
- package/dist/types/utils/getParentPackageJSON.d.ts.map +1 -1
- package/dist/types/utils/listSpecialChars.d.ts +4 -2
- package/dist/types/utils/listSpecialChars.d.ts.map +1 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts +0 -1
- package/dist/types/utils/mapChunksBetweenFiles.d.ts.map +1 -1
- package/dist/types/utils/openBrowser.d.ts.map +1 -1
- package/dist/types/utils/reorderParagraphs.d.ts.map +1 -1
- package/dist/types/utils/selectCmsEnvironment.d.ts +0 -1
- package/dist/types/utils/selectCmsEnvironment.d.ts.map +1 -1
- package/dist/types/utils/setupAI.d.ts +1 -3
- package/dist/types/utils/setupAI.d.ts.map +1 -1
- package/dist/types/watch.d.ts +0 -1
- package/dist/types/watch.d.ts.map +1 -1
- package/package.json +17 -17
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
2
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
4
3
|
let _intlayer_api = require("@intlayer/api");
|
|
5
4
|
let _intlayer_config_built = require("@intlayer/config/built");
|
|
@@ -31,6 +30,7 @@ let eventsource = require("eventsource");
|
|
|
31
30
|
* };
|
|
32
31
|
*/
|
|
33
32
|
var IntlayerEventListener = class {
|
|
33
|
+
intlayerConfig;
|
|
34
34
|
appLogger = (0, _intlayer_config_logger.getAppLogger)({ log: _intlayer_config_built.log });
|
|
35
35
|
eventSource = null;
|
|
36
36
|
reconnectAttempts = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IntlayerEventListener.cjs","names":["EventSource"],"sources":["../../src/IntlayerEventListener.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\n// @ts-ignore: @intlayer/backend is not built yet\nimport type { DictionaryAPI, MessageEventData } from '@intlayer/backend';\nimport { editor, log } from '@intlayer/config/built';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { EventSource } from 'eventsource';\n\nexport type IntlayerMessageEvent = MessageEvent;\n\n/**\n * IntlayerEventListener class to listen for dictionary changes via SSE (Server-Sent Events).\n *\n * Usage example:\n *\n * import { buildIntlayerDictionary } from './transpiler/declaration_file_to_dictionary/intlayer_dictionary';\n * import { IntlayerEventListener } from '@intlayer/api';\n *\n * export const checkDictionaryChanges = async () => {\n * // Instantiate the listener\n * const eventListener = new IntlayerEventListener();\n *\n * // Set up your callbacks\n * eventListener.onDictionaryChange = async (dictionary) => {\n * await buildIntlayerDictionary(dictionary);\n * };\n *\n * // Initialize the listener\n * await eventListener.initialize();\n *\n * // Optionally, clean up later when you’re done\n * // eventListener.cleanup();\n * };\n */\nexport class IntlayerEventListener {\n private appLogger = getAppLogger({ log });\n\n private eventSource: EventSource | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000; // Start with 1 second\n private isManuallyDisconnected = false;\n private reconnectTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Callback triggered when a Dictionary is ADDED.\n */\n public onDictionaryAdded?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is UPDATED.\n */\n public onDictionaryChange?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is DELETED.\n */\n public onDictionaryDeleted?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when connection is established or re-established.\n */\n public onConnectionOpen?: () => any;\n\n /**\n * Callback triggered when connection encounters an error.\n */\n public onConnectionError?: (error: Event) => any;\n\n constructor(\n private intlayerConfig: Pick<IntlayerConfig, 'log' | 'editor'> = {\n log,\n editor,\n }\n ) {\n this.appLogger = getAppLogger(this.intlayerConfig);\n }\n\n /**\n * Initializes the EventSource connection using the given intlayerConfig\n * (or the default config if none was provided).\n */\n public async initialize(): Promise<void> {\n this.isManuallyDisconnected = false;\n await this.connect();\n }\n\n /**\n * Establishes the EventSource connection with automatic reconnection support.\n */\n private async connect(): Promise<void> {\n try {\n const backendURL = this.intlayerConfig.editor.backendURL;\n\n // Retrieve the access token via proxy\n const accessToken = await getIntlayerAPIProxy(\n undefined,\n this.intlayerConfig\n ).oAuth.getOAuth2AccessToken();\n\n if (!accessToken) {\n throw new Error('Failed to retrieve access token');\n }\n\n const API_ROUTE = `${backendURL}/api/event-listener`;\n\n // Close existing connection if any\n if (this.eventSource) {\n this.eventSource.close();\n }\n\n this.eventSource = new EventSource(API_ROUTE, {\n fetch: (input, init) =>\n fetch(input, {\n ...init,\n headers: {\n ...(init?.headers ?? {}),\n Authorization: `Bearer ${accessToken.data?.accessToken}`,\n },\n }),\n });\n\n this.eventSource.onopen = () => {\n this.reconnectAttempts = 0;\n this.reconnectDelay = 1000; // Reset delay\n this.onConnectionOpen?.();\n };\n\n this.eventSource.onmessage = (event) => this.handleMessage(event);\n this.eventSource.onerror = (event) => this.handleError(event);\n } catch (_error) {\n this.appLogger('Failed to establish EventSource connection:', {\n level: 'error',\n });\n this.scheduleReconnect();\n }\n }\n\n /**\n * Cleans up (closes) the EventSource connection.\n */\n public cleanup(): void {\n this.isManuallyDisconnected = true;\n\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n }\n\n /**\n * Schedules a reconnection attempt with exponential backoff.\n */\n private scheduleReconnect(): void {\n if (\n this.isManuallyDisconnected ||\n this.reconnectAttempts >= this.maxReconnectAttempts\n ) {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.appLogger(\n [\n `Max reconnection attempts (${this.maxReconnectAttempts}) reached. Giving up.`,\n ],\n {\n level: 'error',\n }\n );\n }\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectDelay * 2 ** (this.reconnectAttempts - 1); // Exponential backoff\n\n this.appLogger(\n `Scheduling reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`\n );\n\n this.reconnectTimeout = setTimeout(async () => {\n if (!this.isManuallyDisconnected) {\n await this.connect();\n }\n }, delay);\n }\n\n /**\n * Handles incoming SSE messages, parses the event data,\n * and invokes the appropriate callback.\n */\n private async handleMessage(event: IntlayerMessageEvent): Promise<void> {\n try {\n const { data } = event;\n\n const dataJSON: MessageEventData[] = JSON.parse(data);\n\n for (const dataEl of dataJSON) {\n switch (dataEl.object) {\n case 'DICTIONARY':\n switch (dataEl.status) {\n case 'ADDED':\n await this.onDictionaryAdded?.(dataEl.data);\n break;\n case 'UPDATED':\n await this.onDictionaryChange?.(dataEl.data);\n break;\n case 'DELETED':\n await this.onDictionaryDeleted?.(dataEl.data);\n break;\n default:\n this.appLogger(\n ['Unhandled dictionary status:', dataEl.status],\n {\n level: 'error',\n }\n );\n break;\n }\n break;\n default:\n this.appLogger(['Unknown object type:', dataEl.object], {\n level: 'error',\n });\n break;\n }\n }\n } catch (error) {\n this.appLogger(['Error processing dictionary update:', error], {\n level: 'error',\n });\n }\n }\n\n /**\n * Handles any SSE errors and attempts reconnection if appropriate.\n */\n private handleError(event: Event): void {\n const errorEvent = event as any;\n\n // Log detailed error information\n this.appLogger(\n [\n 'EventSource error:',\n {\n type: errorEvent.type,\n message: errorEvent.message,\n code: errorEvent.code,\n readyState: this.eventSource?.readyState,\n url: this.eventSource?.url,\n },\n ],\n {\n level: 'error',\n }\n );\n\n // Notify error callback\n this.onConnectionError?.(event);\n\n // Check if this is a connection close error\n const isConnectionClosed =\n errorEvent.type === 'error' &&\n (errorEvent.message?.includes('terminated') ||\n errorEvent.message?.includes('closed') ||\n this.eventSource?.readyState === EventSource.CLOSED);\n\n if (isConnectionClosed && !this.isManuallyDisconnected) {\n this.appLogger(\n 'Connection was terminated by server, attempting to reconnect...'\n );\n this.scheduleReconnect();\n } else {\n // For other types of errors, close the connection\n this.cleanup();\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IntlayerEventListener.cjs","names":["EventSource"],"sources":["../../src/IntlayerEventListener.ts"],"sourcesContent":["import { getIntlayerAPIProxy } from '@intlayer/api';\n// @ts-ignore: @intlayer/backend is not built yet\nimport type { DictionaryAPI, MessageEventData } from '@intlayer/backend';\nimport { editor, log } from '@intlayer/config/built';\nimport { getAppLogger } from '@intlayer/config/logger';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { EventSource } from 'eventsource';\n\nexport type IntlayerMessageEvent = MessageEvent;\n\n/**\n * IntlayerEventListener class to listen for dictionary changes via SSE (Server-Sent Events).\n *\n * Usage example:\n *\n * import { buildIntlayerDictionary } from './transpiler/declaration_file_to_dictionary/intlayer_dictionary';\n * import { IntlayerEventListener } from '@intlayer/api';\n *\n * export const checkDictionaryChanges = async () => {\n * // Instantiate the listener\n * const eventListener = new IntlayerEventListener();\n *\n * // Set up your callbacks\n * eventListener.onDictionaryChange = async (dictionary) => {\n * await buildIntlayerDictionary(dictionary);\n * };\n *\n * // Initialize the listener\n * await eventListener.initialize();\n *\n * // Optionally, clean up later when you’re done\n * // eventListener.cleanup();\n * };\n */\nexport class IntlayerEventListener {\n private appLogger = getAppLogger({ log });\n\n private eventSource: EventSource | null = null;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000; // Start with 1 second\n private isManuallyDisconnected = false;\n private reconnectTimeout: NodeJS.Timeout | null = null;\n\n /**\n * Callback triggered when a Dictionary is ADDED.\n */\n public onDictionaryAdded?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is UPDATED.\n */\n public onDictionaryChange?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when a Dictionary is DELETED.\n */\n public onDictionaryDeleted?: (dictionary: DictionaryAPI) => any;\n\n /**\n * Callback triggered when connection is established or re-established.\n */\n public onConnectionOpen?: () => any;\n\n /**\n * Callback triggered when connection encounters an error.\n */\n public onConnectionError?: (error: Event) => any;\n\n constructor(\n private intlayerConfig: Pick<IntlayerConfig, 'log' | 'editor'> = {\n log,\n editor,\n }\n ) {\n this.appLogger = getAppLogger(this.intlayerConfig);\n }\n\n /**\n * Initializes the EventSource connection using the given intlayerConfig\n * (or the default config if none was provided).\n */\n public async initialize(): Promise<void> {\n this.isManuallyDisconnected = false;\n await this.connect();\n }\n\n /**\n * Establishes the EventSource connection with automatic reconnection support.\n */\n private async connect(): Promise<void> {\n try {\n const backendURL = this.intlayerConfig.editor.backendURL;\n\n // Retrieve the access token via proxy\n const accessToken = await getIntlayerAPIProxy(\n undefined,\n this.intlayerConfig\n ).oAuth.getOAuth2AccessToken();\n\n if (!accessToken) {\n throw new Error('Failed to retrieve access token');\n }\n\n const API_ROUTE = `${backendURL}/api/event-listener`;\n\n // Close existing connection if any\n if (this.eventSource) {\n this.eventSource.close();\n }\n\n this.eventSource = new EventSource(API_ROUTE, {\n fetch: (input, init) =>\n fetch(input, {\n ...init,\n headers: {\n ...(init?.headers ?? {}),\n Authorization: `Bearer ${accessToken.data?.accessToken}`,\n },\n }),\n });\n\n this.eventSource.onopen = () => {\n this.reconnectAttempts = 0;\n this.reconnectDelay = 1000; // Reset delay\n this.onConnectionOpen?.();\n };\n\n this.eventSource.onmessage = (event) => this.handleMessage(event);\n this.eventSource.onerror = (event) => this.handleError(event);\n } catch (_error) {\n this.appLogger('Failed to establish EventSource connection:', {\n level: 'error',\n });\n this.scheduleReconnect();\n }\n }\n\n /**\n * Cleans up (closes) the EventSource connection.\n */\n public cleanup(): void {\n this.isManuallyDisconnected = true;\n\n if (this.reconnectTimeout) {\n clearTimeout(this.reconnectTimeout);\n this.reconnectTimeout = null;\n }\n\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n }\n\n /**\n * Schedules a reconnection attempt with exponential backoff.\n */\n private scheduleReconnect(): void {\n if (\n this.isManuallyDisconnected ||\n this.reconnectAttempts >= this.maxReconnectAttempts\n ) {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.appLogger(\n [\n `Max reconnection attempts (${this.maxReconnectAttempts}) reached. Giving up.`,\n ],\n {\n level: 'error',\n }\n );\n }\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectDelay * 2 ** (this.reconnectAttempts - 1); // Exponential backoff\n\n this.appLogger(\n `Scheduling reconnection attempt ${this.reconnectAttempts}/${this.maxReconnectAttempts} in ${delay}ms`\n );\n\n this.reconnectTimeout = setTimeout(async () => {\n if (!this.isManuallyDisconnected) {\n await this.connect();\n }\n }, delay);\n }\n\n /**\n * Handles incoming SSE messages, parses the event data,\n * and invokes the appropriate callback.\n */\n private async handleMessage(event: IntlayerMessageEvent): Promise<void> {\n try {\n const { data } = event;\n\n const dataJSON: MessageEventData[] = JSON.parse(data);\n\n for (const dataEl of dataJSON) {\n switch (dataEl.object) {\n case 'DICTIONARY':\n switch (dataEl.status) {\n case 'ADDED':\n await this.onDictionaryAdded?.(dataEl.data);\n break;\n case 'UPDATED':\n await this.onDictionaryChange?.(dataEl.data);\n break;\n case 'DELETED':\n await this.onDictionaryDeleted?.(dataEl.data);\n break;\n default:\n this.appLogger(\n ['Unhandled dictionary status:', dataEl.status],\n {\n level: 'error',\n }\n );\n break;\n }\n break;\n default:\n this.appLogger(['Unknown object type:', dataEl.object], {\n level: 'error',\n });\n break;\n }\n }\n } catch (error) {\n this.appLogger(['Error processing dictionary update:', error], {\n level: 'error',\n });\n }\n }\n\n /**\n * Handles any SSE errors and attempts reconnection if appropriate.\n */\n private handleError(event: Event): void {\n const errorEvent = event as any;\n\n // Log detailed error information\n this.appLogger(\n [\n 'EventSource error:',\n {\n type: errorEvent.type,\n message: errorEvent.message,\n code: errorEvent.code,\n readyState: this.eventSource?.readyState,\n url: this.eventSource?.url,\n },\n ],\n {\n level: 'error',\n }\n );\n\n // Notify error callback\n this.onConnectionError?.(event);\n\n // Check if this is a connection close error\n const isConnectionClosed =\n errorEvent.type === 'error' &&\n (errorEvent.message?.includes('terminated') ||\n errorEvent.message?.includes('closed') ||\n this.eventSource?.readyState === EventSource.CLOSED);\n\n if (isConnectionClosed && !this.isManuallyDisconnected) {\n this.appLogger(\n 'Connection was terminated by server, attempting to reconnect...'\n );\n this.scheduleReconnect();\n } else {\n // For other types of errors, close the connection\n this.cleanup();\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const require_runtime = require('./_rolldown/runtime.cjs');
|
|
2
1
|
let node_fs = require("node:fs");
|
|
3
2
|
let node_path = require("node:path");
|
|
4
3
|
let node_url = require("node:url");
|
|
@@ -42,13 +41,15 @@ const getCallerDir = () => {
|
|
|
42
41
|
const frames = err.stack || [];
|
|
43
42
|
const isVirtualPath = (p) => p.includes(`${node_path.sep}_virtual${node_path.sep}`) || p.includes("/_virtual/");
|
|
44
43
|
for (const frame of frames) {
|
|
45
|
-
const
|
|
44
|
+
const raw = typeof frame.getFileName === "function" ? frame.getFileName() : null;
|
|
45
|
+
const file = normalizeFrameFile(raw);
|
|
46
46
|
if (!file) continue;
|
|
47
47
|
if (file.includes("node:internal") || file.includes(`${node_path.sep}internal${node_path.sep}modules${node_path.sep}`)) continue;
|
|
48
48
|
if (!isVirtualPath(file)) return (0, node_path.dirname)(file);
|
|
49
49
|
}
|
|
50
50
|
for (const frame of frames) {
|
|
51
|
-
const
|
|
51
|
+
const raw = typeof frame.getFileName === "function" ? frame.getFileName() : null;
|
|
52
|
+
const file = normalizeFrameFile(raw);
|
|
52
53
|
if (file) return (0, node_path.dirname)(file);
|
|
53
54
|
}
|
|
54
55
|
} catch {} finally {
|
package/dist/cjs/auth/login.cjs
CHANGED
|
@@ -2,11 +2,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
2
2
|
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_utils_openBrowser = require('../utils/openBrowser.cjs');
|
|
4
4
|
const require_auth_sessionToken = require('./sessionToken.cjs');
|
|
5
|
-
let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
|
|
6
5
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
7
6
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
8
7
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
9
8
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
9
|
+
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
10
10
|
let node_http = require("node:http");
|
|
11
11
|
node_http = require_runtime.__toESM(node_http);
|
|
12
12
|
let node_url = require("node:url");
|
|
@@ -66,7 +66,7 @@ const buildSuccessHtml = (message) => `
|
|
|
66
66
|
`;
|
|
67
67
|
const login = async (options = {}) => {
|
|
68
68
|
const configuration = (0, _intlayer_config_node.getConfiguration)(options.configOptions);
|
|
69
|
-
(0,
|
|
69
|
+
(0, _intlayer_engine_cli.logConfigDetails)(options?.configOptions);
|
|
70
70
|
const logger = (0, _intlayer_config_logger.getAppLogger)(configuration);
|
|
71
71
|
const cmsUrl = options.cmsUrl ?? configuration.editor.cmsURL;
|
|
72
72
|
return new Promise((resolve) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.cjs","names":["http","URL","ANSIColors","writeCliSessionToken"],"sources":["../../../src/auth/login.ts"],"sourcesContent":["import http from 'node:http';\nimport { URL } from 'node:url';\nimport { logConfigDetails } from '@intlayer/chokidar/cli';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { openBrowser } from '../utils/openBrowser';\nimport { writeCliSessionToken } from './sessionToken';\n\nconst buildSuccessHtml = (message: string): string => `\n <!DOCTYPE html>\n <html lang=\"en\" data-theme=\"dark\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Intlayer CLI Login</title>\n <style>\n :root {\n --color-background: rgba(23, 23, 23);\n --color-card: rgba(39, 39, 39);\n --color-text: rgba(255, 245, 237);\n --color-neutral: rgba(93, 93, 93);\n --font-sans: \"Inter\", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n }\n * { box-sizing: border-box; }\n body {\n font-family: var(--font-sans);\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n padding: 1rem;\n background-color: var(--color-background);\n color: var(--color-text);\n }\n .container {\n text-align: center;\n padding: 2rem;\n border-radius: 1rem;\n background-color: var(--color-card);\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 400px;\n width: 100%;\n }\n h1 { margin: 0 0 1rem 0; font-size: 1.5rem; font-weight: 700; color: var(--color-text); }\n p { color: var(--color-neutral); font-size: 0.8rem; margin: 0 0 1.5rem 0; line-height: 1.5; }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <h1>Login Successful</h1>\n <p>${message}</p>\n </div>\n <script>\n window.close();\n setTimeout(() => { window.close(); }, 1000);\n </script>\n </body>\n </html>\n`;\n\ntype LoginOptions = {\n cmsUrl?: string;\n configOptions?: GetConfigurationOptions;\n /**\n * When false, do not call process.exit(0) after a successful login so the\n * caller can continue (e.g. retry a command inline, or finish an interactive\n * setup). Defaults to true to preserve existing standalone-login behaviour.\n */\n exitAfter?: boolean;\n /**\n * Invoked with the access-key credentials when the login flow returns a\n * `clientId` / `clientSecret` pair. When provided, the caller takes ownership\n * of persisting the credentials (e.g. writing them to `.env` and enabling the\n * editor in the config), so the default manual-setup instructions are skipped.\n */\n onCredentials?: (credentials: {\n clientId: string;\n clientSecret: string;\n }) => void | Promise<void>;\n};\n\nexport const login = async (options: LoginOptions = {}) => {\n const configuration = getConfiguration(options.configOptions);\n logConfigDetails(options?.configOptions);\n\n const logger = getAppLogger(configuration);\n\n const cmsUrl = options.cmsUrl ?? configuration.editor.cmsURL;\n\n return new Promise<void>((resolve) => {\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? '', `http://${req.headers.host}`);\n\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (url.pathname === '/callback') {\n const sessionToken = url.searchParams.get('sessionToken');\n const sessionExpiresAt = url.searchParams.get('expiresAt');\n const clientId = url.searchParams.get('clientId');\n const clientSecret = url.searchParams.get('clientSecret');\n\n if (sessionToken && sessionExpiresAt) {\n logger('');\n logger(\n `Log in successful. ${colorize('2h', ANSIColors.BLUE)} session token received.`\n );\n logger('');\n\n logger(\n colorize(\n `Token expires at: ${new Date(sessionExpiresAt).toLocaleString()}`,\n ANSIColors.GREY\n )\n );\n\n await writeCliSessionToken(\n configuration,\n sessionToken,\n new Date(sessionExpiresAt)\n );\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n buildSuccessHtml(\n 'Your 2h session token has been stored. You can now close this tab and return to your terminal.'\n )\n );\n\n server.close(() => {\n resolve();\n if (options.exitAfter !== false) {\n process.exit(0);\n }\n });\n return;\n }\n\n if (clientId && clientSecret) {\n if (options.onCredentials) {\n // The caller persists the credentials itself (e.g. interactive\n // init writing `.env` and enabling the editor in the config).\n logger('');\n logger('Log in successful. Configuring Intlayer CMS...');\n\n try {\n await options.onCredentials({ clientId, clientSecret });\n } catch (error) {\n logger(\n `Failed to persist the CMS credentials automatically: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { level: 'error' }\n );\n }\n } else {\n logger('');\n logger('Log in successful. Client ID and Client Secret received.');\n\n logger('');\n logger([\n '1. Insert the Client ID and Client Secret in your',\n colorizePath('.env'),\n 'file:',\n ]);\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_ID=', ANSIColors.GREY_LIGHT),\n colorize(clientId, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_SECRET=', ANSIColors.GREY_LIGHT),\n colorize(clientSecret, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger('');\n logger('2. Insert in your Intlayer configuration file:');\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n [\n `${ANSIColors.GREY_LIGHT}{`,\n ` editor: {`,\n ` enabled: true,`,\n ` cmsURL: '${colorizePath(cmsUrl!, undefined, ANSIColors.GREY_LIGHT)}',`,\n ` clientId: '${colorize('process.env.INTLAYER_CLIENT_ID', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` clientSecret: '${colorize('process.env.INTLAYER_CLIENT_SECRET', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` },`,\n `}`,\n ].forEach((line) => {\n logger(line);\n });\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n buildSuccessHtml(\n 'You have successfully logged in to Intlayer CLI. You can now close this tab and return to your terminal.'\n )\n );\n\n server.close(() => {\n resolve();\n if (options.exitAfter !== false) {\n process.exit(0);\n }\n });\n } else {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end('Missing parameters');\n }\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n });\n\n server.listen(0, () => {\n const address = server.address();\n const port = typeof address === 'object' && address ? address.port : 0;\n const state = Math.random().toString(36).substring(7);\n\n const websiteUrl =\n cmsUrl ?? process.env.INTLAYER_SITE_URL ?? 'http://localhost:3000';\n const backendUrl = configuration.editor.backendURL ?? '';\n const loginUrl = `${websiteUrl}/auth/cli-login?port=${port}&state=${state}&backendUrl=${encodeURIComponent(backendUrl)}`;\n\n logger('Opening browser for login...');\n logger(`If browser does not open, visit: ${colorizePath(loginUrl)}`);\n\n openBrowser(loginUrl);\n });\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"login.cjs","names":["http","URL","ANSIColors","writeCliSessionToken"],"sources":["../../../src/auth/login.ts"],"sourcesContent":["import http from 'node:http';\nimport { URL } from 'node:url';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, getAppLogger } from '@intlayer/config/logger';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { openBrowser } from '../utils/openBrowser';\nimport { writeCliSessionToken } from './sessionToken';\n\nconst buildSuccessHtml = (message: string): string => `\n <!DOCTYPE html>\n <html lang=\"en\" data-theme=\"dark\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Intlayer CLI Login</title>\n <style>\n :root {\n --color-background: rgba(23, 23, 23);\n --color-card: rgba(39, 39, 39);\n --color-text: rgba(255, 245, 237);\n --color-neutral: rgba(93, 93, 93);\n --font-sans: \"Inter\", -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n }\n * { box-sizing: border-box; }\n body {\n font-family: var(--font-sans);\n display: flex;\n align-items: center;\n justify-content: center;\n min-height: 100vh;\n margin: 0;\n padding: 1rem;\n background-color: var(--color-background);\n color: var(--color-text);\n }\n .container {\n text-align: center;\n padding: 2rem;\n border-radius: 1rem;\n background-color: var(--color-card);\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);\n max-width: 400px;\n width: 100%;\n }\n h1 { margin: 0 0 1rem 0; font-size: 1.5rem; font-weight: 700; color: var(--color-text); }\n p { color: var(--color-neutral); font-size: 0.8rem; margin: 0 0 1.5rem 0; line-height: 1.5; }\n </style>\n </head>\n <body>\n <div class=\"container\">\n <h1>Login Successful</h1>\n <p>${message}</p>\n </div>\n <script>\n window.close();\n setTimeout(() => { window.close(); }, 1000);\n </script>\n </body>\n </html>\n`;\n\ntype LoginOptions = {\n cmsUrl?: string;\n configOptions?: GetConfigurationOptions;\n /**\n * When false, do not call process.exit(0) after a successful login so the\n * caller can continue (e.g. retry a command inline, or finish an interactive\n * setup). Defaults to true to preserve existing standalone-login behaviour.\n */\n exitAfter?: boolean;\n /**\n * Invoked with the access-key credentials when the login flow returns a\n * `clientId` / `clientSecret` pair. When provided, the caller takes ownership\n * of persisting the credentials (e.g. writing them to `.env` and enabling the\n * editor in the config), so the default manual-setup instructions are skipped.\n */\n onCredentials?: (credentials: {\n clientId: string;\n clientSecret: string;\n }) => void | Promise<void>;\n};\n\nexport const login = async (options: LoginOptions = {}) => {\n const configuration = getConfiguration(options.configOptions);\n logConfigDetails(options?.configOptions);\n\n const logger = getAppLogger(configuration);\n\n const cmsUrl = options.cmsUrl ?? configuration.editor.cmsURL;\n\n return new Promise<void>((resolve) => {\n const server = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? '', `http://${req.headers.host}`);\n\n // Set CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (url.pathname === '/callback') {\n const sessionToken = url.searchParams.get('sessionToken');\n const sessionExpiresAt = url.searchParams.get('expiresAt');\n const clientId = url.searchParams.get('clientId');\n const clientSecret = url.searchParams.get('clientSecret');\n\n if (sessionToken && sessionExpiresAt) {\n logger('');\n logger(\n `Log in successful. ${colorize('2h', ANSIColors.BLUE)} session token received.`\n );\n logger('');\n\n logger(\n colorize(\n `Token expires at: ${new Date(sessionExpiresAt).toLocaleString()}`,\n ANSIColors.GREY\n )\n );\n\n await writeCliSessionToken(\n configuration,\n sessionToken,\n new Date(sessionExpiresAt)\n );\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n buildSuccessHtml(\n 'Your 2h session token has been stored. You can now close this tab and return to your terminal.'\n )\n );\n\n server.close(() => {\n resolve();\n if (options.exitAfter !== false) {\n process.exit(0);\n }\n });\n return;\n }\n\n if (clientId && clientSecret) {\n if (options.onCredentials) {\n // The caller persists the credentials itself (e.g. interactive\n // init writing `.env` and enabling the editor in the config).\n logger('');\n logger('Log in successful. Configuring Intlayer CMS...');\n\n try {\n await options.onCredentials({ clientId, clientSecret });\n } catch (error) {\n logger(\n `Failed to persist the CMS credentials automatically: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { level: 'error' }\n );\n }\n } else {\n logger('');\n logger('Log in successful. Client ID and Client Secret received.');\n\n logger('');\n logger([\n '1. Insert the Client ID and Client Secret in your',\n colorizePath('.env'),\n 'file:',\n ]);\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_ID=', ANSIColors.GREY_LIGHT),\n colorize(clientId, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n [\n colorize('INTLAYER_CLIENT_SECRET=', ANSIColors.GREY_LIGHT),\n colorize(clientSecret, ANSIColors.BLUE),\n ].join('')\n );\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n logger('');\n logger('2. Insert in your Intlayer configuration file:');\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n [\n `${ANSIColors.GREY_LIGHT}{`,\n ` editor: {`,\n ` enabled: true,`,\n ` cmsURL: '${colorizePath(cmsUrl!, undefined, ANSIColors.GREY_LIGHT)}',`,\n ` clientId: '${colorize('process.env.INTLAYER_CLIENT_ID', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` clientSecret: '${colorize('process.env.INTLAYER_CLIENT_SECRET', ANSIColors.BLUE, ANSIColors.GREY_LIGHT)}',`,\n ` },`,\n `}`,\n ].forEach((line) => {\n logger(line);\n });\n logger(\n colorize('--------------------------------', ANSIColors.GREY_DARK)\n );\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n buildSuccessHtml(\n 'You have successfully logged in to Intlayer CLI. You can now close this tab and return to your terminal.'\n )\n );\n\n server.close(() => {\n resolve();\n if (options.exitAfter !== false) {\n process.exit(0);\n }\n });\n } else {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end('Missing parameters');\n }\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('Not found');\n }\n });\n\n server.listen(0, () => {\n const address = server.address();\n const port = typeof address === 'object' && address ? address.port : 0;\n const state = Math.random().toString(36).substring(7);\n\n const websiteUrl =\n cmsUrl ?? process.env.INTLAYER_SITE_URL ?? 'http://localhost:3000';\n const backendUrl = configuration.editor.backendURL ?? '';\n const loginUrl = `${websiteUrl}/auth/cli-login?port=${port}&state=${state}&backendUrl=${encodeURIComponent(backendUrl)}`;\n\n logger('Opening browser for login...');\n logger(`If browser does not open, visit: ${colorizePath(loginUrl)}`);\n\n openBrowser(loginUrl);\n });\n });\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionToken.cjs","names":[],"sources":["../../../src/auth/sessionToken.ts"],"sourcesContent":["import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\nconst SESSION_FILE_NAME = 'cli-session.json';\n\nexport type CliSessionData = {\n token: string;\n expiresAt: string; // ISO date string\n};\n\nconst getSessionFilePath = (config: IntlayerConfig): string =>\n join(config.system.tempDir, SESSION_FILE_NAME);\n\nexport const writeCliSessionToken = async (\n config: IntlayerConfig,\n token: string,\n expiresAt: Date\n): Promise<void> => {\n const filePath = getSessionFilePath(config);\n\n await mkdir(config.system.tempDir, { recursive: true });\n\n const data: CliSessionData = { token, expiresAt: expiresAt.toISOString() };\n await writeFile(filePath, JSON.stringify(data, null, 2), { mode: 0o600 });\n};\n\nexport const readCliSessionToken = async (\n config: IntlayerConfig\n): Promise<CliSessionData | null> => {\n const filePath = getSessionFilePath(config);\n\n try {\n const raw = await readFile(filePath, 'utf8');\n const data: CliSessionData = JSON.parse(raw);\n\n if (!data.token || !data.expiresAt) {\n return null;\n }\n\n if (new Date() >= new Date(data.expiresAt)) {\n await clearCliSessionToken(config);\n return null;\n }\n\n return data;\n } catch {\n return null;\n }\n};\n\nexport const clearCliSessionToken = async (\n config: IntlayerConfig\n): Promise<void> => {\n try {\n await unlink(getSessionFilePath(config));\n } catch {\n // Ignore errors (file may not exist)\n }\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"sessionToken.cjs","names":[],"sources":["../../../src/auth/sessionToken.ts"],"sourcesContent":["import { mkdir, readFile, unlink, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { IntlayerConfig } from '@intlayer/types/config';\n\nconst SESSION_FILE_NAME = 'cli-session.json';\n\nexport type CliSessionData = {\n token: string;\n expiresAt: string; // ISO date string\n};\n\nconst getSessionFilePath = (config: IntlayerConfig): string =>\n join(config.system.tempDir, SESSION_FILE_NAME);\n\nexport const writeCliSessionToken = async (\n config: IntlayerConfig,\n token: string,\n expiresAt: Date\n): Promise<void> => {\n const filePath = getSessionFilePath(config);\n\n await mkdir(config.system.tempDir, { recursive: true });\n\n const data: CliSessionData = { token, expiresAt: expiresAt.toISOString() };\n await writeFile(filePath, JSON.stringify(data, null, 2), { mode: 0o600 });\n};\n\nexport const readCliSessionToken = async (\n config: IntlayerConfig\n): Promise<CliSessionData | null> => {\n const filePath = getSessionFilePath(config);\n\n try {\n const raw = await readFile(filePath, 'utf8');\n const data: CliSessionData = JSON.parse(raw);\n\n if (!data.token || !data.expiresAt) {\n return null;\n }\n\n if (new Date() >= new Date(data.expiresAt)) {\n await clearCliSessionToken(config);\n return null;\n }\n\n return data;\n } catch {\n return null;\n }\n};\n\nexport const clearCliSessionToken = async (\n config: IntlayerConfig\n): Promise<void> => {\n try {\n await unlink(getSessionFilePath(config));\n } catch {\n // Ignore errors (file may not exist)\n }\n};\n"],"mappings":";;;;;AAIA,MAAM,oBAAoB;AAO1B,MAAM,sBAAsB,+BACrB,OAAO,OAAO,SAAS,iBAAiB;AAE/C,MAAa,uBAAuB,OAClC,QACA,OACA,cACkB;CAClB,MAAM,WAAW,mBAAmB,MAAM;CAE1C,kCAAY,OAAO,OAAO,SAAS,EAAE,WAAW,KAAK,CAAC;CAEtD,MAAM,OAAuB;EAAE;EAAO,WAAW,UAAU,YAAY;CAAE;CACzE,sCAAgB,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,EAAE,MAAM,IAAM,CAAC;AAC1E;AAEA,MAAa,sBAAsB,OACjC,WACmC;CACnC,MAAM,WAAW,mBAAmB,MAAM;CAE1C,IAAI;EACF,MAAM,MAAM,qCAAe,UAAU,MAAM;EAC3C,MAAM,OAAuB,KAAK,MAAM,GAAG;EAE3C,IAAI,CAAC,KAAK,SAAS,CAAC,KAAK,WACvB,OAAO;EAGT,oBAAI,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,GAAG;GAC1C,MAAM,qBAAqB,MAAM;GACjC,OAAO;EACT;EAEA,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAa,uBAAuB,OAClC,WACkB;CAClB,IAAI;EACF,mCAAa,mBAAmB,MAAM,CAAC;CACzC,QAAQ,CAER;AACF"}
|
package/dist/cjs/build.cjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
|
-
let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
|
|
4
|
-
let _intlayer_chokidar_utils = require("@intlayer/chokidar/utils");
|
|
5
2
|
let _intlayer_config_node = require("@intlayer/config/node");
|
|
6
|
-
let
|
|
3
|
+
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
4
|
+
let _intlayer_engine_utils = require("@intlayer/engine/utils");
|
|
5
|
+
let _intlayer_engine_watcher = require("@intlayer/engine/watcher");
|
|
7
6
|
|
|
8
7
|
//#region src/build.ts
|
|
9
8
|
/**
|
|
@@ -12,13 +11,13 @@ let _intlayer_chokidar_watcher = require("@intlayer/chokidar/watcher");
|
|
|
12
11
|
*/
|
|
13
12
|
const build = async (options) => {
|
|
14
13
|
const config = (0, _intlayer_config_node.getConfiguration)(options?.configOptions);
|
|
15
|
-
(0,
|
|
14
|
+
(0, _intlayer_engine_cli.logConfigDetails)(options?.configOptions);
|
|
16
15
|
let parallelProcess = null;
|
|
17
16
|
if (options?.with) {
|
|
18
|
-
parallelProcess = (0,
|
|
17
|
+
parallelProcess = (0, _intlayer_engine_utils.runParallel)(options.with);
|
|
19
18
|
parallelProcess.result.catch(() => {});
|
|
20
19
|
}
|
|
21
|
-
await (0,
|
|
20
|
+
await (0, _intlayer_engine_watcher.buildAndWatchIntlayer)({
|
|
22
21
|
persistent: options?.watch ?? false,
|
|
23
22
|
skipPrepare: options?.skipPrepare ?? false,
|
|
24
23
|
configuration: config
|
package/dist/cjs/build.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.cjs","names":[],"sources":["../../src/build.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"build.cjs","names":[],"sources":["../../src/build.ts"],"sourcesContent":["import {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { logConfigDetails } from '@intlayer/engine/cli';\nimport { type ParallelHandle, runParallel } from '@intlayer/engine/utils';\nimport { buildAndWatchIntlayer } from '@intlayer/engine/watcher';\n\ntype BuildOptions = {\n watch?: boolean;\n skipPrepare?: boolean;\n with?: string | string[];\n configOptions?: GetConfigurationOptions;\n};\n\n/**\n * Get locales dictionaries .content.{json|ts|tsx|js|jsx|mjs|cjs} and build the JSON dictionaries in the .intlayer directory.\n * Watch mode available to get the change in the .content.{json|ts|tsx|js|jsx|mjs|cjs}\n */\nexport const build = async (options?: BuildOptions) => {\n const config = getConfiguration(options?.configOptions);\n logConfigDetails(options?.configOptions);\n\n let parallelProcess: ParallelHandle | null = null;\n\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 await buildAndWatchIntlayer({\n persistent: options?.watch ?? false,\n skipPrepare: options?.skipPrepare ?? false,\n configuration: config,\n });\n\n if (!options?.watch && parallelProcess) {\n parallelProcess.kill();\n }\n};\n"],"mappings":";;;;;;;;;;;AAmBA,MAAa,QAAQ,OAAO,YAA2B;CACrD,MAAM,qDAA0B,SAAS,aAAa;CACtD,2CAAiB,SAAS,aAAa;CAEvC,IAAI,kBAAyC;CAE7C,IAAI,SAAS,MAAM;EACjB,0DAA8B,QAAQ,IAAI;EAE1C,gBAAgB,OAAO,YAAY,CAEnC,CAAC;CACH;CAEA,0DAA4B;EAC1B,YAAY,SAAS,SAAS;EAC9B,aAAa,SAAS,eAAe;EACrC,eAAe;CACjB,CAAC;CAED,IAAI,CAAC,SAAS,SAAS,iBACrB,gBAAgB,KAAK;AAEzB"}
|
package/dist/cjs/bundle.cjs
CHANGED
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
//#region src/bundle.ts
|
|
4
|
+
/**
|
|
5
|
+
* Computes the tree-shaking defines derived from the project's built
|
|
6
|
+
* dictionaries (unused node types, dictionary selector usage) so the generated
|
|
7
|
+
* bundle drops the corresponding runtime logic, mirroring what the bundler
|
|
8
|
+
* plugins (vite / webpack / esbuild) inject at application build time.
|
|
9
|
+
*
|
|
10
|
+
* Returns an empty object when no dictionary has been built yet: shaking based
|
|
11
|
+
* on an empty dictionary set would mark every node type as unused and strip
|
|
12
|
+
* logic that the runtime content may require.
|
|
13
|
+
*/
|
|
14
|
+
const getDictionaryTreeShakingDefines = async (options) => {
|
|
15
|
+
const { formatDictionarySelectorEnvVar, formatNodeTypeToEnvVar } = await import("@intlayer/config/envVars");
|
|
16
|
+
const { getConfiguration } = await import("@intlayer/config/node");
|
|
17
|
+
const { getHasDictionarySelector, getUnusedNodeTypesAsync } = await import("@intlayer/config/utils");
|
|
18
|
+
const { getDictionaries } = await import("@intlayer/dictionaries-entry");
|
|
19
|
+
const dictionaries = getDictionaries(getConfiguration(options.configOptions));
|
|
20
|
+
if (Object.keys(dictionaries).length === 0) return {};
|
|
21
|
+
const wrapKey = (key) => `process.env.${key}`;
|
|
22
|
+
const wrapValue = (value) => `"${value}"`;
|
|
23
|
+
return {
|
|
24
|
+
...formatNodeTypeToEnvVar(await getUnusedNodeTypesAsync(dictionaries), wrapKey, wrapValue),
|
|
25
|
+
...formatDictionarySelectorEnvVar(getHasDictionarySelector(dictionaries), wrapKey, wrapValue)
|
|
26
|
+
};
|
|
27
|
+
};
|
|
4
28
|
const bundle = async (options) => {
|
|
5
29
|
try {
|
|
6
30
|
const { bundleIntlayer } = await import("@intlayer/config/bundle");
|
|
7
|
-
await
|
|
31
|
+
const dictionaryDefines = await getDictionaryTreeShakingDefines(options);
|
|
32
|
+
await bundleIntlayer({
|
|
33
|
+
...options,
|
|
34
|
+
define: {
|
|
35
|
+
...dictionaryDefines,
|
|
36
|
+
...options.define
|
|
37
|
+
}
|
|
38
|
+
});
|
|
8
39
|
} catch (error) {
|
|
9
40
|
console.error("Failed to create bundle:", error);
|
|
10
41
|
process.exit(1);
|
package/dist/cjs/bundle.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bundle.cjs","names":[],"sources":["../../src/bundle.ts"],"sourcesContent":["import type { BundleIntlayerOptions } from '@intlayer/config/bundle';\n\nexport const bundle = async (options: BundleIntlayerOptions): Promise<void> => {\n try {\n // Dynamic import for performance reason\n const { bundleIntlayer } = await import('@intlayer/config/bundle');\n await bundleIntlayer(options);\n } catch (error) {\n console.error('Failed to create bundle:', error);\n process.exit(1);\n }\n};\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"bundle.cjs","names":[],"sources":["../../src/bundle.ts"],"sourcesContent":["import type { BundleIntlayerOptions } from '@intlayer/config/bundle';\n\n/**\n * Computes the tree-shaking defines derived from the project's built\n * dictionaries (unused node types, dictionary selector usage) so the generated\n * bundle drops the corresponding runtime logic, mirroring what the bundler\n * plugins (vite / webpack / esbuild) inject at application build time.\n *\n * Returns an empty object when no dictionary has been built yet: shaking based\n * on an empty dictionary set would mark every node type as unused and strip\n * logic that the runtime content may require.\n */\nconst getDictionaryTreeShakingDefines = async (\n options: BundleIntlayerOptions\n): Promise<Record<string, string>> => {\n // Dynamic imports for performance reason\n const { formatDictionarySelectorEnvVar, formatNodeTypeToEnvVar } =\n await import('@intlayer/config/envVars');\n const { getConfiguration } = await import('@intlayer/config/node');\n const { getHasDictionarySelector, getUnusedNodeTypesAsync } = await import(\n '@intlayer/config/utils'\n );\n const { getDictionaries } = await import('@intlayer/dictionaries-entry');\n\n const configuration = getConfiguration(options.configOptions);\n const dictionaries = getDictionaries(configuration);\n\n if (Object.keys(dictionaries).length === 0) return {};\n\n const wrapKey = (key: string) => `process.env.${key}`;\n const wrapValue = (value: string) => `\"${value}\"`;\n\n const unusedNodeTypes = await getUnusedNodeTypesAsync(dictionaries);\n\n return {\n // Tree shaking based on unused node types\n ...formatNodeTypeToEnvVar(unusedNodeTypes, wrapKey, wrapValue),\n // Tree shaking the dictionary selector logic (collections / variants)\n ...formatDictionarySelectorEnvVar(\n getHasDictionarySelector(dictionaries),\n wrapKey,\n wrapValue\n ),\n };\n};\n\nexport const bundle = async (options: BundleIntlayerOptions): Promise<void> => {\n try {\n // Dynamic import for performance reason\n const { bundleIntlayer } = await import('@intlayer/config/bundle');\n\n const dictionaryDefines = await getDictionaryTreeShakingDefines(options);\n\n await bundleIntlayer({\n ...options,\n define: {\n ...dictionaryDefines,\n // Caller-supplied defines take precedence\n ...options.define,\n },\n });\n } catch (error) {\n console.error('Failed to create bundle:', error);\n process.exit(1);\n }\n};\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAM,kCAAkC,OACtC,YACoC;CAEpC,MAAM,EAAE,gCAAgC,2BACtC,MAAM,OAAO;CACf,MAAM,EAAE,qBAAqB,MAAM,OAAO;CAC1C,MAAM,EAAE,0BAA0B,4BAA4B,MAAM,OAClE;CAEF,MAAM,EAAE,oBAAoB,MAAM,OAAO;CAGzC,MAAM,eAAe,gBADC,iBAAiB,QAAQ,aACE,CAAC;CAElD,IAAI,OAAO,KAAK,YAAY,CAAC,CAAC,WAAW,GAAG,OAAO,CAAC;CAEpD,MAAM,WAAW,QAAgB,eAAe;CAChD,MAAM,aAAa,UAAkB,IAAI,MAAM;CAI/C,OAAO;EAEL,GAAG,uBAAuB,MAJE,wBAAwB,YAAY,GAIrB,SAAS,SAAS;EAE7D,GAAG,+BACD,yBAAyB,YAAY,GACrC,SACA,SACF;CACF;AACF;AAEA,MAAa,SAAS,OAAO,YAAkD;CAC7E,IAAI;EAEF,MAAM,EAAE,mBAAmB,MAAM,OAAO;EAExC,MAAM,oBAAoB,MAAM,gCAAgC,OAAO;EAEvE,MAAM,eAAe;GACnB,GAAG;GACH,QAAQ;IACN,GAAG;IAEH,GAAG,QAAQ;GACb;EACF,CAAC;CACH,SAAS,OAAO;EACd,QAAQ,MAAM,4BAA4B,KAAK;EAC/C,QAAQ,KAAK,CAAC;CAChB;AACF"}
|
package/dist/cjs/ci.cjs
CHANGED
|
@@ -1,30 +1,88 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
2
|
let node_path = require("node:path");
|
|
4
|
-
let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
|
|
5
3
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
4
|
+
let _intlayer_engine_cli = require("@intlayer/engine/cli");
|
|
6
5
|
let node_child_process = require("node:child_process");
|
|
7
6
|
|
|
8
7
|
//#region src/ci.ts
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Detects the command used to run the local `intlayer` binary. Prefers the
|
|
10
|
+
* package manager that launched the current process (`npm_config_user_agent`),
|
|
11
|
+
* and falls back to lock file detection when the CLI was not started through a
|
|
12
|
+
* package manager (e.g. a global install or a bare CI runner).
|
|
13
|
+
*/
|
|
14
|
+
const getPackageManagerCommand = (lockFileSearchDir) => {
|
|
10
15
|
const userAgent = process.env.npm_config_user_agent;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
const commandByPackageManager = {
|
|
17
|
+
bun: {
|
|
18
|
+
command: "bun",
|
|
19
|
+
args: ["intlayer"]
|
|
20
|
+
},
|
|
21
|
+
pnpm: {
|
|
22
|
+
command: "pnpm",
|
|
23
|
+
args: ["exec", "intlayer"]
|
|
24
|
+
},
|
|
25
|
+
yarn: {
|
|
26
|
+
command: "yarn",
|
|
27
|
+
args: ["run", "intlayer"]
|
|
28
|
+
},
|
|
29
|
+
npm: {
|
|
30
|
+
command: "npx",
|
|
31
|
+
args: ["intlayer"]
|
|
32
|
+
}
|
|
18
33
|
};
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
34
|
+
const userAgentPackageManager = Object.keys(commandByPackageManager).find((packageManager) => userAgent?.startsWith(packageManager));
|
|
35
|
+
if (userAgentPackageManager) return commandByPackageManager[userAgentPackageManager];
|
|
36
|
+
return commandByPackageManager[(0, _intlayer_engine_cli.detectPackageManager)(lockFileSearchDir)];
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Splits a path into segments, accepting both posix and windows separators so
|
|
40
|
+
* credential keys written on any OS compare equal to local project paths.
|
|
41
|
+
*/
|
|
42
|
+
const toPathSegments = (path) => path.split(/[\\/]+/).filter((segment) => segment !== "" && segment !== ".");
|
|
43
|
+
/**
|
|
44
|
+
* Returns true when a credentials key designates the given project directory.
|
|
45
|
+
* A key matches when it is:
|
|
46
|
+
* - the absolute path of the project,
|
|
47
|
+
* - a path relative to `searchDir` (the repository root), or
|
|
48
|
+
* - a trailing sequence of full path segments of the project path (so the key
|
|
49
|
+
* `"apps/web"` matches `/repo/apps/web`, but `"app"` never matches
|
|
50
|
+
* `/repo/my-app`).
|
|
51
|
+
*/
|
|
52
|
+
const credentialsKeyMatchesProject = (key, projectPath, searchDir) => {
|
|
53
|
+
if ((0, node_path.resolve)(key) === projectPath) return true;
|
|
54
|
+
if ((0, node_path.resolve)(searchDir, key) === projectPath) return true;
|
|
55
|
+
const keySegments = toPathSegments(key);
|
|
56
|
+
const projectSegments = toPathSegments(projectPath);
|
|
57
|
+
if (keySegments.length === 0 || keySegments.length > projectSegments.length) return false;
|
|
58
|
+
const trailingProjectSegments = projectSegments.slice(-keySegments.length);
|
|
59
|
+
return keySegments.every((segment, index) => trailingProjectSegments[index] === segment);
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Selects the projects the CI command must run in:
|
|
63
|
+
* - run from the repository root → every discovered project (monorepo mode);
|
|
64
|
+
* - run from inside a project directory (or any of its subdirectories) → that
|
|
65
|
+
* project only, the deepest match winning when projects are nested;
|
|
66
|
+
* - run anywhere else → every discovered project.
|
|
67
|
+
*/
|
|
68
|
+
const selectProjectsToRun = (currentWorkingDir, searchDir, projectsPath) => {
|
|
69
|
+
const cwd = (0, node_path.resolve)(currentWorkingDir);
|
|
70
|
+
if (cwd === (0, node_path.resolve)(searchDir)) return {
|
|
71
|
+
projectsToRun: projectsPath,
|
|
72
|
+
currentProject: void 0
|
|
22
73
|
};
|
|
74
|
+
const currentProject = projectsPath.filter((projectPath) => cwd === projectPath || cwd.startsWith(projectPath + node_path.sep)).sort((a, b) => b.length - a.length)[0];
|
|
23
75
|
return {
|
|
24
|
-
|
|
25
|
-
|
|
76
|
+
projectsToRun: currentProject ? [currentProject] : projectsPath,
|
|
77
|
+
currentProject
|
|
26
78
|
};
|
|
27
79
|
};
|
|
80
|
+
/**
|
|
81
|
+
* Runs an intlayer command in every Intlayer project of the repository (or
|
|
82
|
+
* only in the current one when invoked from inside a project directory),
|
|
83
|
+
* injecting per-project CMS credentials from `INTLAYER_PROJECT_CREDENTIALS`.
|
|
84
|
+
* Exits with code 1 when the command fails in at least one project.
|
|
85
|
+
*/
|
|
28
86
|
const runCI = async (commands) => {
|
|
29
87
|
const credentialsEnv = process.env.INTLAYER_PROJECT_CREDENTIALS;
|
|
30
88
|
let credentials = {};
|
|
@@ -33,15 +91,14 @@ const runCI = async (commands) => {
|
|
|
33
91
|
} catch {
|
|
34
92
|
(0, _intlayer_config_logger.logger)("INTLAYER_PROJECT_CREDENTIALS is not valid JSON. Proceeding without credentials.", { level: "warn" });
|
|
35
93
|
}
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
94
|
+
const { searchDir, projectsPath } = await (0, _intlayer_engine_cli.listProjects)({ gitRoot: true });
|
|
95
|
+
const normalizedProjectsPath = projectsPath.map((projectPath) => (0, node_path.resolve)(projectPath));
|
|
96
|
+
if (normalizedProjectsPath.length === 0) {
|
|
39
97
|
(0, _intlayer_config_logger.logger)("No Intlayer projects found.", { level: "warn" });
|
|
40
98
|
return;
|
|
41
99
|
}
|
|
42
|
-
const currentProject =
|
|
43
|
-
const
|
|
44
|
-
const { command, args: pmArgs } = getPackageManagerCommand();
|
|
100
|
+
const { projectsToRun, currentProject } = selectProjectsToRun(process.cwd(), searchDir, normalizedProjectsPath);
|
|
101
|
+
const { command, args: pmArgs } = getPackageManagerCommand(searchDir);
|
|
45
102
|
const finalArgs = [...pmArgs, ...commands];
|
|
46
103
|
(0, _intlayer_config_logger.logger)(`CI: Using package manager: ${command}`, {
|
|
47
104
|
level: "info",
|
|
@@ -49,29 +106,39 @@ const runCI = async (commands) => {
|
|
|
49
106
|
});
|
|
50
107
|
if (currentProject) (0, _intlayer_config_logger.logger)(`CI: Detected project context: ${currentProject}`, { level: "info" });
|
|
51
108
|
else (0, _intlayer_config_logger.logger)(`CI: No specific project context detected. Iterating over ${projectsToRun.length} discovered projects...`, { level: "info" });
|
|
52
|
-
|
|
109
|
+
const failedProjects = [];
|
|
53
110
|
for (const projectPath of projectsToRun) {
|
|
54
|
-
const creds = Object.entries(credentials).find(([key]) =>
|
|
55
|
-
return (0, node_path.resolve)(key) === projectPath || projectPath.endsWith((0, node_path.normalize)(key));
|
|
56
|
-
})?.[1];
|
|
111
|
+
const creds = Object.entries(credentials).find(([key]) => credentialsKeyMatchesProject(key, projectPath, searchDir))?.[1];
|
|
57
112
|
(0, _intlayer_config_logger.logger)(`\nCI: Executing for ${projectPath}...`, { level: "info" });
|
|
58
113
|
const envVars = { ...process.env };
|
|
59
114
|
if (creds) {
|
|
60
115
|
envVars.INTLAYER_CLIENT_ID = creds.clientId;
|
|
61
116
|
envVars.INTLAYER_CLIENT_SECRET = creds.clientSecret;
|
|
62
117
|
} else if (credentialsEnv) (0, _intlayer_config_logger.logger)(`CI: No matching credentials found for ${projectPath} in INTLAYER_PROJECT_CREDENTIALS.`, { isVerbose: true });
|
|
63
|
-
|
|
118
|
+
const result = (0, node_child_process.spawnSync)(command, finalArgs, {
|
|
64
119
|
cwd: projectPath,
|
|
65
120
|
stdio: "inherit",
|
|
66
121
|
env: envVars
|
|
67
|
-
})
|
|
122
|
+
});
|
|
123
|
+
if (result.error) {
|
|
124
|
+
(0, _intlayer_config_logger.logger)(`CI: Failed to launch "${command}" for ${projectPath}: ${result.error.message}`, { level: "error" });
|
|
125
|
+
failedProjects.push(projectPath);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (result.status !== 0) {
|
|
68
129
|
(0, _intlayer_config_logger.logger)(`CI: Failed for ${projectPath}`, { level: "error" });
|
|
69
|
-
|
|
130
|
+
failedProjects.push(projectPath);
|
|
70
131
|
}
|
|
71
132
|
}
|
|
72
|
-
if (
|
|
133
|
+
if (failedProjects.length > 0) {
|
|
134
|
+
(0, _intlayer_config_logger.logger)(`\nCI: ${failedProjects.length}/${projectsToRun.length} project(s) failed:\n${failedProjects.map((projectPath) => ` - ${projectPath}`).join("\n")}`, { level: "error" });
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
73
137
|
};
|
|
74
138
|
|
|
75
139
|
//#endregion
|
|
140
|
+
exports.credentialsKeyMatchesProject = credentialsKeyMatchesProject;
|
|
141
|
+
exports.getPackageManagerCommand = getPackageManagerCommand;
|
|
76
142
|
exports.runCI = runCI;
|
|
143
|
+
exports.selectProjectsToRun = selectProjectsToRun;
|
|
77
144
|
//# sourceMappingURL=ci.cjs.map
|
package/dist/cjs/ci.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci.cjs","names":[],"sources":["../../src/ci.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { normalize, resolve } from 'node:path';\nimport { listProjects } from '@intlayer/chokidar/cli';\nimport { logger } from '@intlayer/config/logger';\n\n// Helper to detect the package manager used to run the command\nconst getPackageManagerCommand = () => {\n const userAgent = process.env.npm_config_user_agent;\n\n if (userAgent?.startsWith('bun')) {\n return { command: 'bun', args: ['intlayer'] }; // Bun runs local bins natively\n }\n if (userAgent?.startsWith('pnpm')) {\n return { command: 'pnpm', args: ['exec', 'intlayer'] }; // pnpm requires 'exec'\n }\n if (userAgent?.startsWith('yarn')) {\n return { command: 'yarn', args: ['run', 'intlayer'] }; // yarn requires 'run' or 'exec'\n }\n\n // Default fallback\n return { command: 'npx', args: ['intlayer'] };\n};\n\nexport const runCI = async (commands: string[]) => {\n const credentialsEnv = process.env.INTLAYER_PROJECT_CREDENTIALS;\n let credentials: Record<string, { clientId: string; clientSecret: string }> =\n {};\n\n // Parse Credentials (Optional now)\n if (credentialsEnv) {\n try {\n credentials = JSON.parse(credentialsEnv);\n } catch {\n logger(\n 'INTLAYER_PROJECT_CREDENTIALS is not valid JSON. Proceeding without credentials.',\n {\n level: 'warn',\n }\n );\n }\n }\n\n const cwd = process.cwd();\n\n // Discover Projects\n const { projectsPath } = await listProjects();\n\n if (projectsPath.length === 0) {\n logger('No Intlayer projects found.', { level: 'warn' });\n return;\n }\n\n // 3. Determine Context: Single Project vs All Projects\n // Check if the current directory matches one of the discovered project paths\n const currentProject = projectsPath.find((p) => cwd === p);\n const projectsToRun = currentProject ? [currentProject] : projectsPath;\n\n const { command, args: pmArgs } = getPackageManagerCommand();\n const finalArgs = [...pmArgs, ...commands];\n\n logger(`CI: Using package manager: ${command}`, {\n level: 'info',\n isVerbose: true,\n });\n\n if (currentProject) {\n logger(`CI: Detected project context: ${currentProject}`, {\n level: 'info',\n });\n } else {\n logger(\n `CI: No specific project context detected. Iterating over ${projectsToRun.length} discovered projects...`,\n {\n level: 'info',\n }\n );\n }\n\n let hasError = false;\n\n // Iterate and Execute\n for (const projectPath of projectsToRun) {\n // Attempt to match credentials to the project path\n // We check if the key (relative or absolute) matches the resolved project path\n const credsEntry = Object.entries(credentials).find(([key]) => {\n const absKey = resolve(key);\n return absKey === projectPath || projectPath.endsWith(normalize(key));\n });\n\n const creds = credsEntry?.[1];\n\n logger(`\\nCI: Executing for ${projectPath}...`, {\n level: 'info',\n });\n\n const envVars = { ...process.env };\n\n if (creds) {\n envVars.INTLAYER_CLIENT_ID = creds.clientId;\n envVars.INTLAYER_CLIENT_SECRET = creds.clientSecret;\n } else if (credentialsEnv) {\n logger(\n `CI: No matching credentials found for ${projectPath} in INTLAYER_PROJECT_CREDENTIALS.`,\n { isVerbose: true }\n );\n }\n\n const result = spawnSync(command, finalArgs, {\n cwd: projectPath,\n stdio: 'inherit',\n env: envVars,\n });\n\n if (result.status !== 0) {\n logger(`CI: Failed for ${projectPath}`, {\n level: 'error',\n });\n hasError = true;\n }\n }\n\n if (hasError) process.exit(1);\n};\n"],"mappings":";;;;;;;;AAMA,MAAM,iCAAiC;CACrC,MAAM,YAAY,QAAQ,IAAI;AAE9B,KAAI,WAAW,WAAW,MAAM,CAC9B,QAAO;EAAE,SAAS;EAAO,MAAM,CAAC,WAAW;EAAE;AAE/C,KAAI,WAAW,WAAW,OAAO,CAC/B,QAAO;EAAE,SAAS;EAAQ,MAAM,CAAC,QAAQ,WAAW;EAAE;AAExD,KAAI,WAAW,WAAW,OAAO,CAC/B,QAAO;EAAE,SAAS;EAAQ,MAAM,CAAC,OAAO,WAAW;EAAE;AAIvD,QAAO;EAAE,SAAS;EAAO,MAAM,CAAC,WAAW;EAAE;;AAG/C,MAAa,QAAQ,OAAO,aAAuB;CACjD,MAAM,iBAAiB,QAAQ,IAAI;CACnC,IAAI,cACF,EAAE;AAGJ,KAAI,eACF,KAAI;AACF,gBAAc,KAAK,MAAM,eAAe;SAClC;AACN,sCACE,mFACA,EACE,OAAO,QACR,CACF;;CAIL,MAAM,MAAM,QAAQ,KAAK;CAGzB,MAAM,EAAE,iBAAiB,gDAAoB;AAE7C,KAAI,aAAa,WAAW,GAAG;AAC7B,sCAAO,+BAA+B,EAAE,OAAO,QAAQ,CAAC;AACxD;;CAKF,MAAM,iBAAiB,aAAa,MAAM,MAAM,QAAQ,EAAE;CAC1D,MAAM,gBAAgB,iBAAiB,CAAC,eAAe,GAAG;CAE1D,MAAM,EAAE,SAAS,MAAM,WAAW,0BAA0B;CAC5D,MAAM,YAAY,CAAC,GAAG,QAAQ,GAAG,SAAS;AAE1C,qCAAO,8BAA8B,WAAW;EAC9C,OAAO;EACP,WAAW;EACZ,CAAC;AAEF,KAAI,eACF,qCAAO,iCAAiC,kBAAkB,EACxD,OAAO,QACR,CAAC;KAEF,qCACE,4DAA4D,cAAc,OAAO,0BACjF,EACE,OAAO,QACR,CACF;CAGH,IAAI,WAAW;AAGf,MAAK,MAAM,eAAe,eAAe;EAQvC,MAAM,QALa,OAAO,QAAQ,YAAY,CAAC,MAAM,CAAC,SAAS;AAE7D,iCADuB,IACV,KAAK,eAAe,YAAY,kCAAmB,IAAI,CAAC;IAG/C,GAAG;AAE3B,sCAAO,uBAAuB,YAAY,MAAM,EAC9C,OAAO,QACR,CAAC;EAEF,MAAM,UAAU,EAAE,GAAG,QAAQ,KAAK;AAElC,MAAI,OAAO;AACT,WAAQ,qBAAqB,MAAM;AACnC,WAAQ,yBAAyB,MAAM;aAC9B,eACT,qCACE,yCAAyC,YAAY,oCACrD,EAAE,WAAW,MAAM,CACpB;AASH,wCANyB,SAAS,WAAW;GAC3C,KAAK;GACL,OAAO;GACP,KAAK;GACN,CAES,CAAC,WAAW,GAAG;AACvB,uCAAO,kBAAkB,eAAe,EACtC,OAAO,SACR,CAAC;AACF,cAAW;;;AAIf,KAAI,SAAU,SAAQ,KAAK,EAAE"}
|
|
1
|
+
{"version":3,"file":"ci.cjs","names":["sep"],"sources":["../../src/ci.ts"],"sourcesContent":["import { spawnSync } from 'node:child_process';\nimport { resolve, sep } from 'node:path';\nimport { logger } from '@intlayer/config/logger';\nimport {\n detectPackageManager,\n listProjects,\n type PackageManager,\n} from '@intlayer/engine/cli';\n\n/** CMS access keys of a single project. */\ntype ProjectCredentials = {\n clientId: string;\n clientSecret: string;\n};\n\n/**\n * Shape of the `INTLAYER_PROJECT_CREDENTIALS` environment variable: a JSON map\n * of project path (absolute, or relative to the repository root) to its CMS\n * access keys.\n */\ntype CredentialsMap = Record<string, ProjectCredentials>;\n\n/** Command used to run the locally installed `intlayer` binary. */\ntype PackageManagerCommand = {\n command: string;\n args: string[];\n};\n\n/**\n * Detects the command used to run the local `intlayer` binary. Prefers the\n * package manager that launched the current process (`npm_config_user_agent`),\n * and falls back to lock file detection when the CLI was not started through a\n * package manager (e.g. a global install or a bare CI runner).\n */\nexport const getPackageManagerCommand = (\n lockFileSearchDir: string\n): PackageManagerCommand => {\n const userAgent = process.env.npm_config_user_agent;\n\n const commandByPackageManager: Record<PackageManager, PackageManagerCommand> =\n {\n bun: { command: 'bun', args: ['intlayer'] }, // Bun runs local bins natively\n pnpm: { command: 'pnpm', args: ['exec', 'intlayer'] }, // pnpm requires 'exec'\n yarn: { command: 'yarn', args: ['run', 'intlayer'] }, // yarn requires 'run' or 'exec'\n npm: { command: 'npx', args: ['intlayer'] },\n };\n\n const userAgentPackageManager = (\n Object.keys(commandByPackageManager) as PackageManager[]\n ).find((packageManager) => userAgent?.startsWith(packageManager));\n\n if (userAgentPackageManager) {\n return commandByPackageManager[userAgentPackageManager];\n }\n\n // No user agent — infer the package manager from the repository lock file.\n return commandByPackageManager[detectPackageManager(lockFileSearchDir)];\n};\n\n/**\n * Splits a path into segments, accepting both posix and windows separators so\n * credential keys written on any OS compare equal to local project paths.\n */\nconst toPathSegments = (path: string): string[] =>\n path.split(/[\\\\/]+/).filter((segment) => segment !== '' && segment !== '.');\n\n/**\n * Returns true when a credentials key designates the given project directory.\n * A key matches when it is:\n * - the absolute path of the project,\n * - a path relative to `searchDir` (the repository root), or\n * - a trailing sequence of full path segments of the project path (so the key\n * `\"apps/web\"` matches `/repo/apps/web`, but `\"app\"` never matches\n * `/repo/my-app`).\n */\nexport const credentialsKeyMatchesProject = (\n key: string,\n projectPath: string,\n searchDir: string\n): boolean => {\n if (resolve(key) === projectPath) return true;\n if (resolve(searchDir, key) === projectPath) return true;\n\n const keySegments = toPathSegments(key);\n const projectSegments = toPathSegments(projectPath);\n\n if (keySegments.length === 0 || keySegments.length > projectSegments.length) {\n return false;\n }\n\n const trailingProjectSegments = projectSegments.slice(-keySegments.length);\n\n return keySegments.every(\n (segment, index) => trailingProjectSegments[index] === segment\n );\n};\n\n/**\n * Selects the projects the CI command must run in:\n * - run from the repository root → every discovered project (monorepo mode);\n * - run from inside a project directory (or any of its subdirectories) → that\n * project only, the deepest match winning when projects are nested;\n * - run anywhere else → every discovered project.\n */\nexport const selectProjectsToRun = (\n currentWorkingDir: string,\n searchDir: string,\n projectsPath: string[]\n): { projectsToRun: string[]; currentProject: string | undefined } => {\n const cwd = resolve(currentWorkingDir);\n\n if (cwd === resolve(searchDir)) {\n return { projectsToRun: projectsPath, currentProject: undefined };\n }\n\n const currentProject = projectsPath\n .filter(\n (projectPath) => cwd === projectPath || cwd.startsWith(projectPath + sep)\n )\n .sort((a, b) => b.length - a.length)[0];\n\n return {\n projectsToRun: currentProject ? [currentProject] : projectsPath,\n currentProject,\n };\n};\n\n/**\n * Runs an intlayer command in every Intlayer project of the repository (or\n * only in the current one when invoked from inside a project directory),\n * injecting per-project CMS credentials from `INTLAYER_PROJECT_CREDENTIALS`.\n * Exits with code 1 when the command fails in at least one project.\n */\nexport const runCI = async (commands: string[]) => {\n const credentialsEnv = process.env.INTLAYER_PROJECT_CREDENTIALS;\n let credentials: CredentialsMap = {};\n\n // Parse Credentials (Optional now)\n if (credentialsEnv) {\n try {\n credentials = JSON.parse(credentialsEnv);\n } catch {\n logger(\n 'INTLAYER_PROJECT_CREDENTIALS is not valid JSON. Proceeding without credentials.',\n {\n level: 'warn',\n }\n );\n }\n }\n\n // Discover projects from the git root so every project of the repository is\n // found regardless of the directory the command is launched from.\n const { searchDir, projectsPath } = await listProjects({ gitRoot: true });\n const normalizedProjectsPath = projectsPath.map((projectPath) =>\n resolve(projectPath)\n );\n\n if (normalizedProjectsPath.length === 0) {\n logger('No Intlayer projects found.', { level: 'warn' });\n return;\n }\n\n // Determine Context: Single Project vs All Projects\n const { projectsToRun, currentProject } = selectProjectsToRun(\n process.cwd(),\n searchDir,\n normalizedProjectsPath\n );\n\n const { command, args: pmArgs } = getPackageManagerCommand(searchDir);\n const finalArgs = [...pmArgs, ...commands];\n\n logger(`CI: Using package manager: ${command}`, {\n level: 'info',\n isVerbose: true,\n });\n\n if (currentProject) {\n logger(`CI: Detected project context: ${currentProject}`, {\n level: 'info',\n });\n } else {\n logger(\n `CI: No specific project context detected. Iterating over ${projectsToRun.length} discovered projects...`,\n {\n level: 'info',\n }\n );\n }\n\n const failedProjects: string[] = [];\n\n // Iterate and Execute\n for (const projectPath of projectsToRun) {\n // Attempt to match credentials to the project path\n const credsEntry = Object.entries(credentials).find(([key]) =>\n credentialsKeyMatchesProject(key, projectPath, searchDir)\n );\n\n const creds = credsEntry?.[1];\n\n logger(`\\nCI: Executing for ${projectPath}...`, {\n level: 'info',\n });\n\n const envVars = { ...process.env };\n\n if (creds) {\n envVars.INTLAYER_CLIENT_ID = creds.clientId;\n envVars.INTLAYER_CLIENT_SECRET = creds.clientSecret;\n } else if (credentialsEnv) {\n logger(\n `CI: No matching credentials found for ${projectPath} in INTLAYER_PROJECT_CREDENTIALS.`,\n { isVerbose: true }\n );\n }\n\n const result = spawnSync(command, finalArgs, {\n cwd: projectPath,\n stdio: 'inherit',\n env: envVars,\n });\n\n if (result.error) {\n logger(\n `CI: Failed to launch \"${command}\" for ${projectPath}: ${result.error.message}`,\n { level: 'error' }\n );\n failedProjects.push(projectPath);\n continue;\n }\n\n if (result.status !== 0) {\n logger(`CI: Failed for ${projectPath}`, {\n level: 'error',\n });\n failedProjects.push(projectPath);\n }\n }\n\n if (failedProjects.length > 0) {\n logger(\n `\\nCI: ${failedProjects.length}/${projectsToRun.length} project(s) failed:\\n${failedProjects\n .map((projectPath) => ` - ${projectPath}`)\n .join('\\n')}`,\n { level: 'error' }\n );\n process.exit(1);\n }\n};\n"],"mappings":"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"}
|