@intlayer/engine 9.5.9-canary.0 → 9.5.10
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/_virtual/_utils_asset.cjs +1 -1
- package/dist/cjs/build.cjs +4 -4
- package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +2 -2
- package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +3 -3
- package/dist/cjs/buildIntlayerDictionary/writeMergedDictionary.cjs +1 -1
- package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +3 -3
- package/dist/cjs/buildIntlayerDictionary/writeRemoteDictionary.cjs +2 -2
- package/dist/cjs/buildIntlayerDictionary/writeUnmergedDictionary.cjs +2 -2
- package/dist/cjs/cleanOutputDir.cjs +1 -1
- package/dist/cjs/cleanRemovedContentDeclaration.cjs +1 -1
- package/dist/cjs/cli.cjs +10 -3
- package/dist/cjs/createDictionaryEntryPoint/createDictionaryEntryPoint.cjs +1 -1
- package/dist/cjs/createDictionaryEntryPoint/getBuiltDictionariesPath.cjs +2 -2
- package/dist/cjs/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.cjs +2 -2
- package/dist/cjs/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.cjs +2 -2
- package/dist/cjs/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.cjs +2 -2
- package/dist/cjs/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.cjs +2 -2
- package/dist/cjs/createType/createModuleAugmentation.cjs +3 -3
- package/dist/cjs/createType/createType.cjs +1 -1
- package/dist/cjs/docReview/index.cjs +5 -5
- package/dist/cjs/docReview/pipeline.cjs +4 -4
- package/dist/cjs/docReview/reviewReport.cjs.map +1 -1
- package/dist/cjs/fetchDistantDictionaries.cjs +1 -1
- package/dist/cjs/handleContentDeclarationFileChange.cjs +2 -2
- package/dist/cjs/handleUnlinkedContentDeclarationFile.cjs +1 -1
- package/dist/cjs/init/cms.cjs +35 -0
- package/dist/cjs/init/cms.cjs.map +1 -1
- package/dist/cjs/init/documentationRouter.cjs +141 -0
- package/dist/cjs/init/documentationRouter.cjs.map +1 -0
- package/dist/cjs/init/frameworkSetup/backend/index.cjs +138 -0
- package/dist/cjs/init/frameworkSetup/backend/index.cjs.map +1 -0
- package/dist/cjs/init/frameworkSetup/backend/transforms.cjs +223 -0
- package/dist/cjs/init/frameworkSetup/backend/transforms.cjs.map +1 -0
- package/dist/cjs/init/frameworkSetup/index.cjs +9 -3
- package/dist/cjs/init/frameworkSetup/index.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/localeRouting.cjs +13 -0
- package/dist/cjs/init/frameworkSetup/localeRouting.cjs.map +1 -0
- package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs +34 -7
- package/dist/cjs/init/frameworkSetup/nextAppRouter/index.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/restructure.cjs +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs +56 -0
- package/dist/cjs/init/frameworkSetup/nextAppRouter/templates.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/nextAppRouter/transforms.cjs +2 -2
- package/dist/cjs/init/frameworkSetup/nextAppRouter/transforms.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs +32 -3
- package/dist/cjs/init/frameworkSetup/tanstackStart/index.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/restructure.cjs +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs +58 -0
- package/dist/cjs/init/frameworkSetup/tanstackStart/templates.cjs.map +1 -1
- package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +94 -14
- package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
- package/dist/cjs/init/index.cjs +46 -159
- package/dist/cjs/init/index.cjs.map +1 -1
- package/dist/cjs/init/utils/configManipulation.cjs +39 -0
- package/dist/cjs/init/utils/configManipulation.cjs.map +1 -1
- package/dist/cjs/init/utils/fileSystem.cjs +1 -1
- package/dist/cjs/init/utils/githubActions.cjs +1 -1
- package/dist/cjs/init/utils/index.cjs +10 -0
- package/dist/cjs/init/utils/intlayerDependencies.cjs +1 -1
- package/dist/cjs/init/utils/lintConfig.cjs +52 -0
- package/dist/cjs/init/utils/lintConfig.cjs.map +1 -0
- package/dist/cjs/init/utils/packageManager.cjs +63 -14
- package/dist/cjs/init/utils/packageManager.cjs.map +1 -1
- package/dist/cjs/init/utils/urlRoutingFramework.cjs +41 -0
- package/dist/cjs/init/utils/urlRoutingFramework.cjs.map +1 -0
- package/dist/cjs/initConfig/index.cjs +5 -2
- package/dist/cjs/initConfig/index.cjs.map +1 -1
- package/dist/cjs/installLSP.cjs +1 -1
- package/dist/cjs/installMCP/installMCP.cjs +1 -1
- package/dist/cjs/installSkills/index.cjs +1 -1
- package/dist/cjs/listDictionariesPath.cjs +1 -1
- package/dist/cjs/listGitFiles.cjs +1 -1
- package/dist/cjs/loadDictionaries/getIntlayerBundle.cjs +2 -2
- package/dist/cjs/loadDictionaries/index.cjs +1 -1
- package/dist/cjs/loadDictionaries/loadContentDeclaration.cjs +2 -2
- package/dist/cjs/loadDictionaries/loadDictionaries.cjs +1 -1
- package/dist/cjs/loadDictionaries/loadLocalDictionaries.cjs +1 -1
- package/dist/cjs/loadDictionaries/loadMarkdownContentDeclaration.cjs +1 -1
- package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs +104 -43
- package/dist/cjs/loadDictionaries/logTypeScriptErrors.cjs.map +1 -1
- package/dist/cjs/logConfigDetails.cjs +1 -1
- package/dist/cjs/prepareIntlayer.cjs +4 -4
- package/dist/cjs/scan/index.cjs +1 -1
- package/dist/cjs/scan/scanWebsite.cjs +1 -1
- package/dist/cjs/syncPluginKit/createFileAdapter.cjs +1 -1
- package/dist/cjs/syncPluginKit/index.cjs +1 -1
- package/dist/cjs/utils/buildComponentFilesList.cjs +1 -1
- package/dist/cjs/utils/contentWatcherLock.cjs +2 -2
- package/dist/cjs/utils/index.cjs +4 -4
- package/dist/cjs/utils/readDictionariesFromDisk.cjs +1 -1
- package/dist/cjs/utils/runOnce.cjs +1 -1
- package/dist/cjs/utils/runParallel/pidTree.cjs +1 -1
- package/dist/cjs/utils/withFileLock.cjs +1 -1
- package/dist/cjs/watcher.cjs +6 -6
- package/dist/cjs/writeConfiguration/index.cjs +1 -1
- package/dist/cjs/writeContentDeclaration/processContentDeclarationContent.cjs +2 -2
- package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +1 -1
- package/dist/cjs/writeContentDeclaration/writeContentDeclaration.cjs +4 -4
- package/dist/cjs/writeContentDeclaration/writeJSFile.cjs +3 -3
- package/dist/cjs/writeContentDeclaration/writeMarkdownFile.cjs +1 -1
- package/dist/cjs/writeContentDeclaration/writeYamlFile.cjs +1 -1
- package/dist/cjs/writeFileIfChanged.cjs +1 -1
- package/dist/esm/_virtual/_utils_asset.mjs +1 -1
- package/dist/esm/build.mjs +4 -4
- package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +2 -2
- package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +3 -3
- package/dist/esm/buildIntlayerDictionary/writeMergedDictionary.mjs +1 -1
- package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +3 -3
- package/dist/esm/buildIntlayerDictionary/writeRemoteDictionary.mjs +2 -2
- package/dist/esm/buildIntlayerDictionary/writeUnmergedDictionary.mjs +2 -2
- package/dist/esm/cleanOutputDir.mjs +1 -1
- package/dist/esm/cleanRemovedContentDeclaration.mjs +1 -1
- package/dist/esm/cli.mjs +8 -6
- package/dist/esm/createDictionaryEntryPoint/createDictionaryEntryPoint.mjs +1 -1
- package/dist/esm/createDictionaryEntryPoint/getBuiltDictionariesPath.mjs +2 -2
- package/dist/esm/createDictionaryEntryPoint/getBuiltDynamicDictionariesPath.mjs +2 -2
- package/dist/esm/createDictionaryEntryPoint/getBuiltFetchDictionariesPath.mjs +2 -2
- package/dist/esm/createDictionaryEntryPoint/getBuiltRemoteDictionariesPath.mjs +2 -2
- package/dist/esm/createDictionaryEntryPoint/getBuiltUnmergedDictionariesPath.mjs +2 -2
- package/dist/esm/createType/createModuleAugmentation.mjs +3 -3
- package/dist/esm/createType/createType.mjs +1 -1
- package/dist/esm/docReview/index.mjs +5 -5
- package/dist/esm/docReview/pipeline.mjs +4 -4
- package/dist/esm/docReview/reviewReport.mjs.map +1 -1
- package/dist/esm/fetchDistantDictionaries.mjs +1 -1
- package/dist/esm/handleContentDeclarationFileChange.mjs +2 -2
- package/dist/esm/handleUnlinkedContentDeclarationFile.mjs +1 -1
- package/dist/esm/init/cms.mjs +35 -2
- package/dist/esm/init/cms.mjs.map +1 -1
- package/dist/esm/init/documentationRouter.mjs +139 -0
- package/dist/esm/init/documentationRouter.mjs.map +1 -0
- package/dist/esm/init/frameworkSetup/backend/index.mjs +130 -0
- package/dist/esm/init/frameworkSetup/backend/index.mjs.map +1 -0
- package/dist/esm/init/frameworkSetup/backend/transforms.mjs +216 -0
- package/dist/esm/init/frameworkSetup/backend/transforms.mjs.map +1 -0
- package/dist/esm/init/frameworkSetup/index.mjs +9 -3
- package/dist/esm/init/frameworkSetup/index.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/localeRouting.mjs +12 -0
- package/dist/esm/init/frameworkSetup/localeRouting.mjs.map +1 -0
- package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs +36 -9
- package/dist/esm/init/frameworkSetup/nextAppRouter/index.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/restructure.mjs +1 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/templates.mjs +54 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/templates.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/nextAppRouter/transforms.mjs +2 -2
- package/dist/esm/init/frameworkSetup/nextAppRouter/transforms.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs +35 -6
- package/dist/esm/init/frameworkSetup/tanstackStart/index.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/restructure.mjs +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs +56 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/templates.mjs.map +1 -1
- package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +94 -15
- package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
- package/dist/esm/init/index.mjs +42 -158
- package/dist/esm/init/index.mjs.map +1 -1
- package/dist/esm/init/utils/configManipulation.mjs +38 -1
- package/dist/esm/init/utils/configManipulation.mjs.map +1 -1
- package/dist/esm/init/utils/fileSystem.mjs +1 -1
- package/dist/esm/init/utils/githubActions.mjs +1 -1
- package/dist/esm/init/utils/index.mjs +5 -3
- package/dist/esm/init/utils/intlayerDependencies.mjs +1 -1
- package/dist/esm/init/utils/lintConfig.mjs +50 -0
- package/dist/esm/init/utils/lintConfig.mjs.map +1 -0
- package/dist/esm/init/utils/packageManager.mjs +61 -15
- package/dist/esm/init/utils/packageManager.mjs.map +1 -1
- package/dist/esm/init/utils/urlRoutingFramework.mjs +40 -0
- package/dist/esm/init/utils/urlRoutingFramework.mjs.map +1 -0
- package/dist/esm/initConfig/index.mjs +5 -2
- package/dist/esm/initConfig/index.mjs.map +1 -1
- package/dist/esm/installLSP.mjs +1 -1
- package/dist/esm/installMCP/installMCP.mjs +1 -1
- package/dist/esm/installSkills/index.mjs +1 -1
- package/dist/esm/listDictionariesPath.mjs +1 -1
- package/dist/esm/listGitFiles.mjs +1 -1
- package/dist/esm/loadDictionaries/getIntlayerBundle.mjs +2 -2
- package/dist/esm/loadDictionaries/index.mjs +1 -1
- package/dist/esm/loadDictionaries/loadContentDeclaration.mjs +2 -2
- package/dist/esm/loadDictionaries/loadDictionaries.mjs +1 -1
- package/dist/esm/loadDictionaries/loadLocalDictionaries.mjs +1 -1
- package/dist/esm/loadDictionaries/loadMarkdownContentDeclaration.mjs +1 -1
- package/dist/esm/loadDictionaries/logTypeScriptErrors.mjs +105 -44
- package/dist/esm/loadDictionaries/logTypeScriptErrors.mjs.map +1 -1
- package/dist/esm/logConfigDetails.mjs +1 -1
- package/dist/esm/prepareIntlayer.mjs +4 -4
- package/dist/esm/scan/index.mjs +1 -1
- package/dist/esm/scan/scanWebsite.mjs +1 -1
- package/dist/esm/syncPluginKit/createFileAdapter.mjs +1 -1
- package/dist/esm/syncPluginKit/index.mjs +1 -1
- package/dist/esm/utils/buildComponentFilesList.mjs +1 -1
- package/dist/esm/utils/contentWatcherLock.mjs +2 -2
- package/dist/esm/utils/index.mjs +4 -4
- package/dist/esm/utils/readDictionariesFromDisk.mjs +1 -1
- package/dist/esm/utils/runOnce.mjs +1 -1
- package/dist/esm/utils/runParallel/pidTree.mjs +1 -1
- package/dist/esm/utils/withFileLock.mjs +1 -1
- package/dist/esm/watcher.mjs +6 -6
- package/dist/esm/writeConfiguration/index.mjs +1 -1
- package/dist/esm/writeContentDeclaration/processContentDeclarationContent.mjs +2 -2
- package/dist/esm/writeContentDeclaration/transformJSFile.mjs +1 -1
- package/dist/esm/writeContentDeclaration/writeContentDeclaration.mjs +4 -4
- package/dist/esm/writeContentDeclaration/writeJSFile.mjs +3 -3
- package/dist/esm/writeContentDeclaration/writeMarkdownFile.mjs +1 -1
- package/dist/esm/writeContentDeclaration/writeYamlFile.mjs +1 -1
- package/dist/esm/writeFileIfChanged.mjs +1 -1
- package/dist/types/cli.d.ts +5 -3
- package/dist/types/docReview/reviewReport.d.ts.map +1 -1
- package/dist/types/formatDictionary.d.ts +2 -2
- package/dist/types/init/cms.d.ts +11 -0
- package/dist/types/init/cms.d.ts.map +1 -1
- package/dist/types/init/documentationRouter.d.ts +64 -0
- package/dist/types/init/documentationRouter.d.ts.map +1 -0
- package/dist/types/init/frameworkSetup/backend/index.d.ts +16 -0
- package/dist/types/init/frameworkSetup/backend/index.d.ts.map +1 -0
- package/dist/types/init/frameworkSetup/backend/transforms.d.ts +37 -0
- package/dist/types/init/frameworkSetup/backend/transforms.d.ts.map +1 -0
- package/dist/types/init/frameworkSetup/index.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/localeRouting.d.ts +11 -0
- package/dist/types/init/frameworkSetup/localeRouting.d.ts.map +1 -0
- package/dist/types/init/frameworkSetup/nextAppRouter/index.d.ts +5 -5
- package/dist/types/init/frameworkSetup/nextAppRouter/index.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/nextAppRouter/templates.d.ts +12 -0
- package/dist/types/init/frameworkSetup/nextAppRouter/templates.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/nextAppRouter/transforms.d.ts +10 -1
- package/dist/types/init/frameworkSetup/nextAppRouter/transforms.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/tanstackStart/index.d.ts +3 -2
- package/dist/types/init/frameworkSetup/tanstackStart/index.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts +10 -0
- package/dist/types/init/frameworkSetup/tanstackStart/templates.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts +12 -0
- package/dist/types/init/frameworkSetup/tanstackStart/transforms.d.ts.map +1 -1
- package/dist/types/init/frameworkSetup/types.d.ts +6 -0
- package/dist/types/init/frameworkSetup/types.d.ts.map +1 -1
- package/dist/types/init/index.d.ts +15 -1
- package/dist/types/init/index.d.ts.map +1 -1
- package/dist/types/init/utils/configManipulation.d.ts +14 -0
- package/dist/types/init/utils/configManipulation.d.ts.map +1 -1
- package/dist/types/init/utils/index.d.ts +5 -3
- package/dist/types/init/utils/lintConfig.d.ts +28 -0
- package/dist/types/init/utils/lintConfig.d.ts.map +1 -0
- package/dist/types/init/utils/packageManager.d.ts +29 -6
- package/dist/types/init/utils/packageManager.d.ts.map +1 -1
- package/dist/types/init/utils/urlRoutingFramework.d.ts +9 -0
- package/dist/types/init/utils/urlRoutingFramework.d.ts.map +1 -0
- package/dist/types/initConfig/index.d.ts +3 -1
- package/dist/types/initConfig/index.d.ts.map +1 -1
- package/dist/types/loadDictionaries/logTypeScriptErrors.d.ts +4 -0
- package/dist/types/loadDictionaries/logTypeScriptErrors.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
|
|
2
1
|
import { getPathHash } from "../utils/getPathHash.mjs";
|
|
3
|
-
import {
|
|
2
|
+
import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
|
|
4
3
|
import { basename, extname, join, relative } from "node:path";
|
|
5
4
|
import { kebabCaseToCamelCase, normalizePath } from "@intlayer/config/utils";
|
|
6
|
-
import { getDomainOrigin, getRewriteRules, isLocaleExclusiveOnDomain } from "@intlayer/core/localization";
|
|
7
5
|
import fg from "fast-glob";
|
|
6
|
+
import { mkdir } from "node:fs/promises";
|
|
7
|
+
import { getDomainOrigin, getRewriteRules, isLocaleExclusiveOnDomain } from "@intlayer/core/localization";
|
|
8
8
|
|
|
9
9
|
//#region src/createType/createModuleAugmentation.ts
|
|
10
10
|
const getTypeName = (key) => `${kebabCaseToCamelCase(key)}Content`;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parallelize } from "../utils/parallelize.mjs";
|
|
2
2
|
import { writeFileIfChanged } from "../writeFileIfChanged.mjs";
|
|
3
|
-
import { mkdir } from "node:fs/promises";
|
|
4
3
|
import { resolve } from "node:path";
|
|
4
|
+
import { mkdir } from "node:fs/promises";
|
|
5
5
|
|
|
6
6
|
//#region src/createType/createType.ts
|
|
7
7
|
const generateTypeScriptType = (dictionary) => {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { normalizeBlock } from "./normalizeBlock.mjs";
|
|
2
|
+
import { fingerprintBlock } from "./fingerprintBlock.mjs";
|
|
3
|
+
import { segmentDocument } from "./segmentDocument.mjs";
|
|
4
|
+
import { planAlignmentActions } from "./planActions.mjs";
|
|
2
5
|
import { computeJaccardSimilarity, generateCharacterShingles } from "./computeSimilarity.mjs";
|
|
3
6
|
import { alignBaseAndTargetBlocks } from "./alignBlocks.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { normalizeBlock } from "./normalizeBlock.mjs";
|
|
7
|
+
import { mapChangedLinesToBlocks } from "./mapChangedLinesToBlocks.mjs";
|
|
6
8
|
import { identifySegmentsToReview, mergeReviewedSegments } from "./rebuildDocument.mjs";
|
|
7
|
-
import { segmentDocument } from "./segmentDocument.mjs";
|
|
8
9
|
import { buildAlignmentPlan } from "./pipeline.mjs";
|
|
9
|
-
import { planAlignmentActions } from "./planActions.mjs";
|
|
10
10
|
import { buildReviewReport, formatReviewReport } from "./reviewReport.mjs";
|
|
11
11
|
|
|
12
12
|
export { alignBaseAndTargetBlocks, buildAlignmentPlan, buildReviewReport, computeJaccardSimilarity, fingerprintBlock, formatReviewReport, generateCharacterShingles, identifySegmentsToReview, mapChangedLinesToBlocks, mergeReviewedSegments, normalizeBlock, planAlignmentActions, segmentDocument };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { mapChangedLinesToBlocks } from "./mapChangedLinesToBlocks.mjs";
|
|
2
|
-
import { alignBaseAndTargetBlocks } from "./alignBlocks.mjs";
|
|
3
|
-
import { fingerprintBlock } from "./fingerprintBlock.mjs";
|
|
4
1
|
import { normalizeBlock } from "./normalizeBlock.mjs";
|
|
5
|
-
import {
|
|
2
|
+
import { fingerprintBlock } from "./fingerprintBlock.mjs";
|
|
6
3
|
import { segmentDocument, segmentSections } from "./segmentDocument.mjs";
|
|
4
|
+
import { alignBaseAndTargetBlocks } from "./alignBlocks.mjs";
|
|
5
|
+
import { mapChangedLinesToBlocks } from "./mapChangedLinesToBlocks.mjs";
|
|
6
|
+
import { identifySegmentsToReview, mergeReviewedSegments } from "./rebuildDocument.mjs";
|
|
7
7
|
|
|
8
8
|
//#region src/docReview/pipeline.ts
|
|
9
9
|
/** Fingerprint a list of already-segmented blocks (context = neighbours). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reviewReport.mjs","names":[],"sources":["../../../src/docReview/reviewReport.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizeNumber } from '@intlayer/config/logger';\nimport { buildAlignmentPlan } from './pipeline';\n\n/**\n * The kind of change detected for a block when reviewing a translation against\n * its base document.\n *\n * - `review`: the base block changed and its translation must be updated.\n * - `insert_new`: the base block has no translation yet and must be added.\n * - `delete`: the target block no longer exists in the base and should be removed.\n */\nexport type ReviewBlockAction = 'review' | 'insert_new' | 'delete';\n\n/** A 1-based, inclusive line range within a document. */\nexport type LineRange = {\n start: number;\n end: number;\n};\n\n/**\n * A single block that diverges between the base document and its translation.\n *\n * This is the unit an external translator (AI client, human, or agent) needs to\n * act on: it carries the base content to translate, the existing translation to\n * update, and where each lives so the change can be located in the file.\n */\nexport type ReviewReportBlock = {\n /** What should happen to this block. */\n action: ReviewBlockAction;\n /** Line range of the block in the base document (omitted for pure deletions). */\n baseLineRange?: LineRange;\n /** Line range of the block in the target document (omitted for new insertions). */\n targetLineRange?: LineRange;\n /** Raw markdown of the base block (omitted for pure deletions). */\n baseContent?: string;\n /** Existing translation of the block (omitted for new insertions). */\n targetContent?: string;\n};\n\nexport type ReviewReportSummary = {\n /** Number of blocks reused as-is (unchanged translation). */\n reuse: number;\n /** Number of blocks whose translation must be updated. */\n review: number;\n /** Number of blocks missing a translation. */\n insertNew: number;\n /** Number of stale target blocks to delete. */\n delete: number;\n};\n\nexport type ReviewReport = {\n /** Only the blocks that diverge (review, insert_new, delete). */\n blocks: ReviewReportBlock[];\n /** Counts per action over the whole document, including reused blocks. */\n summary: ReviewReportSummary;\n};\n\nexport type BuildReviewReportInput = {\n /** The base (source) document, used as the translation reference. */\n baseText: string;\n /** The existing target (translated) document, possibly empty. */\n targetText: string;\n /**\n * 1-based line numbers that changed in the base document.\n *\n * When omitted the whole document is compared, and only inserted and deleted\n * blocks are reported (no aligned block is flagged for review since there is\n * no way to know which ones changed). An empty array means nothing changed,\n * and no block at all is reported.\n */\n changedLines?: number[];\n};\n\n/**\n * Compare a base markdown document with its translation and report only the\n * blocks that need attention, with their line ranges and content.\n *\n * Reusable across the CLI (`doc review --log`), the backend (comparing two\n * translation contents stored in database), and agents that generate the\n * missing translations.\n *\n * @param input - The base/target texts and optional changed lines.\n * @returns The divergent blocks and a per-action summary.\n */\nexport const buildReviewReport = ({\n baseText,\n targetText,\n changedLines,\n}: BuildReviewReportInput): ReviewReport => {\n const { baseBlocks, targetBlocks, plan } = buildAlignmentPlan({\n baseText,\n targetText,\n changedLines,\n });\n\n const summary: ReviewReportSummary = {\n reuse: 0,\n review: 0,\n insertNew: 0,\n delete: 0,\n };\n\n const blocks: ReviewReportBlock[] = [];\n\n for (const [actionIndex, action] of plan.actions.entries()) {\n if (action.kind === 'reuse') {\n summary.reuse += 1;\n continue;\n }\n\n if (action.kind === 'review') {\n summary.review += 1;\n const baseBlock = baseBlocks[action.baseIndex];\n\n if (!baseBlock) continue;\n\n const targetBlock =\n action.targetIndex !== null ? targetBlocks[action.targetIndex] : null;\n\n blocks.push({\n action: 'review',\n baseLineRange: { start: baseBlock.lineStart, end: baseBlock.lineEnd },\n targetLineRange: targetBlock\n ? { start: targetBlock.lineStart, end: targetBlock.lineEnd }\n : undefined,\n baseContent: baseBlock.content,\n targetContent: targetBlock?.content,\n });\n continue;\n }\n\n if (action.kind === 'insert_new') {\n summary.insertNew += 1;\n const baseBlock = baseBlocks[action.baseIndex];\n\n if (!baseBlock) continue;\n\n // Find the target line after which the new block should be inserted:\n // scan backwards for the last action that produced a target block.\n let insertAfterLine: number | undefined;\n for (let prevIndex = actionIndex - 1; prevIndex >= 0; prevIndex--) {\n const prevAction = plan.actions[prevIndex];\n if (!prevAction) continue;\n\n let targetIdx: number | null = null;\n if (prevAction.kind === 'reuse') targetIdx = prevAction.targetIndex;\n else if (\n prevAction.kind === 'review' &&\n prevAction.targetIndex !== null\n )\n targetIdx = prevAction.targetIndex;\n else if (prevAction.kind === 'delete')\n targetIdx = prevAction.targetIndex;\n\n if (targetIdx !== null) {\n const prevTargetBlock = targetBlocks[targetIdx];\n if (prevTargetBlock) {\n insertAfterLine = prevTargetBlock.lineEnd + 1;\n break;\n }\n }\n }\n\n blocks.push({\n action: 'insert_new',\n baseLineRange: { start: baseBlock.lineStart, end: baseBlock.lineEnd },\n targetLineRange:\n insertAfterLine !== undefined\n ? { start: insertAfterLine, end: insertAfterLine }\n : undefined,\n baseContent: baseBlock.content,\n });\n continue;\n }\n\n if (action.kind === 'delete') {\n summary.delete += 1;\n const targetBlock = targetBlocks[action.targetIndex];\n\n if (!targetBlock) continue;\n\n blocks.push({\n action: 'delete',\n targetLineRange: {\n start: targetBlock.lineStart,\n end: targetBlock.lineEnd,\n },\n targetContent: targetBlock.content,\n });\n }\n }\n\n return { blocks, summary };\n};\n\n/** Render a line range as a blue colored string, or an orange dash when absent. */\nconst colorizeLineRange = (range?: LineRange): string => {\n if (!range) return colorize('—', ANSIColors.ORANGE);\n const rangeStr =\n range.start === range.end\n ? `L${range.start}`\n : `L${range.start}-${range.end}`;\n return colorize(rangeStr, ANSIColors.BLUE);\n};\n\n/**\n * Colorize a count with green when zero (nothing to do) and a caller-supplied\n * non-zero color (orange for warnings, red for destructive actions).\n */\nconst colorizeCount = (\n count: number,\n nonZeroColor: (typeof ANSIColors)[keyof typeof ANSIColors]\n): string =>\n colorizeNumber(count, {\n zero: ANSIColors.GREEN,\n one: nonZeroColor,\n two: nonZeroColor,\n few: nonZeroColor,\n many: nonZeroColor,\n other: nonZeroColor,\n });\n\n/**\n * Render a {@link ReviewReport} as a human and agent readable log.\n *\n * Each divergent block is printed with its action, the base/target line ranges,\n * the base content to translate, and the existing translation to update.\n *\n * @param report - The report to format.\n * @param options - Optional labels for the base and target locales.\n * @returns A multi-line string describing every block that needs attention.\n */\nexport const formatReviewReport = (\n report: ReviewReport,\n options?: { baseLabel?: string; targetLabel?: string }\n): string => {\n const baseLabel = options?.baseLabel ?? 'base';\n const targetLabel = options?.targetLabel ?? 'target';\n\n const { summary, blocks } = report;\n\n // Build the summary header piece-by-piece so each count uses its own color.\n const header = [\n colorize('Review report: ', ANSIColors.ORANGE),\n colorizeCount(blocks.length, ANSIColors.ORANGE),\n colorize(' block(s) need attention (review=', ANSIColors.ORANGE),\n colorizeCount(summary.review, ANSIColors.ORANGE),\n colorize(', new=', ANSIColors.ORANGE),\n colorizeCount(summary.insertNew, ANSIColors.ORANGE),\n colorize(', delete=', ANSIColors.ORANGE),\n colorizeCount(summary.delete, ANSIColors.RED),\n colorize(', reuse=', ANSIColors.ORANGE),\n colorizeNumber(summary.reuse),\n colorize(').', ANSIColors.ORANGE),\n ].join('');\n\n if (blocks.length === 0) {\n return `${header}\\n${colorize('No changes needed.', ANSIColors.GREEN)}`;\n }\n\n const sections = blocks.map((block, index) => {\n const lines: string[] = [];\n\n // Block header: each token colored individually.\n const blockHeader = [\n colorize('--- Block ', ANSIColors.ORANGE),\n colorizeNumber(index + 1),\n colorize('/', ANSIColors.ORANGE),\n colorizeNumber(blocks.length),\n colorize(` [${block.action}] `, ANSIColors.ORANGE),\n baseLabel,\n colorize(' ', ANSIColors.ORANGE),\n colorizeLineRange(block.baseLineRange),\n colorize(' → ', ANSIColors.ORANGE),\n targetLabel,\n colorize(' ', ANSIColors.ORANGE),\n colorizeLineRange(block.targetLineRange),\n colorize(' ---', ANSIColors.ORANGE),\n ].join('');\n\n lines.push(blockHeader);\n\n if (block.baseContent !== undefined) {\n lines.push(colorize(`[${baseLabel}]`, ANSIColors.BEIGE));\n lines.push(colorize(block.baseContent.trimEnd(), ANSIColors.GREY));\n }\n\n if (block.targetContent !== undefined) {\n lines.push(colorize(`[${targetLabel}]`, ANSIColors.BEIGE));\n lines.push(colorize(block.targetContent.trimEnd(), ANSIColors.GREY));\n } else if (block.action === 'insert_new') {\n lines.push(colorize(`[${targetLabel}]`, ANSIColors.BEIGE));\n lines.push(colorize('(missing — to be translated)', ANSIColors.ORANGE));\n }\n\n return lines.join('\\n');\n });\n\n const editingNote = colorize(\n 'Tip: start editing from the last block — working bottom-up keeps earlier line numbers accurate.',\n ANSIColors.GREY\n );\n\n return [header, '', ...sections, '', editingNote].join('\\n');\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reviewReport.mjs","names":[],"sources":["../../../src/docReview/reviewReport.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport {\n type ANSIColorsType,\n colorize,\n colorizeNumber,\n} from '@intlayer/config/logger';\nimport { buildAlignmentPlan } from './pipeline';\n\n/**\n * The kind of change detected for a block when reviewing a translation against\n * its base document.\n *\n * - `review`: the base block changed and its translation must be updated.\n * - `insert_new`: the base block has no translation yet and must be added.\n * - `delete`: the target block no longer exists in the base and should be removed.\n */\nexport type ReviewBlockAction = 'review' | 'insert_new' | 'delete';\n\n/** A 1-based, inclusive line range within a document. */\nexport type LineRange = {\n start: number;\n end: number;\n};\n\n/**\n * A single block that diverges between the base document and its translation.\n *\n * This is the unit an external translator (AI client, human, or agent) needs to\n * act on: it carries the base content to translate, the existing translation to\n * update, and where each lives so the change can be located in the file.\n */\nexport type ReviewReportBlock = {\n /** What should happen to this block. */\n action: ReviewBlockAction;\n /** Line range of the block in the base document (omitted for pure deletions). */\n baseLineRange?: LineRange;\n /** Line range of the block in the target document (omitted for new insertions). */\n targetLineRange?: LineRange;\n /** Raw markdown of the base block (omitted for pure deletions). */\n baseContent?: string;\n /** Existing translation of the block (omitted for new insertions). */\n targetContent?: string;\n};\n\nexport type ReviewReportSummary = {\n /** Number of blocks reused as-is (unchanged translation). */\n reuse: number;\n /** Number of blocks whose translation must be updated. */\n review: number;\n /** Number of blocks missing a translation. */\n insertNew: number;\n /** Number of stale target blocks to delete. */\n delete: number;\n};\n\nexport type ReviewReport = {\n /** Only the blocks that diverge (review, insert_new, delete). */\n blocks: ReviewReportBlock[];\n /** Counts per action over the whole document, including reused blocks. */\n summary: ReviewReportSummary;\n};\n\nexport type BuildReviewReportInput = {\n /** The base (source) document, used as the translation reference. */\n baseText: string;\n /** The existing target (translated) document, possibly empty. */\n targetText: string;\n /**\n * 1-based line numbers that changed in the base document.\n *\n * When omitted the whole document is compared, and only inserted and deleted\n * blocks are reported (no aligned block is flagged for review since there is\n * no way to know which ones changed). An empty array means nothing changed,\n * and no block at all is reported.\n */\n changedLines?: number[];\n};\n\n/**\n * Compare a base markdown document with its translation and report only the\n * blocks that need attention, with their line ranges and content.\n *\n * Reusable across the CLI (`doc review --log`), the backend (comparing two\n * translation contents stored in database), and agents that generate the\n * missing translations.\n *\n * @param input - The base/target texts and optional changed lines.\n * @returns The divergent blocks and a per-action summary.\n */\nexport const buildReviewReport = ({\n baseText,\n targetText,\n changedLines,\n}: BuildReviewReportInput): ReviewReport => {\n const { baseBlocks, targetBlocks, plan } = buildAlignmentPlan({\n baseText,\n targetText,\n changedLines,\n });\n\n const summary: ReviewReportSummary = {\n reuse: 0,\n review: 0,\n insertNew: 0,\n delete: 0,\n };\n\n const blocks: ReviewReportBlock[] = [];\n\n for (const [actionIndex, action] of plan.actions.entries()) {\n if (action.kind === 'reuse') {\n summary.reuse += 1;\n continue;\n }\n\n if (action.kind === 'review') {\n summary.review += 1;\n const baseBlock = baseBlocks[action.baseIndex];\n\n if (!baseBlock) continue;\n\n const targetBlock =\n action.targetIndex !== null ? targetBlocks[action.targetIndex] : null;\n\n blocks.push({\n action: 'review',\n baseLineRange: { start: baseBlock.lineStart, end: baseBlock.lineEnd },\n targetLineRange: targetBlock\n ? { start: targetBlock.lineStart, end: targetBlock.lineEnd }\n : undefined,\n baseContent: baseBlock.content,\n targetContent: targetBlock?.content,\n });\n continue;\n }\n\n if (action.kind === 'insert_new') {\n summary.insertNew += 1;\n const baseBlock = baseBlocks[action.baseIndex];\n\n if (!baseBlock) continue;\n\n // Find the target line after which the new block should be inserted:\n // scan backwards for the last action that produced a target block.\n let insertAfterLine: number | undefined;\n for (let prevIndex = actionIndex - 1; prevIndex >= 0; prevIndex--) {\n const prevAction = plan.actions[prevIndex];\n if (!prevAction) continue;\n\n let targetIdx: number | null = null;\n if (prevAction.kind === 'reuse') targetIdx = prevAction.targetIndex;\n else if (\n prevAction.kind === 'review' &&\n prevAction.targetIndex !== null\n )\n targetIdx = prevAction.targetIndex;\n else if (prevAction.kind === 'delete')\n targetIdx = prevAction.targetIndex;\n\n if (targetIdx !== null) {\n const prevTargetBlock = targetBlocks[targetIdx];\n if (prevTargetBlock) {\n insertAfterLine = prevTargetBlock.lineEnd + 1;\n break;\n }\n }\n }\n\n blocks.push({\n action: 'insert_new',\n baseLineRange: { start: baseBlock.lineStart, end: baseBlock.lineEnd },\n targetLineRange:\n insertAfterLine !== undefined\n ? { start: insertAfterLine, end: insertAfterLine }\n : undefined,\n baseContent: baseBlock.content,\n });\n continue;\n }\n\n if (action.kind === 'delete') {\n summary.delete += 1;\n const targetBlock = targetBlocks[action.targetIndex];\n\n if (!targetBlock) continue;\n\n blocks.push({\n action: 'delete',\n targetLineRange: {\n start: targetBlock.lineStart,\n end: targetBlock.lineEnd,\n },\n targetContent: targetBlock.content,\n });\n }\n }\n\n return { blocks, summary };\n};\n\n/** Render a line range as a blue colored string, or an orange dash when absent. */\nconst colorizeLineRange = (range?: LineRange): string => {\n if (!range) return colorize('—', ANSIColors.ORANGE);\n const rangeStr =\n range.start === range.end\n ? `L${range.start}`\n : `L${range.start}-${range.end}`;\n return colorize(rangeStr, ANSIColors.BLUE);\n};\n\n/**\n * Colorize a count with green when zero (nothing to do) and a caller-supplied\n * non-zero color (orange for warnings, red for destructive actions).\n */\nconst colorizeCount = (count: number, nonZeroColor: ANSIColorsType): string =>\n colorizeNumber(count, {\n zero: ANSIColors.GREEN,\n one: nonZeroColor,\n two: nonZeroColor,\n few: nonZeroColor,\n many: nonZeroColor,\n other: nonZeroColor,\n });\n\n/**\n * Render a {@link ReviewReport} as a human and agent readable log.\n *\n * Each divergent block is printed with its action, the base/target line ranges,\n * the base content to translate, and the existing translation to update.\n *\n * @param report - The report to format.\n * @param options - Optional labels for the base and target locales.\n * @returns A multi-line string describing every block that needs attention.\n */\nexport const formatReviewReport = (\n report: ReviewReport,\n options?: { baseLabel?: string; targetLabel?: string }\n): string => {\n const baseLabel = options?.baseLabel ?? 'base';\n const targetLabel = options?.targetLabel ?? 'target';\n\n const { summary, blocks } = report;\n\n // Build the summary header piece-by-piece so each count uses its own color.\n const header = [\n colorize('Review report: ', ANSIColors.ORANGE),\n colorizeCount(blocks.length, ANSIColors.ORANGE),\n colorize(' block(s) need attention (review=', ANSIColors.ORANGE),\n colorizeCount(summary.review, ANSIColors.ORANGE),\n colorize(', new=', ANSIColors.ORANGE),\n colorizeCount(summary.insertNew, ANSIColors.ORANGE),\n colorize(', delete=', ANSIColors.ORANGE),\n colorizeCount(summary.delete, ANSIColors.RED),\n colorize(', reuse=', ANSIColors.ORANGE),\n colorizeNumber(summary.reuse),\n colorize(').', ANSIColors.ORANGE),\n ].join('');\n\n if (blocks.length === 0) {\n return `${header}\\n${colorize('No changes needed.', ANSIColors.GREEN)}`;\n }\n\n const sections = blocks.map((block, index) => {\n const lines: string[] = [];\n\n // Block header: each token colored individually.\n const blockHeader = [\n colorize('--- Block ', ANSIColors.ORANGE),\n colorizeNumber(index + 1),\n colorize('/', ANSIColors.ORANGE),\n colorizeNumber(blocks.length),\n colorize(` [${block.action}] `, ANSIColors.ORANGE),\n baseLabel,\n colorize(' ', ANSIColors.ORANGE),\n colorizeLineRange(block.baseLineRange),\n colorize(' → ', ANSIColors.ORANGE),\n targetLabel,\n colorize(' ', ANSIColors.ORANGE),\n colorizeLineRange(block.targetLineRange),\n colorize(' ---', ANSIColors.ORANGE),\n ].join('');\n\n lines.push(blockHeader);\n\n if (block.baseContent !== undefined) {\n lines.push(colorize(`[${baseLabel}]`, ANSIColors.BEIGE));\n lines.push(colorize(block.baseContent.trimEnd(), ANSIColors.GREY));\n }\n\n if (block.targetContent !== undefined) {\n lines.push(colorize(`[${targetLabel}]`, ANSIColors.BEIGE));\n lines.push(colorize(block.targetContent.trimEnd(), ANSIColors.GREY));\n } else if (block.action === 'insert_new') {\n lines.push(colorize(`[${targetLabel}]`, ANSIColors.BEIGE));\n lines.push(colorize('(missing — to be translated)', ANSIColors.ORANGE));\n }\n\n return lines.join('\\n');\n });\n\n const editingNote = colorize(\n 'Tip: start editing from the last block — working bottom-up keeps earlier line numbers accurate.',\n ANSIColors.GREY\n );\n\n return [header, '', ...sections, '', editingNote].join('\\n');\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAyFA,MAAa,qBAAqB,EAChC,UACA,YACA,mBAC0C;CAC1C,MAAM,EAAE,YAAY,cAAc,SAAS,mBAAmB;EAC5D;EACA;EACA;CACF,CAAC;CAED,MAAM,UAA+B;EACnC,OAAO;EACP,QAAQ;EACR,WAAW;EACX,QAAQ;CACV;CAEA,MAAM,SAA8B,CAAC;CAErC,KAAK,MAAM,CAAC,aAAa,WAAW,KAAK,QAAQ,QAAQ,GAAG;EAC1D,IAAI,OAAO,SAAS,SAAS;GAC3B,QAAQ,SAAS;GACjB;EACF;EAEA,IAAI,OAAO,SAAS,UAAU;GAC5B,QAAQ,UAAU;GAClB,MAAM,YAAY,WAAW,OAAO;GAEpC,IAAI,CAAC,WAAW;GAEhB,MAAM,cACJ,OAAO,gBAAgB,OAAO,aAAa,OAAO,eAAe;GAEnE,OAAO,KAAK;IACV,QAAQ;IACR,eAAe;KAAE,OAAO,UAAU;KAAW,KAAK,UAAU;IAAQ;IACpE,iBAAiB,cACb;KAAE,OAAO,YAAY;KAAW,KAAK,YAAY;IAAQ,IACzD;IACJ,aAAa,UAAU;IACvB,eAAe,aAAa;GAC9B,CAAC;GACD;EACF;EAEA,IAAI,OAAO,SAAS,cAAc;GAChC,QAAQ,aAAa;GACrB,MAAM,YAAY,WAAW,OAAO;GAEpC,IAAI,CAAC,WAAW;GAIhB,IAAI;GACJ,KAAK,IAAI,YAAY,cAAc,GAAG,aAAa,GAAG,aAAa;IACjE,MAAM,aAAa,KAAK,QAAQ;IAChC,IAAI,CAAC,YAAY;IAEjB,IAAI,YAA2B;IAC/B,IAAI,WAAW,SAAS,SAAS,YAAY,WAAW;SACnD,IACH,WAAW,SAAS,YACpB,WAAW,gBAAgB,MAE3B,YAAY,WAAW;SACpB,IAAI,WAAW,SAAS,UAC3B,YAAY,WAAW;IAEzB,IAAI,cAAc,MAAM;KACtB,MAAM,kBAAkB,aAAa;KACrC,IAAI,iBAAiB;MACnB,kBAAkB,gBAAgB,UAAU;MAC5C;KACF;IACF;GACF;GAEA,OAAO,KAAK;IACV,QAAQ;IACR,eAAe;KAAE,OAAO,UAAU;KAAW,KAAK,UAAU;IAAQ;IACpE,iBACE,oBAAoB,SAChB;KAAE,OAAO;KAAiB,KAAK;IAAgB,IAC/C;IACN,aAAa,UAAU;GACzB,CAAC;GACD;EACF;EAEA,IAAI,OAAO,SAAS,UAAU;GAC5B,QAAQ,UAAU;GAClB,MAAM,cAAc,aAAa,OAAO;GAExC,IAAI,CAAC,aAAa;GAElB,OAAO,KAAK;IACV,QAAQ;IACR,iBAAiB;KACf,OAAO,YAAY;KACnB,KAAK,YAAY;IACnB;IACA,eAAe,YAAY;GAC7B,CAAC;EACH;CACF;CAEA,OAAO;EAAE;EAAQ;CAAQ;AAC3B;;AAGA,MAAM,qBAAqB,UAA8B;CACvD,IAAI,CAAC,OAAO,OAAO,SAAS,KAAK,WAAW,MAAM;CAClD,MAAM,WACJ,MAAM,UAAU,MAAM,MAClB,IAAI,MAAM,UACV,IAAI,MAAM,MAAM,GAAG,MAAM;CAC/B,OAAO,SAAS,UAAU,WAAW,IAAI;AAC3C;;;;;AAMA,MAAM,iBAAiB,OAAe,iBACpC,eAAe,OAAO;CACpB,MAAM,WAAW;CACjB,KAAK;CACL,KAAK;CACL,KAAK;CACL,MAAM;CACN,OAAO;AACT,CAAC;;;;;;;;;;;AAYH,MAAa,sBACX,QACA,YACW;CACX,MAAM,YAAY,SAAS,aAAa;CACxC,MAAM,cAAc,SAAS,eAAe;CAE5C,MAAM,EAAE,SAAS,WAAW;CAG5B,MAAM,SAAS;EACb,SAAS,mBAAmB,WAAW,MAAM;EAC7C,cAAc,OAAO,QAAQ,WAAW,MAAM;EAC9C,SAAS,qCAAqC,WAAW,MAAM;EAC/D,cAAc,QAAQ,QAAQ,WAAW,MAAM;EAC/C,SAAS,UAAU,WAAW,MAAM;EACpC,cAAc,QAAQ,WAAW,WAAW,MAAM;EAClD,SAAS,aAAa,WAAW,MAAM;EACvC,cAAc,QAAQ,QAAQ,WAAW,GAAG;EAC5C,SAAS,YAAY,WAAW,MAAM;EACtC,eAAe,QAAQ,KAAK;EAC5B,SAAS,MAAM,WAAW,MAAM;CAClC,CAAC,CAAC,KAAK,EAAE;CAET,IAAI,OAAO,WAAW,GACpB,OAAO,GAAG,OAAO,IAAI,SAAS,sBAAsB,WAAW,KAAK;CAGtE,MAAM,WAAW,OAAO,KAAK,OAAO,UAAU;EAC5C,MAAM,QAAkB,CAAC;EAGzB,MAAM,cAAc;GAClB,SAAS,cAAc,WAAW,MAAM;GACxC,eAAe,QAAQ,CAAC;GACxB,SAAS,KAAK,WAAW,MAAM;GAC/B,eAAe,OAAO,MAAM;GAC5B,SAAS,KAAK,MAAM,OAAO,KAAK,WAAW,MAAM;GACjD;GACA,SAAS,KAAK,WAAW,MAAM;GAC/B,kBAAkB,MAAM,aAAa;GACrC,SAAS,OAAO,WAAW,MAAM;GACjC;GACA,SAAS,KAAK,WAAW,MAAM;GAC/B,kBAAkB,MAAM,eAAe;GACvC,SAAS,QAAQ,WAAW,MAAM;EACpC,CAAC,CAAC,KAAK,EAAE;EAET,MAAM,KAAK,WAAW;EAEtB,IAAI,MAAM,gBAAgB,QAAW;GACnC,MAAM,KAAK,SAAS,IAAI,UAAU,IAAI,WAAW,KAAK,CAAC;GACvD,MAAM,KAAK,SAAS,MAAM,YAAY,QAAQ,GAAG,WAAW,IAAI,CAAC;EACnE;EAEA,IAAI,MAAM,kBAAkB,QAAW;GACrC,MAAM,KAAK,SAAS,IAAI,YAAY,IAAI,WAAW,KAAK,CAAC;GACzD,MAAM,KAAK,SAAS,MAAM,cAAc,QAAQ,GAAG,WAAW,IAAI,CAAC;EACrE,OAAO,IAAI,MAAM,WAAW,cAAc;GACxC,MAAM,KAAK,SAAS,IAAI,YAAY,IAAI,WAAW,KAAK,CAAC;GACzD,MAAM,KAAK,SAAS,gCAAgC,WAAW,MAAM,CAAC;EACxE;EAEA,OAAO,MAAM,KAAK,IAAI;CACxB,CAAC;CAED,MAAM,cAAc,SAClB,mGACA,WAAW,IACb;CAEA,OAAO;EAAC;EAAQ;EAAI,GAAG;EAAU;EAAI;CAAW,CAAC,CAAC,KAAK,IAAI;AAC7D"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { parallelize } from "./utils/parallelize.mjs";
|
|
2
1
|
import { chunkArray } from "./utils/chunkArray.mjs";
|
|
2
|
+
import { parallelize } from "./utils/parallelize.mjs";
|
|
3
3
|
import { getAppLogger, x } from "@intlayer/config/logger";
|
|
4
4
|
import { getConfiguration } from "@intlayer/config/node";
|
|
5
5
|
import { retryManager } from "@intlayer/config/utils";
|
|
@@ -6,10 +6,10 @@ import { createModuleAugmentation } from "./createType/createModuleAugmentation.
|
|
|
6
6
|
import { createTypes } from "./createType/createType.mjs";
|
|
7
7
|
import { loadLocalDictionaries } from "./loadDictionaries/loadLocalDictionaries.mjs";
|
|
8
8
|
import { cleanRemovedContentDeclaration } from "./cleanRemovedContentDeclaration.mjs";
|
|
9
|
-
import { existsSync } from "node:fs";
|
|
10
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
11
9
|
import { join } from "node:path";
|
|
12
10
|
import { getAppLogger } from "@intlayer/config/logger";
|
|
11
|
+
import { existsSync } from "node:fs";
|
|
12
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
13
13
|
|
|
14
14
|
//#region src/handleContentDeclarationFileChange.ts
|
|
15
15
|
const handleContentDeclarationFileChange = async (filePath, config) => {
|
|
@@ -3,8 +3,8 @@ import { buildDictionary } from "./buildIntlayerDictionary/buildIntlayerDictiona
|
|
|
3
3
|
import { createModuleAugmentation } from "./createType/createModuleAugmentation.mjs";
|
|
4
4
|
import { createTypes } from "./createType/createType.mjs";
|
|
5
5
|
import { loadLocalDictionaries } from "./loadDictionaries/loadLocalDictionaries.mjs";
|
|
6
|
-
import { cleanRemovedContentDeclaration } from "./cleanRemovedContentDeclaration.mjs";
|
|
7
6
|
import { listDictionaries } from "./listDictionariesPath.mjs";
|
|
7
|
+
import { cleanRemovedContentDeclaration } from "./cleanRemovedContentDeclaration.mjs";
|
|
8
8
|
import { normalize } from "node:path";
|
|
9
9
|
import { getAppLogger } from "@intlayer/config/logger";
|
|
10
10
|
|
package/dist/esm/init/cms.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { enableIntlayerEditorConfig, setIntlayerConfigCompilerOutput, setIntlayerConfigRoutingMode } from "./utils/configManipulation.mjs";
|
|
1
|
+
import { enableIntlayerEditorConfig, setIntlayerConfigCompilerOutput, setIntlayerConfigEnableProxy, setIntlayerConfigRoutingMode, setIntlayerConfigRoutingStorageOnly } from "./utils/configManipulation.mjs";
|
|
2
2
|
import { exists, readFileFromRoot, writeFileToRoot } from "./utils/fileSystem.mjs";
|
|
3
3
|
import * as ANSIColors from "@intlayer/config/colors";
|
|
4
4
|
import { colorize, colorizePath, logger, v, x } from "@intlayer/config/logger";
|
|
@@ -117,6 +117,39 @@ const setRoutingModeInConfig = async (rootDir, mode) => {
|
|
|
117
117
|
return configFile;
|
|
118
118
|
};
|
|
119
119
|
/**
|
|
120
|
+
* Sets `routing.enableProxy` in the project's Intlayer configuration file.
|
|
121
|
+
* Returns the config file that was updated, or `undefined` when none was found.
|
|
122
|
+
*/
|
|
123
|
+
const setEnableProxyInConfig = async (rootDir, enableProxy) => {
|
|
124
|
+
const configFile = await findIntlayerConfigFile(rootDir);
|
|
125
|
+
if (!configFile) return void 0;
|
|
126
|
+
const extension = configFile.split(".").pop();
|
|
127
|
+
const content = await readFileFromRoot(rootDir, configFile);
|
|
128
|
+
const updatedContent = setIntlayerConfigEnableProxy(content, extension, enableProxy);
|
|
129
|
+
if (updatedContent !== content) {
|
|
130
|
+
await writeFileToRoot(rootDir, configFile, updatedContent);
|
|
131
|
+
logger(`${v} Set ${colorize(`routing.enableProxy = ${enableProxy}`, ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)}`);
|
|
132
|
+
}
|
|
133
|
+
return configFile;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Reduces `routing` in the project's Intlayer configuration file to its
|
|
137
|
+
* `storage` entry. Returns the config file that was updated, or `undefined`
|
|
138
|
+
* when none was found.
|
|
139
|
+
*/
|
|
140
|
+
const setRoutingStorageOnlyInConfig = async (rootDir) => {
|
|
141
|
+
const configFile = await findIntlayerConfigFile(rootDir);
|
|
142
|
+
if (!configFile) return void 0;
|
|
143
|
+
const extension = configFile.split(".").pop();
|
|
144
|
+
const content = await readFileFromRoot(rootDir, configFile);
|
|
145
|
+
const updatedContent = setIntlayerConfigRoutingStorageOnly(content, extension);
|
|
146
|
+
if (updatedContent !== content) {
|
|
147
|
+
await writeFileToRoot(rootDir, configFile, updatedContent);
|
|
148
|
+
logger(`${v} Kept only ${colorize("routing.storage", ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)} (no URL routing in this project)`);
|
|
149
|
+
}
|
|
150
|
+
return configFile;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
120
153
|
* Sets `compiler.output` in the project's Intlayer configuration file to the
|
|
121
154
|
* given `{{variable}}` path template. Returns the config file that was updated,
|
|
122
155
|
* or `undefined` when none was found.
|
|
@@ -144,5 +177,5 @@ const setupCmsCredentials = async (rootDir, credentials) => {
|
|
|
144
177
|
};
|
|
145
178
|
|
|
146
179
|
//#endregion
|
|
147
|
-
export { INTLAYER_CONFIG_FILE_CANDIDATES, enableEditorInConfig, findEnvFile, setCompilerOutputInConfig, setRoutingModeInConfig, setupCmsCredentials, writeCmsCredentialsToEnv };
|
|
180
|
+
export { INTLAYER_CONFIG_FILE_CANDIDATES, enableEditorInConfig, findEnvFile, setCompilerOutputInConfig, setEnableProxyInConfig, setRoutingModeInConfig, setRoutingStorageOnlyInConfig, setupCmsCredentials, writeCmsCredentialsToEnv };
|
|
148
181
|
//# sourceMappingURL=cms.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cms.mjs","names":[],"sources":["../../../src/init/cms.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport fg from 'fast-glob';\nimport {\n enableIntlayerEditorConfig,\n type RoutingMode,\n setIntlayerConfigCompilerOutput,\n setIntlayerConfigRoutingMode,\n} from './utils/configManipulation';\nimport { exists, readFileFromRoot, writeFileToRoot } from './utils/fileSystem';\n\n/**\n * Intlayer configuration file candidates, ordered by the precedence used when\n * resolving which file to mutate.\n */\nexport const INTLAYER_CONFIG_FILE_CANDIDATES = [\n 'intlayer.config.ts',\n 'intlayer.config.mjs',\n 'intlayer.config.js',\n 'intlayer.config.cjs',\n 'intlayer.config.json',\n] as const;\n\n/**\n * Environment files searched (most-preferred first) when persisting the CMS\n * credentials. The first existing match is reused; otherwise a `.env` file is\n * created at the project root.\n */\nconst ENV_FILE_CANDIDATES = ['.env', '.env.local', '.env.development'] as const;\n\n/** Credentials returned by the CMS login flow (access key pair). */\nexport type CmsCredentials = {\n clientId: string;\n clientSecret: string;\n};\n\n/**\n * Resolves the first existing Intlayer configuration file at the project root,\n * or `undefined` when none is present.\n */\nconst findIntlayerConfigFile = async (\n rootDir: string\n): Promise<(typeof INTLAYER_CONFIG_FILE_CANDIDATES)[number] | undefined> => {\n for (const candidate of INTLAYER_CONFIG_FILE_CANDIDATES) {\n if (await exists(rootDir, candidate)) {\n return candidate;\n }\n }\n\n return undefined;\n};\n\n/**\n * Locates the environment file the CMS credentials should be written to. Uses\n * `fast-glob` to detect an existing dotenv file at the project root, preferring\n * a plain `.env`; falls back to `.env` (to be created) when none exist.\n */\nexport const findEnvFile = async (rootDir: string): Promise<string> => {\n const matches = await fg([...ENV_FILE_CANDIDATES], {\n cwd: rootDir,\n dot: true,\n deep: 1,\n onlyFiles: true,\n });\n\n return (\n ENV_FILE_CANDIDATES.find((candidate) => matches.includes(candidate)) ??\n '.env'\n );\n};\n\n/**\n * Inserts or updates a `KEY=value` line in dotenv file content. An existing\n * assignment of the same key is replaced in place; otherwise the line is\n * appended with a trailing newline.\n */\nconst upsertEnvVariable = (\n content: string,\n key: string,\n value: string\n): string => {\n const line = `${key}=${value}`;\n const keyMatcher = new RegExp(`^${key}=.*$`, 'm');\n\n if (keyMatcher.test(content)) {\n return content.replace(keyMatcher, line);\n }\n\n const needsLeadingNewline = content.length > 0 && !content.endsWith('\\n');\n\n return `${content}${needsLeadingNewline ? '\\n' : ''}${line}\\n`;\n};\n\n/**\n * Persists the CMS access-key credentials to the project's environment file as\n * `INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET`. The target file is detected\n * with {@link findEnvFile} and created when missing. Returns the relative path\n * of the file that was written.\n */\nexport const writeCmsCredentialsToEnv = async (\n rootDir: string,\n { clientId, clientSecret }: CmsCredentials\n): Promise<string> => {\n const envFile = await findEnvFile(rootDir);\n\n let content = '';\n if (await exists(rootDir, envFile)) {\n content = await readFileFromRoot(rootDir, envFile);\n }\n\n let updatedContent = content;\n updatedContent = upsertEnvVariable(\n updatedContent,\n 'INTLAYER_CLIENT_ID',\n clientId\n );\n updatedContent = upsertEnvVariable(\n updatedContent,\n 'INTLAYER_CLIENT_SECRET',\n clientSecret\n );\n\n await writeFileToRoot(rootDir, envFile, updatedContent);\n logger(\n `${v} Saved Intlayer CMS credentials to ${colorizePath(envFile)} (${colorize('INTLAYER_CLIENT_ID', ANSIColors.GREY_LIGHT)}, ${colorize('INTLAYER_CLIENT_SECRET', ANSIColors.GREY_LIGHT)})`\n );\n\n return envFile;\n};\n\n/**\n * Enables the Intlayer visual editor in the project's configuration file:\n * flips `editor.enabled` to `true` and wires `clientId` / `clientSecret` to the\n * matching environment variables. JSON configs cannot reference `process.env`,\n * so they are skipped with a warning. Returns the config file that was updated,\n * or `undefined` when no editable config was found.\n */\nexport const enableEditorInConfig = async (\n rootDir: string\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) {\n logger(\n `${x} Could not find an Intlayer configuration file to enable the editor.`,\n { level: 'warn' }\n );\n return undefined;\n }\n\n const extension = configFile.split('.').pop()!;\n\n if (extension === 'json') {\n logger(\n `${x} ${colorizePath(configFile)} is a JSON config and cannot reference environment variables. Enable the editor and set clientId/clientSecret manually.`,\n { level: 'warn' }\n );\n return undefined;\n }\n\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = enableIntlayerEditorConfig(content);\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(`${v} Enabled the Intlayer editor in ${colorizePath(configFile)}`);\n } else {\n logger(\n `${v} ${colorizePath(configFile)} already has the Intlayer editor enabled`\n );\n }\n\n return configFile;\n};\n\n/**\n * Sets `routing.mode` in the project's Intlayer configuration file. Returns the\n * config file that was updated, or `undefined` when none was found.\n */\nexport const setRoutingModeInConfig = async (\n rootDir: string,\n mode: RoutingMode\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) return undefined;\n\n const extension = configFile.split('.').pop()!;\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = setIntlayerConfigRoutingMode(content, extension, mode);\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(\n `${v} Set ${colorize(`routing.mode = '${mode}'`, ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)}`\n );\n }\n\n return configFile;\n};\n\n/**\n * Sets `compiler.output` in the project's Intlayer configuration file to the\n * given `{{variable}}` path template. Returns the config file that was updated,\n * or `undefined` when none was found.\n */\nexport const setCompilerOutputInConfig = async (\n rootDir: string,\n outputTemplate: string\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) return undefined;\n\n const extension = configFile.split('.').pop()!;\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = setIntlayerConfigCompilerOutput(\n content,\n extension,\n outputTemplate\n );\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(\n `${v} Set ${colorize(`compiler.output = '${outputTemplate}'`, ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)}`\n );\n }\n\n return configFile;\n};\n\n/**\n * Completes the CMS setup once credentials are received from the login flow:\n * writes them to the environment file and enables the editor in the Intlayer\n * configuration file.\n */\nexport const setupCmsCredentials = async (\n rootDir: string,\n credentials: CmsCredentials\n): Promise<void> => {\n await writeCmsCredentialsToEnv(rootDir, credentials);\n await enableEditorInConfig(rootDir);\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cms.mjs","names":[],"sources":["../../../src/init/cms.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport fg from 'fast-glob';\nimport {\n enableIntlayerEditorConfig,\n type RoutingMode,\n setIntlayerConfigCompilerOutput,\n setIntlayerConfigEnableProxy,\n setIntlayerConfigRoutingMode,\n setIntlayerConfigRoutingStorageOnly,\n} from './utils/configManipulation';\nimport { exists, readFileFromRoot, writeFileToRoot } from './utils/fileSystem';\n\n/**\n * Intlayer configuration file candidates, ordered by the precedence used when\n * resolving which file to mutate.\n */\nexport const INTLAYER_CONFIG_FILE_CANDIDATES = [\n 'intlayer.config.ts',\n 'intlayer.config.mjs',\n 'intlayer.config.js',\n 'intlayer.config.cjs',\n 'intlayer.config.json',\n] as const;\n\n/**\n * Environment files searched (most-preferred first) when persisting the CMS\n * credentials. The first existing match is reused; otherwise a `.env` file is\n * created at the project root.\n */\nconst ENV_FILE_CANDIDATES = ['.env', '.env.local', '.env.development'] as const;\n\n/** Credentials returned by the CMS login flow (access key pair). */\nexport type CmsCredentials = {\n clientId: string;\n clientSecret: string;\n};\n\n/**\n * Resolves the first existing Intlayer configuration file at the project root,\n * or `undefined` when none is present.\n */\nconst findIntlayerConfigFile = async (\n rootDir: string\n): Promise<(typeof INTLAYER_CONFIG_FILE_CANDIDATES)[number] | undefined> => {\n for (const candidate of INTLAYER_CONFIG_FILE_CANDIDATES) {\n if (await exists(rootDir, candidate)) {\n return candidate;\n }\n }\n\n return undefined;\n};\n\n/**\n * Locates the environment file the CMS credentials should be written to. Uses\n * `fast-glob` to detect an existing dotenv file at the project root, preferring\n * a plain `.env`; falls back to `.env` (to be created) when none exist.\n */\nexport const findEnvFile = async (rootDir: string): Promise<string> => {\n const matches = await fg([...ENV_FILE_CANDIDATES], {\n cwd: rootDir,\n dot: true,\n deep: 1,\n onlyFiles: true,\n });\n\n return (\n ENV_FILE_CANDIDATES.find((candidate) => matches.includes(candidate)) ??\n '.env'\n );\n};\n\n/**\n * Inserts or updates a `KEY=value` line in dotenv file content. An existing\n * assignment of the same key is replaced in place; otherwise the line is\n * appended with a trailing newline.\n */\nconst upsertEnvVariable = (\n content: string,\n key: string,\n value: string\n): string => {\n const line = `${key}=${value}`;\n const keyMatcher = new RegExp(`^${key}=.*$`, 'm');\n\n if (keyMatcher.test(content)) {\n return content.replace(keyMatcher, line);\n }\n\n const needsLeadingNewline = content.length > 0 && !content.endsWith('\\n');\n\n return `${content}${needsLeadingNewline ? '\\n' : ''}${line}\\n`;\n};\n\n/**\n * Persists the CMS access-key credentials to the project's environment file as\n * `INTLAYER_CLIENT_ID` / `INTLAYER_CLIENT_SECRET`. The target file is detected\n * with {@link findEnvFile} and created when missing. Returns the relative path\n * of the file that was written.\n */\nexport const writeCmsCredentialsToEnv = async (\n rootDir: string,\n { clientId, clientSecret }: CmsCredentials\n): Promise<string> => {\n const envFile = await findEnvFile(rootDir);\n\n let content = '';\n if (await exists(rootDir, envFile)) {\n content = await readFileFromRoot(rootDir, envFile);\n }\n\n let updatedContent = content;\n updatedContent = upsertEnvVariable(\n updatedContent,\n 'INTLAYER_CLIENT_ID',\n clientId\n );\n updatedContent = upsertEnvVariable(\n updatedContent,\n 'INTLAYER_CLIENT_SECRET',\n clientSecret\n );\n\n await writeFileToRoot(rootDir, envFile, updatedContent);\n logger(\n `${v} Saved Intlayer CMS credentials to ${colorizePath(envFile)} (${colorize('INTLAYER_CLIENT_ID', ANSIColors.GREY_LIGHT)}, ${colorize('INTLAYER_CLIENT_SECRET', ANSIColors.GREY_LIGHT)})`\n );\n\n return envFile;\n};\n\n/**\n * Enables the Intlayer visual editor in the project's configuration file:\n * flips `editor.enabled` to `true` and wires `clientId` / `clientSecret` to the\n * matching environment variables. JSON configs cannot reference `process.env`,\n * so they are skipped with a warning. Returns the config file that was updated,\n * or `undefined` when no editable config was found.\n */\nexport const enableEditorInConfig = async (\n rootDir: string\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) {\n logger(\n `${x} Could not find an Intlayer configuration file to enable the editor.`,\n { level: 'warn' }\n );\n return undefined;\n }\n\n const extension = configFile.split('.').pop()!;\n\n if (extension === 'json') {\n logger(\n `${x} ${colorizePath(configFile)} is a JSON config and cannot reference environment variables. Enable the editor and set clientId/clientSecret manually.`,\n { level: 'warn' }\n );\n return undefined;\n }\n\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = enableIntlayerEditorConfig(content);\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(`${v} Enabled the Intlayer editor in ${colorizePath(configFile)}`);\n } else {\n logger(\n `${v} ${colorizePath(configFile)} already has the Intlayer editor enabled`\n );\n }\n\n return configFile;\n};\n\n/**\n * Sets `routing.mode` in the project's Intlayer configuration file. Returns the\n * config file that was updated, or `undefined` when none was found.\n */\nexport const setRoutingModeInConfig = async (\n rootDir: string,\n mode: RoutingMode\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) return undefined;\n\n const extension = configFile.split('.').pop()!;\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = setIntlayerConfigRoutingMode(content, extension, mode);\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(\n `${v} Set ${colorize(`routing.mode = '${mode}'`, ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)}`\n );\n }\n\n return configFile;\n};\n\n/**\n * Sets `routing.enableProxy` in the project's Intlayer configuration file.\n * Returns the config file that was updated, or `undefined` when none was found.\n */\nexport const setEnableProxyInConfig = async (\n rootDir: string,\n enableProxy: boolean\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) return undefined;\n\n const extension = configFile.split('.').pop()!;\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = setIntlayerConfigEnableProxy(\n content,\n extension,\n enableProxy\n );\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(\n `${v} Set ${colorize(`routing.enableProxy = ${enableProxy}`, ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)}`\n );\n }\n\n return configFile;\n};\n\n/**\n * Reduces `routing` in the project's Intlayer configuration file to its\n * `storage` entry. Returns the config file that was updated, or `undefined`\n * when none was found.\n */\nexport const setRoutingStorageOnlyInConfig = async (\n rootDir: string\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) return undefined;\n\n const extension = configFile.split('.').pop()!;\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = setIntlayerConfigRoutingStorageOnly(\n content,\n extension\n );\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(\n `${v} Kept only ${colorize('routing.storage', ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)} (no URL routing in this project)`\n );\n }\n\n return configFile;\n};\n\n/**\n * Sets `compiler.output` in the project's Intlayer configuration file to the\n * given `{{variable}}` path template. Returns the config file that was updated,\n * or `undefined` when none was found.\n */\nexport const setCompilerOutputInConfig = async (\n rootDir: string,\n outputTemplate: string\n): Promise<string | undefined> => {\n const configFile = await findIntlayerConfigFile(rootDir);\n\n if (!configFile) return undefined;\n\n const extension = configFile.split('.').pop()!;\n const content = await readFileFromRoot(rootDir, configFile);\n const updatedContent = setIntlayerConfigCompilerOutput(\n content,\n extension,\n outputTemplate\n );\n\n if (updatedContent !== content) {\n await writeFileToRoot(rootDir, configFile, updatedContent);\n logger(\n `${v} Set ${colorize(`compiler.output = '${outputTemplate}'`, ANSIColors.GREY_LIGHT)} in ${colorizePath(configFile)}`\n );\n }\n\n return configFile;\n};\n\n/**\n * Completes the CMS setup once credentials are received from the login flow:\n * writes them to the environment file and enables the editor in the Intlayer\n * configuration file.\n */\nexport const setupCmsCredentials = async (\n rootDir: string,\n credentials: CmsCredentials\n): Promise<void> => {\n await writeCmsCredentialsToEnv(rootDir, credentials);\n await enableEditorInConfig(rootDir);\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
//#region src/init/documentationRouter.ts
|
|
2
|
+
/**
|
|
3
|
+
* Documentation URL Constants
|
|
4
|
+
*/
|
|
5
|
+
const DocumentationRouter = {
|
|
6
|
+
NextJS: "https://intlayer.org/doc/environment/nextjs",
|
|
7
|
+
NextJS_16: "https://intlayer.org/doc/environment/nextjs",
|
|
8
|
+
NextJS_15: "https://intlayer.org/doc/environment/nextjs/15",
|
|
9
|
+
NextJS_14: "https://intlayer.org/doc/environment/nextjs/14",
|
|
10
|
+
NextJS_PageRouter: "https://intlayer.org/doc/environment/nextjs/next-with-page-router",
|
|
11
|
+
CRA: "https://intlayer.org/doc/environment/create-react-app",
|
|
12
|
+
Astro: "https://intlayer.org/doc/environment/astro",
|
|
13
|
+
Astro_Lit: "https://intlayer.org/doc/environment/astro/lit",
|
|
14
|
+
Astro_Preact: "https://intlayer.org/doc/environment/astro/preact",
|
|
15
|
+
Astro_React: "https://intlayer.org/doc/environment/astro/react",
|
|
16
|
+
Astro_Solid: "https://intlayer.org/doc/environment/astro/solid",
|
|
17
|
+
Astro_Svelte: "https://intlayer.org/doc/environment/astro/svelte",
|
|
18
|
+
Astro_Vue: "https://intlayer.org/doc/environment/astro/vue",
|
|
19
|
+
ViteAndReact: "https://intlayer.org/doc/environment/vite-and-react",
|
|
20
|
+
ViteAndReact_ReactRouterV7: "https://intlayer.org/doc/environment/vite-and-react/react-router-v7",
|
|
21
|
+
ViteAndVue: "https://intlayer.org/doc/environment/vite-and-vue",
|
|
22
|
+
ViteAndSolid: "https://intlayer.org/doc/environment/vite-and-solid",
|
|
23
|
+
ViteAndSvelte: "https://intlayer.org/doc/environment/vite-and-svelte",
|
|
24
|
+
ViteAndPreact: "https://intlayer.org/doc/environment/vite-and-preact",
|
|
25
|
+
ViteAndLit: "https://intlayer.org/doc/environment/vite-and-lit",
|
|
26
|
+
ViteAndVanilla: "https://intlayer.org/doc/environment/vite-and-vanilla",
|
|
27
|
+
Vanilla: "https://intlayer.org/doc/environment/vanilla",
|
|
28
|
+
TanStackRouter: "https://intlayer.org/doc/environment/tanstack-start",
|
|
29
|
+
TanStackRouterAndSolid: "https://intlayer.org/doc/environment/tanstack-start/solid",
|
|
30
|
+
SolidStart: "https://intlayer.org/doc/environment/solid-start",
|
|
31
|
+
Analog: "https://intlayer.org/doc/environment/analog",
|
|
32
|
+
Remix: "https://intlayer.org/doc/environment/remix-3",
|
|
33
|
+
NuxtAndVue: "https://intlayer.org/doc/environment/nuxt-and-vue",
|
|
34
|
+
Angular: "https://intlayer.org/doc/environment/angular",
|
|
35
|
+
Angular_19: "https://intlayer.org/doc/environment/angular/19",
|
|
36
|
+
SvelteKit: "https://intlayer.org/doc/environment/sveltekit",
|
|
37
|
+
ReactNativeAndExpo: "https://intlayer.org/doc/environment/react-native-and-expo",
|
|
38
|
+
Lynx: "https://intlayer.org/doc/environment/lynx-and-react",
|
|
39
|
+
HTMX: "https://intlayer.org/doc/environment/htmx",
|
|
40
|
+
Storybook: "https://intlayer.org/doc/storybook",
|
|
41
|
+
Express: "https://intlayer.org/doc/environment/express",
|
|
42
|
+
NestJS: "https://intlayer.org/doc/environment/nest",
|
|
43
|
+
Fastify: "https://intlayer.org/doc/environment/fastify",
|
|
44
|
+
Hono: "https://intlayer.org/doc/environment/hono",
|
|
45
|
+
AdonisJS: "https://intlayer.org/doc/environment/adonisjs",
|
|
46
|
+
Elysia: "https://intlayer.org/doc/environment/elysia",
|
|
47
|
+
Default: "https://intlayer.org/doc/get-started",
|
|
48
|
+
LSP: "https://intlayer.org/doc/lsp",
|
|
49
|
+
ESLint: "https://intlayer.org/doc/eslint",
|
|
50
|
+
NextIntl: "https://intlayer.org/doc/next-intl",
|
|
51
|
+
NextI18Next: "https://intlayer.org/doc/next-i18next",
|
|
52
|
+
ReactI18Next: "https://intlayer.org/doc/compatibility/react-i18next",
|
|
53
|
+
ReactIntl: "https://intlayer.org/doc/compatibility/react-intl",
|
|
54
|
+
VueI18n: "https://intlayer.org/doc/compatibility/vue-i18n",
|
|
55
|
+
NuxtI18n: "https://intlayer.org/doc/compatibility/nuxtjs-i18n",
|
|
56
|
+
I18next: "https://intlayer.org/doc/compatibility/i18next"
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Helper: Detects the environment and returns the doc URL
|
|
60
|
+
*/
|
|
61
|
+
const getDocumentationUrl = (packageJson) => {
|
|
62
|
+
const deps = {
|
|
63
|
+
...packageJson?.dependencies,
|
|
64
|
+
...packageJson?.devDependencies
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Helper to check if a version string matches a specific major version
|
|
68
|
+
* Matches: "15", "^15.0.0", "~15.2", "15.0.0-beta"
|
|
69
|
+
*/
|
|
70
|
+
const isVersion = (versionString, major) => {
|
|
71
|
+
if (!versionString || typeof versionString !== "string") return false;
|
|
72
|
+
return new RegExp(`^[\\^~]?${major}(?:\\.|$)`).test(versionString);
|
|
73
|
+
};
|
|
74
|
+
if (deps["@lynx-js/react"] || deps["@lynx-js/core"]) return DocumentationRouter.Lynx;
|
|
75
|
+
if (deps["react-native"] || deps.expo) return DocumentationRouter.ReactNativeAndExpo;
|
|
76
|
+
if (deps.next) {
|
|
77
|
+
const version = deps.next;
|
|
78
|
+
if (isVersion(version, 14)) return DocumentationRouter.NextJS_14;
|
|
79
|
+
if (isVersion(version, 15)) return DocumentationRouter.NextJS_15;
|
|
80
|
+
return DocumentationRouter.NextJS;
|
|
81
|
+
}
|
|
82
|
+
if (deps.nuxt) return DocumentationRouter.NuxtAndVue;
|
|
83
|
+
if (deps.astro) {
|
|
84
|
+
if (deps["@astrojs/react"] || deps.react) return DocumentationRouter.Astro_React;
|
|
85
|
+
if (deps["@astrojs/vue"] || deps.vue) return DocumentationRouter.Astro_Vue;
|
|
86
|
+
if (deps["@astrojs/svelte"] || deps.svelte) return DocumentationRouter.Astro_Svelte;
|
|
87
|
+
if (deps["@astrojs/solid-js"] || deps["solid-js"]) return DocumentationRouter.Astro_Solid;
|
|
88
|
+
if (deps["@astrojs/preact"] || deps.preact) return DocumentationRouter.Astro_Preact;
|
|
89
|
+
if (deps["@astrojs/lit"] || deps.lit) return DocumentationRouter.Astro_Lit;
|
|
90
|
+
return DocumentationRouter.Astro;
|
|
91
|
+
}
|
|
92
|
+
if (deps["@sveltejs/kit"]) return DocumentationRouter.SvelteKit;
|
|
93
|
+
if (deps["@analogjs/platform"]) return DocumentationRouter.Analog;
|
|
94
|
+
if (deps["@solidjs/start"]) return DocumentationRouter.SolidStart;
|
|
95
|
+
if (deps.remix || deps["remix-intlayer"]) return DocumentationRouter.Remix;
|
|
96
|
+
if (deps["@tanstack/react-router"]) return DocumentationRouter.TanStackRouter;
|
|
97
|
+
if (deps["@tanstack/solid-router"]) return DocumentationRouter.TanStackRouterAndSolid;
|
|
98
|
+
if (deps["@tanstack/start"]) {
|
|
99
|
+
if (deps["solid-js"] || deps["@tanstack/solid-router"]) return DocumentationRouter.TanStackRouterAndSolid;
|
|
100
|
+
return DocumentationRouter.TanStackRouter;
|
|
101
|
+
}
|
|
102
|
+
const reactRouterVersion = deps["react-router"];
|
|
103
|
+
if (typeof reactRouterVersion === "string" && (deps["@react-router/fs-routes"] || isVersion(reactRouterVersion, 7))) return DocumentationRouter.ViteAndReact_ReactRouterV7;
|
|
104
|
+
if (deps.vite) {
|
|
105
|
+
if (deps.vue) return DocumentationRouter.ViteAndVue;
|
|
106
|
+
if (deps["solid-js"]) return DocumentationRouter.ViteAndSolid;
|
|
107
|
+
if (deps.svelte) return DocumentationRouter.ViteAndSvelte;
|
|
108
|
+
if (deps.preact) return DocumentationRouter.ViteAndPreact;
|
|
109
|
+
if (deps.lit) return DocumentationRouter.ViteAndLit;
|
|
110
|
+
if (deps["vanilla-intlayer"]) return DocumentationRouter.ViteAndVanilla;
|
|
111
|
+
return DocumentationRouter.ViteAndReact;
|
|
112
|
+
}
|
|
113
|
+
if (deps["react-scripts"]) return DocumentationRouter.CRA;
|
|
114
|
+
if (deps["@angular/core"]) {
|
|
115
|
+
const version = deps["@angular/core"];
|
|
116
|
+
if (isVersion(version, 19)) return DocumentationRouter.Angular_19;
|
|
117
|
+
return DocumentationRouter.Angular;
|
|
118
|
+
}
|
|
119
|
+
if (deps.lit) return DocumentationRouter.ViteAndLit;
|
|
120
|
+
if (deps["vanilla-intlayer"]) return DocumentationRouter.Vanilla;
|
|
121
|
+
if (deps.htmx || deps["htmx.org"]) return DocumentationRouter.HTMX;
|
|
122
|
+
if (deps.storybook || deps["@storybook/react"] || deps["@storybook/vue3"]) return DocumentationRouter.Storybook;
|
|
123
|
+
if (deps["@nestjs/core"]) return DocumentationRouter.NestJS;
|
|
124
|
+
if (deps["@adonisjs/core"]) return DocumentationRouter.AdonisJS;
|
|
125
|
+
if (deps.elysia) return DocumentationRouter.Elysia;
|
|
126
|
+
if (deps.hono) return DocumentationRouter.Hono;
|
|
127
|
+
if (deps.express) return DocumentationRouter.Express;
|
|
128
|
+
if (deps.fastify) return DocumentationRouter.Fastify;
|
|
129
|
+
if (deps["next-intl"]) return DocumentationRouter.NextIntl;
|
|
130
|
+
if (deps["react-i18next"] || deps.i18next) return DocumentationRouter.ReactI18Next;
|
|
131
|
+
if (deps["react-intl"]) return DocumentationRouter.ReactIntl;
|
|
132
|
+
if (deps["next-i18next"]) return DocumentationRouter.NextI18Next;
|
|
133
|
+
if (deps["vue-i18n"]) return DocumentationRouter.VueI18n;
|
|
134
|
+
return DocumentationRouter.Default;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
//#endregion
|
|
138
|
+
export { DocumentationRouter, getDocumentationUrl };
|
|
139
|
+
//# sourceMappingURL=documentationRouter.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documentationRouter.mjs","names":[],"sources":["../../../src/init/documentationRouter.ts"],"sourcesContent":["/**\n * Documentation URL Constants\n */\nexport const DocumentationRouter = {\n NextJS: 'https://intlayer.org/doc/environment/nextjs',\n NextJS_16: 'https://intlayer.org/doc/environment/nextjs',\n NextJS_15: 'https://intlayer.org/doc/environment/nextjs/15',\n NextJS_14: 'https://intlayer.org/doc/environment/nextjs/14',\n NextJS_PageRouter:\n 'https://intlayer.org/doc/environment/nextjs/next-with-page-router',\n CRA: 'https://intlayer.org/doc/environment/create-react-app',\n Astro: 'https://intlayer.org/doc/environment/astro',\n Astro_Lit: 'https://intlayer.org/doc/environment/astro/lit',\n Astro_Preact: 'https://intlayer.org/doc/environment/astro/preact',\n Astro_React: 'https://intlayer.org/doc/environment/astro/react',\n Astro_Solid: 'https://intlayer.org/doc/environment/astro/solid',\n Astro_Svelte: 'https://intlayer.org/doc/environment/astro/svelte',\n Astro_Vue: 'https://intlayer.org/doc/environment/astro/vue',\n ViteAndReact: 'https://intlayer.org/doc/environment/vite-and-react',\n ViteAndReact_ReactRouterV7:\n 'https://intlayer.org/doc/environment/vite-and-react/react-router-v7',\n ViteAndVue: 'https://intlayer.org/doc/environment/vite-and-vue',\n ViteAndSolid: 'https://intlayer.org/doc/environment/vite-and-solid',\n ViteAndSvelte: 'https://intlayer.org/doc/environment/vite-and-svelte',\n ViteAndPreact: 'https://intlayer.org/doc/environment/vite-and-preact',\n ViteAndLit: 'https://intlayer.org/doc/environment/vite-and-lit',\n ViteAndVanilla: 'https://intlayer.org/doc/environment/vite-and-vanilla',\n Vanilla: 'https://intlayer.org/doc/environment/vanilla',\n TanStackRouter: 'https://intlayer.org/doc/environment/tanstack-start',\n TanStackRouterAndSolid:\n 'https://intlayer.org/doc/environment/tanstack-start/solid',\n SolidStart: 'https://intlayer.org/doc/environment/solid-start',\n Analog: 'https://intlayer.org/doc/environment/analog',\n Remix: 'https://intlayer.org/doc/environment/remix-3',\n NuxtAndVue: 'https://intlayer.org/doc/environment/nuxt-and-vue',\n Angular: 'https://intlayer.org/doc/environment/angular',\n Angular_19: 'https://intlayer.org/doc/environment/angular/19',\n SvelteKit: 'https://intlayer.org/doc/environment/sveltekit',\n ReactNativeAndExpo:\n 'https://intlayer.org/doc/environment/react-native-and-expo',\n Lynx: 'https://intlayer.org/doc/environment/lynx-and-react',\n HTMX: 'https://intlayer.org/doc/environment/htmx',\n Storybook: 'https://intlayer.org/doc/storybook',\n Express: 'https://intlayer.org/doc/environment/express',\n NestJS: 'https://intlayer.org/doc/environment/nest',\n Fastify: 'https://intlayer.org/doc/environment/fastify',\n Hono: 'https://intlayer.org/doc/environment/hono',\n AdonisJS: 'https://intlayer.org/doc/environment/adonisjs',\n Elysia: 'https://intlayer.org/doc/environment/elysia',\n Default: 'https://intlayer.org/doc/get-started',\n\n // Intlayer Language Server (Go-to-Definition from getter keys to .content files)\n LSP: 'https://intlayer.org/doc/lsp',\n\n // Lint rules for hardcoded text and non-optimizable dynamic calls\n ESLint: 'https://intlayer.org/doc/eslint',\n\n // Competitor / Compat libs\n NextIntl: 'https://intlayer.org/doc/next-intl',\n NextI18Next: 'https://intlayer.org/doc/next-i18next',\n ReactI18Next: 'https://intlayer.org/doc/compatibility/react-i18next',\n ReactIntl: 'https://intlayer.org/doc/compatibility/react-intl',\n VueI18n: 'https://intlayer.org/doc/compatibility/vue-i18n',\n NuxtI18n: 'https://intlayer.org/doc/compatibility/nuxtjs-i18n',\n I18next: 'https://intlayer.org/doc/compatibility/i18next',\n};\n\nexport type DocumentationRouterType = typeof DocumentationRouter;\n\n/**\n * Helper: Detects the environment and returns the doc URL\n */\nexport const getDocumentationUrl = (packageJson: any): string => {\n const deps = {\n ...packageJson?.dependencies,\n ...packageJson?.devDependencies,\n };\n\n /**\n * Helper to check if a version string matches a specific major version\n * Matches: \"15\", \"^15.0.0\", \"~15.2\", \"15.0.0-beta\"\n */\n const isVersion = (versionString: string, major: number): boolean => {\n if (!versionString || typeof versionString !== 'string') return false;\n const regex = new RegExp(`^[\\\\^~]?${major}(?:\\\\.|$)`);\n return regex.test(versionString);\n };\n\n // Mobile / Cross-platform\n if (deps['@lynx-js/react'] || deps['@lynx-js/core']) {\n return DocumentationRouter.Lynx;\n }\n if (deps['react-native'] || deps.expo) {\n return DocumentationRouter.ReactNativeAndExpo;\n }\n\n // Meta-frameworks (Next, Nuxt, Astro, SvelteKit)\n if (deps.next) {\n const version = deps.next;\n\n if (isVersion(version, 14)) {\n return DocumentationRouter.NextJS_14;\n }\n\n if (isVersion(version, 15)) {\n return DocumentationRouter.NextJS_15;\n }\n\n return DocumentationRouter.NextJS;\n }\n\n if (deps.nuxt) return DocumentationRouter.NuxtAndVue;\n\n if (deps.astro) {\n if (deps['@astrojs/react'] || deps.react)\n return DocumentationRouter.Astro_React;\n if (deps['@astrojs/vue'] || deps.vue) return DocumentationRouter.Astro_Vue;\n if (deps['@astrojs/svelte'] || deps.svelte)\n return DocumentationRouter.Astro_Svelte;\n if (deps['@astrojs/solid-js'] || deps['solid-js'])\n return DocumentationRouter.Astro_Solid;\n if (deps['@astrojs/preact'] || deps.preact)\n return DocumentationRouter.Astro_Preact;\n if (deps['@astrojs/lit'] || deps.lit) return DocumentationRouter.Astro_Lit;\n\n return DocumentationRouter.Astro;\n }\n\n if (deps['@sveltejs/kit']) return DocumentationRouter.SvelteKit;\n if (deps['@analogjs/platform']) return DocumentationRouter.Analog;\n if (deps['@solidjs/start']) return DocumentationRouter.SolidStart;\n if (deps.remix || deps['remix-intlayer']) return DocumentationRouter.Remix;\n\n // Routers (TanStack & React Router v7)\n if (deps['@tanstack/react-router']) {\n return DocumentationRouter.TanStackRouter;\n }\n if (deps['@tanstack/solid-router']) {\n return DocumentationRouter.TanStackRouterAndSolid;\n }\n if (deps['@tanstack/start']) {\n if (deps['solid-js'] || deps['@tanstack/solid-router']) {\n return DocumentationRouter.TanStackRouterAndSolid;\n }\n return DocumentationRouter.TanStackRouter;\n }\n\n // Check for React Router v7 (the guide covers both config and FS routes)\n const reactRouterVersion = deps['react-router'];\n if (\n typeof reactRouterVersion === 'string' &&\n (deps['@react-router/fs-routes'] || isVersion(reactRouterVersion, 7))\n ) {\n return DocumentationRouter.ViteAndReact_ReactRouterV7;\n }\n\n // Vite Ecosystem (General)\n if (deps.vite) {\n if (deps.vue) return DocumentationRouter.ViteAndVue;\n if (deps['solid-js']) return DocumentationRouter.ViteAndSolid;\n if (deps.svelte) return DocumentationRouter.ViteAndSvelte;\n if (deps.preact) return DocumentationRouter.ViteAndPreact;\n if (deps.lit) return DocumentationRouter.ViteAndLit;\n if (deps['vanilla-intlayer']) return DocumentationRouter.ViteAndVanilla;\n\n // Default to React if Vite is present but specific other frameworks aren't found\n return DocumentationRouter.ViteAndReact;\n }\n\n // Other Web Frameworks\n if (deps['react-scripts']) return DocumentationRouter.CRA;\n if (deps['@angular/core']) {\n const version = deps['@angular/core'];\n if (isVersion(version, 19)) {\n return DocumentationRouter.Angular_19;\n }\n return DocumentationRouter.Angular;\n }\n if (deps.lit) return DocumentationRouter.ViteAndLit;\n if (deps['vanilla-intlayer']) return DocumentationRouter.Vanilla;\n if (deps.htmx || deps['htmx.org']) return DocumentationRouter.HTMX;\n if (deps.storybook || deps['@storybook/react'] || deps['@storybook/vue3'])\n return DocumentationRouter.Storybook;\n\n // Backend\n // NestJS first: it runs on top of Express (or Fastify), so both dependencies\n // are present and the more specific one has to win.\n if (deps['@nestjs/core']) return DocumentationRouter.NestJS;\n if (deps['@adonisjs/core']) return DocumentationRouter.AdonisJS;\n if (deps.elysia) return DocumentationRouter.Elysia;\n if (deps.hono) return DocumentationRouter.Hono;\n if (deps.express) return DocumentationRouter.Express;\n if (deps.fastify) return DocumentationRouter.Fastify;\n\n // Competitor Libs (Migration Guides)\n // We check these last as specific environment setup is usually higher priority,\n // but if no specific framework logic matched (or as a fallback), we guide to migration.\n if (deps['next-intl']) return DocumentationRouter.NextIntl;\n if (deps['react-i18next'] || deps.i18next)\n return DocumentationRouter.ReactI18Next;\n if (deps['react-intl']) return DocumentationRouter.ReactIntl;\n if (deps['next-i18next']) return DocumentationRouter.NextI18Next;\n if (deps['vue-i18n']) return DocumentationRouter.VueI18n;\n\n return DocumentationRouter.Default;\n};\n"],"mappings":";;;;AAGA,MAAa,sBAAsB;CACjC,QAAQ;CACR,WAAW;CACX,WAAW;CACX,WAAW;CACX,mBACE;CACF,KAAK;CACL,OAAO;CACP,WAAW;CACX,cAAc;CACd,aAAa;CACb,aAAa;CACb,cAAc;CACd,WAAW;CACX,cAAc;CACd,4BACE;CACF,YAAY;CACZ,cAAc;CACd,eAAe;CACf,eAAe;CACf,YAAY;CACZ,gBAAgB;CAChB,SAAS;CACT,gBAAgB;CAChB,wBACE;CACF,YAAY;CACZ,QAAQ;CACR,OAAO;CACP,YAAY;CACZ,SAAS;CACT,YAAY;CACZ,WAAW;CACX,oBACE;CACF,MAAM;CACN,MAAM;CACN,WAAW;CACX,SAAS;CACT,QAAQ;CACR,SAAS;CACT,MAAM;CACN,UAAU;CACV,QAAQ;CACR,SAAS;CAGT,KAAK;CAGL,QAAQ;CAGR,UAAU;CACV,aAAa;CACb,cAAc;CACd,WAAW;CACX,SAAS;CACT,UAAU;CACV,SAAS;AACX;;;;AAOA,MAAa,uBAAuB,gBAA6B;CAC/D,MAAM,OAAO;EACX,GAAG,aAAa;EAChB,GAAG,aAAa;CAClB;;;;;CAMA,MAAM,aAAa,eAAuB,UAA2B;EACnE,IAAI,CAAC,iBAAiB,OAAO,kBAAkB,UAAU,OAAO;EAEhE,OAAO,IADW,OAAO,WAAW,MAAM,UAC/B,CAAC,CAAC,KAAK,aAAa;CACjC;CAGA,IAAI,KAAK,qBAAqB,KAAK,kBACjC,OAAO,oBAAoB;CAE7B,IAAI,KAAK,mBAAmB,KAAK,MAC/B,OAAO,oBAAoB;CAI7B,IAAI,KAAK,MAAM;EACb,MAAM,UAAU,KAAK;EAErB,IAAI,UAAU,SAAS,EAAE,GACvB,OAAO,oBAAoB;EAG7B,IAAI,UAAU,SAAS,EAAE,GACvB,OAAO,oBAAoB;EAG7B,OAAO,oBAAoB;CAC7B;CAEA,IAAI,KAAK,MAAM,OAAO,oBAAoB;CAE1C,IAAI,KAAK,OAAO;EACd,IAAI,KAAK,qBAAqB,KAAK,OACjC,OAAO,oBAAoB;EAC7B,IAAI,KAAK,mBAAmB,KAAK,KAAK,OAAO,oBAAoB;EACjE,IAAI,KAAK,sBAAsB,KAAK,QAClC,OAAO,oBAAoB;EAC7B,IAAI,KAAK,wBAAwB,KAAK,aACpC,OAAO,oBAAoB;EAC7B,IAAI,KAAK,sBAAsB,KAAK,QAClC,OAAO,oBAAoB;EAC7B,IAAI,KAAK,mBAAmB,KAAK,KAAK,OAAO,oBAAoB;EAEjE,OAAO,oBAAoB;CAC7B;CAEA,IAAI,KAAK,kBAAkB,OAAO,oBAAoB;CACtD,IAAI,KAAK,uBAAuB,OAAO,oBAAoB;CAC3D,IAAI,KAAK,mBAAmB,OAAO,oBAAoB;CACvD,IAAI,KAAK,SAAS,KAAK,mBAAmB,OAAO,oBAAoB;CAGrE,IAAI,KAAK,2BACP,OAAO,oBAAoB;CAE7B,IAAI,KAAK,2BACP,OAAO,oBAAoB;CAE7B,IAAI,KAAK,oBAAoB;EAC3B,IAAI,KAAK,eAAe,KAAK,2BAC3B,OAAO,oBAAoB;EAE7B,OAAO,oBAAoB;CAC7B;CAGA,MAAM,qBAAqB,KAAK;CAChC,IACE,OAAO,uBAAuB,aAC7B,KAAK,8BAA8B,UAAU,oBAAoB,CAAC,IAEnE,OAAO,oBAAoB;CAI7B,IAAI,KAAK,MAAM;EACb,IAAI,KAAK,KAAK,OAAO,oBAAoB;EACzC,IAAI,KAAK,aAAa,OAAO,oBAAoB;EACjD,IAAI,KAAK,QAAQ,OAAO,oBAAoB;EAC5C,IAAI,KAAK,QAAQ,OAAO,oBAAoB;EAC5C,IAAI,KAAK,KAAK,OAAO,oBAAoB;EACzC,IAAI,KAAK,qBAAqB,OAAO,oBAAoB;EAGzD,OAAO,oBAAoB;CAC7B;CAGA,IAAI,KAAK,kBAAkB,OAAO,oBAAoB;CACtD,IAAI,KAAK,kBAAkB;EACzB,MAAM,UAAU,KAAK;EACrB,IAAI,UAAU,SAAS,EAAE,GACvB,OAAO,oBAAoB;EAE7B,OAAO,oBAAoB;CAC7B;CACA,IAAI,KAAK,KAAK,OAAO,oBAAoB;CACzC,IAAI,KAAK,qBAAqB,OAAO,oBAAoB;CACzD,IAAI,KAAK,QAAQ,KAAK,aAAa,OAAO,oBAAoB;CAC9D,IAAI,KAAK,aAAa,KAAK,uBAAuB,KAAK,oBACrD,OAAO,oBAAoB;CAK7B,IAAI,KAAK,iBAAiB,OAAO,oBAAoB;CACrD,IAAI,KAAK,mBAAmB,OAAO,oBAAoB;CACvD,IAAI,KAAK,QAAQ,OAAO,oBAAoB;CAC5C,IAAI,KAAK,MAAM,OAAO,oBAAoB;CAC1C,IAAI,KAAK,SAAS,OAAO,oBAAoB;CAC7C,IAAI,KAAK,SAAS,OAAO,oBAAoB;CAK7C,IAAI,KAAK,cAAc,OAAO,oBAAoB;CAClD,IAAI,KAAK,oBAAoB,KAAK,SAChC,OAAO,oBAAoB;CAC7B,IAAI,KAAK,eAAe,OAAO,oBAAoB;CACnD,IAAI,KAAK,iBAAiB,OAAO,oBAAoB;CACrD,IAAI,KAAK,aAAa,OAAO,oBAAoB;CAEjD,OAAO,oBAAoB;AAC7B"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { exists, readFileFromRoot, writeFileToRoot } from "../../utils/fileSystem.mjs";
|
|
2
|
+
import { registerElysiaPlugin, registerExpressMiddleware, registerFastifyPlugin, registerHonoMiddleware, registerNestJsMiddleware } from "./transforms.mjs";
|
|
3
|
+
import * as ANSIColors from "@intlayer/config/colors";
|
|
4
|
+
import { colorize, colorizePath, logger, v, x } from "@intlayer/config/logger";
|
|
5
|
+
|
|
6
|
+
//#region src/init/frameworkSetup/backend/index.ts
|
|
7
|
+
/** Script extensions probed for a server entry file. */
|
|
8
|
+
const ENTRY_EXTENSIONS = [
|
|
9
|
+
"ts",
|
|
10
|
+
"mts",
|
|
11
|
+
"js",
|
|
12
|
+
"mjs",
|
|
13
|
+
"cjs"
|
|
14
|
+
];
|
|
15
|
+
/** Conventional server entry file names, most likely first. */
|
|
16
|
+
const DEFAULT_ENTRY_BASE_NAMES = [
|
|
17
|
+
"src/index",
|
|
18
|
+
"src/server",
|
|
19
|
+
"src/app",
|
|
20
|
+
"src/main",
|
|
21
|
+
"index",
|
|
22
|
+
"server",
|
|
23
|
+
"app",
|
|
24
|
+
"main"
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Lists the candidate server entry files: the `package.json` `main` field when
|
|
28
|
+
* it points at source (not a build output), then the conventional names.
|
|
29
|
+
*/
|
|
30
|
+
const getEntryCandidates = async (rootDir, entryBaseNames) => {
|
|
31
|
+
const candidates = [];
|
|
32
|
+
try {
|
|
33
|
+
const { main } = JSON.parse(await readFileFromRoot(rootDir, "package.json"));
|
|
34
|
+
if (typeof main === "string" && !/^(\.\/)?(dist|build|out)\//.test(main)) candidates.push(main.replace(/^\.\//, ""));
|
|
35
|
+
} catch {}
|
|
36
|
+
for (const baseName of entryBaseNames) for (const extension of ENTRY_EXTENSIONS) candidates.push(`${baseName}.${extension}`);
|
|
37
|
+
return [...new Set(candidates)];
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Registers the middleware in the first candidate entry file the transform
|
|
41
|
+
* recognizes. Files the transform cannot confidently edit are left untouched;
|
|
42
|
+
* when none matches, guidance is logged instead.
|
|
43
|
+
*/
|
|
44
|
+
const registerBackendMiddleware = async (rootDir, integration) => {
|
|
45
|
+
logger(colorize(`Setting up ${integration.name} integration...`, ANSIColors.CYAN));
|
|
46
|
+
const candidates = await getEntryCandidates(rootDir, integration.entryBaseNames);
|
|
47
|
+
for (const candidate of candidates) {
|
|
48
|
+
if (!await exists(rootDir, candidate)) continue;
|
|
49
|
+
const code = await readFileFromRoot(rootDir, candidate);
|
|
50
|
+
let result;
|
|
51
|
+
try {
|
|
52
|
+
result = integration.transform(code);
|
|
53
|
+
} catch {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (result.status === "already") {
|
|
57
|
+
logger(`${v} ${colorizePath(candidate)} already registers the Intlayer middleware`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (result.status === "registered") {
|
|
61
|
+
await writeFileToRoot(rootDir, candidate, result.code);
|
|
62
|
+
logger(`${v} Registered ${colorize(integration.registrationHint, ANSIColors.MAGENTA)} in ${colorizePath(candidate)}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
logger(`${x} Could not find where your ${integration.name} app is created — add ${colorize(integration.registrationHint, ANSIColors.MAGENTA)} manually: ${colorizePath(integration.documentationUrl)}`, { level: "warn" });
|
|
67
|
+
};
|
|
68
|
+
/** Wraps a backend integration into a framework adapter. */
|
|
69
|
+
const createBackendAdapter = (integration) => ({
|
|
70
|
+
name: integration.name,
|
|
71
|
+
detect: ({ allDeps }) => integration.detect(allDeps),
|
|
72
|
+
setup: ({ rootDir }) => registerBackendMiddleware(rootDir, integration)
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* NestJS on the Express platform. Checked before Express: a Nest app is
|
|
76
|
+
* created by `NestFactory`, not `express()`. Nest on Fastify is left to the
|
|
77
|
+
* guide (its adapter is registered through the Fastify instance).
|
|
78
|
+
*/
|
|
79
|
+
const nestJsAdapter = createBackendAdapter({
|
|
80
|
+
name: "NestJS",
|
|
81
|
+
detect: (allDeps) => Boolean(allDeps["@nestjs/core"]) && !allDeps["@nestjs/platform-fastify"],
|
|
82
|
+
entryBaseNames: ["src/main", "main"],
|
|
83
|
+
transform: registerNestJsMiddleware,
|
|
84
|
+
registrationHint: "app.use(intlayer())",
|
|
85
|
+
documentationUrl: "https://intlayer.org/doc/environment/nest.md"
|
|
86
|
+
});
|
|
87
|
+
const expressAdapter = createBackendAdapter({
|
|
88
|
+
name: "Express",
|
|
89
|
+
detect: (allDeps) => Boolean(allDeps.express),
|
|
90
|
+
entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,
|
|
91
|
+
transform: registerExpressMiddleware,
|
|
92
|
+
registrationHint: "app.use(intlayer())",
|
|
93
|
+
documentationUrl: "https://intlayer.org/doc/environment/express.md"
|
|
94
|
+
});
|
|
95
|
+
const fastifyAdapter = createBackendAdapter({
|
|
96
|
+
name: "Fastify",
|
|
97
|
+
detect: (allDeps) => Boolean(allDeps.fastify),
|
|
98
|
+
entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,
|
|
99
|
+
transform: registerFastifyPlugin,
|
|
100
|
+
registrationHint: "fastify.register(intlayer)",
|
|
101
|
+
documentationUrl: "https://intlayer.org/doc/environment/fastify.md"
|
|
102
|
+
});
|
|
103
|
+
const honoAdapter = createBackendAdapter({
|
|
104
|
+
name: "Hono",
|
|
105
|
+
detect: (allDeps) => Boolean(allDeps.hono),
|
|
106
|
+
entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,
|
|
107
|
+
transform: registerHonoMiddleware,
|
|
108
|
+
registrationHint: "app.use(\"*\", intlayer())",
|
|
109
|
+
documentationUrl: "https://intlayer.org/doc/environment/hono.md"
|
|
110
|
+
});
|
|
111
|
+
const elysiaAdapter = createBackendAdapter({
|
|
112
|
+
name: "Elysia",
|
|
113
|
+
detect: (allDeps) => Boolean(allDeps.elysia),
|
|
114
|
+
entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,
|
|
115
|
+
transform: registerElysiaPlugin,
|
|
116
|
+
registrationHint: "new Elysia().use(intlayer())",
|
|
117
|
+
documentationUrl: "https://intlayer.org/doc/environment/elysia.md"
|
|
118
|
+
});
|
|
119
|
+
/** Backend adapters, in detection order. */
|
|
120
|
+
const backendAdapters = [
|
|
121
|
+
nestJsAdapter,
|
|
122
|
+
expressAdapter,
|
|
123
|
+
fastifyAdapter,
|
|
124
|
+
honoAdapter,
|
|
125
|
+
elysiaAdapter
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
//#endregion
|
|
129
|
+
export { backendAdapters, elysiaAdapter, expressAdapter, fastifyAdapter, honoAdapter, nestJsAdapter };
|
|
130
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../../../src/init/frameworkSetup/backend/index.ts"],"sourcesContent":["import * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport type { FrameworkAdapter } from '../types';\nimport {\n type BackendTransformResult,\n registerElysiaPlugin,\n registerExpressMiddleware,\n registerFastifyPlugin,\n registerHonoMiddleware,\n registerNestJsMiddleware,\n} from './transforms';\n\n/** Script extensions probed for a server entry file. */\nconst ENTRY_EXTENSIONS = ['ts', 'mts', 'js', 'mjs', 'cjs'] as const;\n\n/** Conventional server entry file names, most likely first. */\nconst DEFAULT_ENTRY_BASE_NAMES = [\n 'src/index',\n 'src/server',\n 'src/app',\n 'src/main',\n 'index',\n 'server',\n 'app',\n 'main',\n] as const;\n\n/**\n * Lists the candidate server entry files: the `package.json` `main` field when\n * it points at source (not a build output), then the conventional names.\n */\nconst getEntryCandidates = async (\n rootDir: string,\n entryBaseNames: readonly string[]\n): Promise<string[]> => {\n const candidates: string[] = [];\n\n try {\n const { main } = JSON.parse(\n await readFileFromRoot(rootDir, 'package.json')\n );\n const isSourceEntry =\n typeof main === 'string' && !/^(\\.\\/)?(dist|build|out)\\//.test(main);\n if (isSourceEntry) candidates.push(main.replace(/^\\.\\//, ''));\n } catch {\n // No readable package.json — rely on the conventional names.\n }\n\n for (const baseName of entryBaseNames) {\n for (const extension of ENTRY_EXTENSIONS) {\n candidates.push(`${baseName}.${extension}`);\n }\n }\n\n return [...new Set(candidates)];\n};\n\n/** A server framework whose Intlayer middleware can be registered by init. */\ntype BackendIntegration = {\n /** Human-readable framework name, used in logs. */\n name: string;\n /** Returns true when the project uses this framework. */\n detect: (allDeps: Record<string, string>) => boolean;\n /** Entry file base names to probe, in order. */\n entryBaseNames: readonly string[];\n /** Registers the middleware in an entry file's source. */\n transform: (code: string) => BackendTransformResult;\n /** How the registration reads, shown in logs and manual-setup guidance. */\n registrationHint: string;\n /** Guide for a manual setup. */\n documentationUrl: string;\n};\n\n/**\n * Registers the middleware in the first candidate entry file the transform\n * recognizes. Files the transform cannot confidently edit are left untouched;\n * when none matches, guidance is logged instead.\n */\nconst registerBackendMiddleware = async (\n rootDir: string,\n integration: BackendIntegration\n): Promise<void> => {\n logger(\n colorize(`Setting up ${integration.name} integration...`, ANSIColors.CYAN)\n );\n\n const candidates = await getEntryCandidates(\n rootDir,\n integration.entryBaseNames\n );\n\n for (const candidate of candidates) {\n if (!(await exists(rootDir, candidate))) continue;\n\n const code = await readFileFromRoot(rootDir, candidate);\n\n let result: BackendTransformResult;\n try {\n result = integration.transform(code);\n } catch {\n // Unparsable file — try the next candidate.\n continue;\n }\n\n if (result.status === 'already') {\n logger(\n `${v} ${colorizePath(candidate)} already registers the Intlayer middleware`\n );\n return;\n }\n\n if (result.status === 'registered') {\n await writeFileToRoot(rootDir, candidate, result.code);\n logger(\n `${v} Registered ${colorize(integration.registrationHint, ANSIColors.MAGENTA)} in ${colorizePath(candidate)}`\n );\n return;\n }\n }\n\n logger(\n `${x} Could not find where your ${integration.name} app is created — add ${colorize(integration.registrationHint, ANSIColors.MAGENTA)} manually: ${colorizePath(integration.documentationUrl)}`,\n { level: 'warn' }\n );\n};\n\n/** Wraps a backend integration into a framework adapter. */\nconst createBackendAdapter = (\n integration: BackendIntegration\n): FrameworkAdapter => ({\n name: integration.name,\n detect: ({ allDeps }) => integration.detect(allDeps),\n setup: ({ rootDir }) => registerBackendMiddleware(rootDir, integration),\n});\n\n/**\n * NestJS on the Express platform. Checked before Express: a Nest app is\n * created by `NestFactory`, not `express()`. Nest on Fastify is left to the\n * guide (its adapter is registered through the Fastify instance).\n */\nexport const nestJsAdapter = createBackendAdapter({\n name: 'NestJS',\n detect: (allDeps) =>\n Boolean(allDeps['@nestjs/core']) && !allDeps['@nestjs/platform-fastify'],\n entryBaseNames: ['src/main', 'main'],\n transform: registerNestJsMiddleware,\n registrationHint: 'app.use(intlayer())',\n documentationUrl: 'https://intlayer.org/doc/environment/nest.md',\n});\n\nexport const expressAdapter = createBackendAdapter({\n name: 'Express',\n detect: (allDeps) => Boolean(allDeps.express),\n entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,\n transform: registerExpressMiddleware,\n registrationHint: 'app.use(intlayer())',\n documentationUrl: 'https://intlayer.org/doc/environment/express.md',\n});\n\nexport const fastifyAdapter = createBackendAdapter({\n name: 'Fastify',\n detect: (allDeps) => Boolean(allDeps.fastify),\n entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,\n transform: registerFastifyPlugin,\n registrationHint: 'fastify.register(intlayer)',\n documentationUrl: 'https://intlayer.org/doc/environment/fastify.md',\n});\n\nexport const honoAdapter = createBackendAdapter({\n name: 'Hono',\n detect: (allDeps) => Boolean(allDeps.hono),\n entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,\n transform: registerHonoMiddleware,\n registrationHint: 'app.use(\"*\", intlayer())',\n documentationUrl: 'https://intlayer.org/doc/environment/hono.md',\n});\n\nexport const elysiaAdapter = createBackendAdapter({\n name: 'Elysia',\n detect: (allDeps) => Boolean(allDeps.elysia),\n entryBaseNames: DEFAULT_ENTRY_BASE_NAMES,\n transform: registerElysiaPlugin,\n registrationHint: 'new Elysia().use(intlayer())',\n documentationUrl: 'https://intlayer.org/doc/environment/elysia.md',\n});\n\n/** Backend adapters, in detection order. */\nexport const backendAdapters: FrameworkAdapter[] = [\n nestJsAdapter,\n expressAdapter,\n fastifyAdapter,\n honoAdapter,\n elysiaAdapter,\n];\n"],"mappings":";;;;;;;AAkBA,MAAM,mBAAmB;CAAC;CAAM;CAAO;CAAM;CAAO;AAAK;;AAGzD,MAAM,2BAA2B;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;;;;;AAMA,MAAM,qBAAqB,OACzB,SACA,mBACsB;CACtB,MAAM,aAAuB,CAAC;CAE9B,IAAI;EACF,MAAM,EAAE,SAAS,KAAK,MACpB,MAAM,iBAAiB,SAAS,cAAc,CAChD;EAGA,IADE,OAAO,SAAS,YAAY,CAAC,6BAA6B,KAAK,IAAI,GAClD,WAAW,KAAK,KAAK,QAAQ,SAAS,EAAE,CAAC;CAC9D,QAAQ,CAER;CAEA,KAAK,MAAM,YAAY,gBACrB,KAAK,MAAM,aAAa,kBACtB,WAAW,KAAK,GAAG,SAAS,GAAG,WAAW;CAI9C,OAAO,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC;AAChC;;;;;;AAuBA,MAAM,4BAA4B,OAChC,SACA,gBACkB;CAClB,OACE,SAAS,cAAc,YAAY,KAAK,kBAAkB,WAAW,IAAI,CAC3E;CAEA,MAAM,aAAa,MAAM,mBACvB,SACA,YAAY,cACd;CAEA,KAAK,MAAM,aAAa,YAAY;EAClC,IAAI,CAAE,MAAM,OAAO,SAAS,SAAS,GAAI;EAEzC,MAAM,OAAO,MAAM,iBAAiB,SAAS,SAAS;EAEtD,IAAI;EACJ,IAAI;GACF,SAAS,YAAY,UAAU,IAAI;EACrC,QAAQ;GAEN;EACF;EAEA,IAAI,OAAO,WAAW,WAAW;GAC/B,OACE,GAAG,EAAE,GAAG,aAAa,SAAS,EAAE,2CAClC;GACA;EACF;EAEA,IAAI,OAAO,WAAW,cAAc;GAClC,MAAM,gBAAgB,SAAS,WAAW,OAAO,IAAI;GACrD,OACE,GAAG,EAAE,cAAc,SAAS,YAAY,kBAAkB,WAAW,OAAO,EAAE,MAAM,aAAa,SAAS,GAC5G;GACA;EACF;CACF;CAEA,OACE,GAAG,EAAE,6BAA6B,YAAY,KAAK,wBAAwB,SAAS,YAAY,kBAAkB,WAAW,OAAO,EAAE,aAAa,aAAa,YAAY,gBAAgB,KAC5L,EAAE,OAAO,OAAO,CAClB;AACF;;AAGA,MAAM,wBACJ,iBACsB;CACtB,MAAM,YAAY;CAClB,SAAS,EAAE,cAAc,YAAY,OAAO,OAAO;CACnD,QAAQ,EAAE,cAAc,0BAA0B,SAAS,WAAW;AACxE;;;;;;AAOA,MAAa,gBAAgB,qBAAqB;CAChD,MAAM;CACN,SAAS,YACP,QAAQ,QAAQ,eAAe,KAAK,CAAC,QAAQ;CAC/C,gBAAgB,CAAC,YAAY,MAAM;CACnC,WAAW;CACX,kBAAkB;CAClB,kBAAkB;AACpB,CAAC;AAED,MAAa,iBAAiB,qBAAqB;CACjD,MAAM;CACN,SAAS,YAAY,QAAQ,QAAQ,OAAO;CAC5C,gBAAgB;CAChB,WAAW;CACX,kBAAkB;CAClB,kBAAkB;AACpB,CAAC;AAED,MAAa,iBAAiB,qBAAqB;CACjD,MAAM;CACN,SAAS,YAAY,QAAQ,QAAQ,OAAO;CAC5C,gBAAgB;CAChB,WAAW;CACX,kBAAkB;CAClB,kBAAkB;AACpB,CAAC;AAED,MAAa,cAAc,qBAAqB;CAC9C,MAAM;CACN,SAAS,YAAY,QAAQ,QAAQ,IAAI;CACzC,gBAAgB;CAChB,WAAW;CACX,kBAAkB;CAClB,kBAAkB;AACpB,CAAC;AAED,MAAa,gBAAgB,qBAAqB;CAChD,MAAM;CACN,SAAS,YAAY,QAAQ,QAAQ,MAAM;CAC3C,gBAAgB;CAChB,WAAW;CACX,kBAAkB;CAClB,kBAAkB;AACpB,CAAC;;AAGD,MAAa,kBAAsC;CACjD;CACA;CACA;CACA;CACA;AACF"}
|