@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
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
//#region src/init/frameworkSetup/localeRouting.ts
|
|
3
|
+
/**
|
|
4
|
+
* Whether the locale is carried by a URL path segment (`/fr/about`), which the
|
|
5
|
+
* framework router must declare (`[locale]`, `{-$locale}`, `$locale`…). Only the
|
|
6
|
+
* prefix routing modes do, and only while the proxy is enabled: `no-prefix` and
|
|
7
|
+
* `search-params` resolve the locale from storage/headers/query instead.
|
|
8
|
+
*/
|
|
9
|
+
const usesLocalePathSegment = ({ routingMode, enableProxy }) => enableProxy && (routingMode === "prefix-all" || routingMode === "prefix-no-default");
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
exports.usesLocalePathSegment = usesLocalePathSegment;
|
|
13
|
+
//# sourceMappingURL=localeRouting.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"localeRouting.cjs","names":[],"sources":["../../../../src/init/frameworkSetup/localeRouting.ts"],"sourcesContent":["import type { FrameworkSetupContext } from './types';\n\n/**\n * Whether the locale is carried by a URL path segment (`/fr/about`), which the\n * framework router must declare (`[locale]`, `{-$locale}`, `$locale`…). Only the\n * prefix routing modes do, and only while the proxy is enabled: `no-prefix` and\n * `search-params` resolve the locale from storage/headers/query instead.\n */\nexport const usesLocalePathSegment = ({\n routingMode,\n enableProxy,\n}: Pick<FrameworkSetupContext, 'routingMode' | 'enableProxy'>): boolean =>\n enableProxy &&\n (routingMode === 'prefix-all' || routingMode === 'prefix-no-default');\n"],"mappings":";;;;;;;;AAQA,MAAa,yBAAyB,EACpC,aACA,kBAEA,gBACC,gBAAgB,gBAAgB,gBAAgB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_init_utils_fileSystem = require('../../utils/fileSystem.cjs');
|
|
4
|
+
const require_init_frameworkSetup_localeRouting = require('../localeRouting.cjs');
|
|
4
5
|
const require_init_utils_version = require('../../utils/version.cjs');
|
|
5
6
|
const require_init_frameworkSetup_nextAppRouter_detect = require('./detect.cjs');
|
|
6
7
|
const require_init_frameworkSetup_nextAppRouter_restructure = require('./restructure.cjs');
|
|
@@ -10,6 +11,7 @@ let node_path = require("node:path");
|
|
|
10
11
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
11
12
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
12
13
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
14
|
+
let node_fs_promises = require("node:fs/promises");
|
|
13
15
|
|
|
14
16
|
//#region src/init/frameworkSetup/nextAppRouter/index.ts
|
|
15
17
|
/**
|
|
@@ -64,11 +66,29 @@ const createIfMissing = async (rootDir, filePath, content, description) => {
|
|
|
64
66
|
return true;
|
|
65
67
|
};
|
|
66
68
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
|
|
69
|
+
* Wires an app whose URLs carry no locale segment (`no-prefix`,
|
|
70
|
+
* `search-params`, or no proxy): routes stay at the app root and the root
|
|
71
|
+
* layout provides the locale resolved by `getLocale()`. An app already nested
|
|
72
|
+
* under a locale segment is left untouched, with guidance.
|
|
73
|
+
*/
|
|
74
|
+
const setupUnprefixedApp = async (rootDir, appDir, useTypeScript) => {
|
|
75
|
+
const scriptExtension = useTypeScript ? "tsx" : "jsx";
|
|
76
|
+
const existingLocaleSegment = (await (0, node_fs_promises.readdir)((0, node_path.join)(rootDir, appDir))).find(require_init_frameworkSetup_nextAppRouter_restructure.isLocaleSegment);
|
|
77
|
+
if (existingLocaleSegment) {
|
|
78
|
+
(0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.x} Routes live under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(appDir, existingLocaleSegment))} but the chosen routing has no locale in the URL — move them back to ${(0, _intlayer_config_logger.colorizePath)(appDir)} manually.`, { level: "warn" });
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const existingLayout = await require_init_frameworkSetup_nextAppRouter_detect.findAppFile(rootDir, appDir, "layout");
|
|
82
|
+
if (existingLayout) await transformExistingFile(rootDir, existingLayout, (code) => require_init_frameworkSetup_nextAppRouter_transforms.wrapLayoutWithProvider(code, { exportStaticParams: false }));
|
|
83
|
+
else await createIfMissing(rootDir, (0, node_path.join)(appDir, `layout.${scriptExtension}`), useTypeScript ? require_init_frameworkSetup_nextAppRouter_templates.UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS : require_init_frameworkSetup_nextAppRouter_templates.UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS, "root layout");
|
|
84
|
+
if (!await require_init_frameworkSetup_nextAppRouter_detect.findAppFile(rootDir, appDir, "page")) await createIfMissing(rootDir, (0, node_path.join)(appDir, `page.${scriptExtension}`), require_init_frameworkSetup_nextAppRouter_templates.UNPREFIXED_PAGE_TEMPLATE, "page");
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Next.js App Router adapter. Scaffolds the locale proxy/middleware (when the
|
|
88
|
+
* proxy is enabled), restructures the app into a `[locale]` segment (prefix
|
|
89
|
+
* routing modes only), and wraps the layout with the unified Intlayer provider
|
|
90
|
+
* — all idempotently and without overwriting recognizable user code. Pages are
|
|
91
|
+
* never wrapped: `IntlayerProvider` in the layout covers them.
|
|
72
92
|
*/
|
|
73
93
|
const nextAppRouterAdapter = {
|
|
74
94
|
name: "Next.js App Router",
|
|
@@ -76,14 +96,21 @@ const nextAppRouterAdapter = {
|
|
|
76
96
|
if (!allDeps.next) return false;
|
|
77
97
|
return await require_init_frameworkSetup_nextAppRouter_detect.detectNextAppDir(rootDir) !== null;
|
|
78
98
|
},
|
|
79
|
-
setup: async ({ rootDir, allDeps, useTypeScript }) => {
|
|
99
|
+
setup: async ({ rootDir, allDeps, useTypeScript, routingMode, enableProxy }) => {
|
|
80
100
|
const appDirInfo = await require_init_frameworkSetup_nextAppRouter_detect.detectNextAppDir(rootDir);
|
|
81
101
|
if (!appDirInfo) return;
|
|
82
102
|
const { appDir, srcDir } = appDirInfo;
|
|
83
103
|
const isNext16 = require_init_utils_version.isVersionAtLeast(allDeps.next, 16);
|
|
84
104
|
const scriptExtension = useTypeScript ? "tsx" : "jsx";
|
|
85
105
|
(0, _intlayer_config_logger.logger)((0, _intlayer_config_logger.colorize)("Setting up Next.js App Router integration...", _intlayer_config_colors.CYAN));
|
|
86
|
-
await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);
|
|
106
|
+
if (enableProxy) await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);
|
|
107
|
+
if (!require_init_frameworkSetup_localeRouting.usesLocalePathSegment({
|
|
108
|
+
routingMode,
|
|
109
|
+
enableProxy
|
|
110
|
+
})) {
|
|
111
|
+
await setupUnprefixedApp(rootDir, appDir, useTypeScript);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
87
114
|
const restructureResult = await require_init_frameworkSetup_nextAppRouter_restructure.restructureAppIntoLocale(rootDir, appDir);
|
|
88
115
|
if (restructureResult.status === "moved") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Restructured app routes under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(appDir, "[locale]"))}: ${restructureResult.movedEntries.map((entry) => (0, _intlayer_config_logger.colorize)(entry, _intlayer_config_colors.MAGENTA)).join(", ")}`);
|
|
89
116
|
else if (restructureResult.status === "already-structured") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(appDir, restructureResult.localeSegment))} already exists, skipping restructure`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["exists","join","v","colorizePath","PROXY_TEMPLATE","MIDDLEWARE_TEMPLATE","ensureDirectory","writeFileToRoot","x","readFileFromRoot","detectNextAppDir","isVersionAtLeast","colorize","ANSIColors","restructureAppIntoLocale","ROOT_LAYOUT_TEMPLATE_TS","ROOT_LAYOUT_TEMPLATE_JS","findAppFile","wrapLayoutWithProvider","LOCALE_LAYOUT_TEMPLATE_TS","LOCALE_LAYOUT_TEMPLATE_JS","LOCALE_PAGE_TEMPLATE_TS","LOCALE_PAGE_TEMPLATE_JS"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectNextAppDir, findAppFile, isVersionAtLeast } from './detect';\nimport { restructureAppIntoLocale } from './restructure';\nimport {\n LOCALE_LAYOUT_TEMPLATE_JS,\n LOCALE_LAYOUT_TEMPLATE_TS,\n LOCALE_PAGE_TEMPLATE_JS,\n LOCALE_PAGE_TEMPLATE_TS,\n MIDDLEWARE_TEMPLATE,\n PROXY_TEMPLATE,\n ROOT_LAYOUT_TEMPLATE_JS,\n ROOT_LAYOUT_TEMPLATE_TS,\n} from './templates';\nimport { type TransformResult, wrapLayoutWithProvider } from './transforms';\n\n/**\n * Creates the locale-detection proxy (Next >= 16) or middleware (Next < 16),\n * but only when neither already exists, so a user's custom file is never\n * touched. Placed next to the app directory's parent (`src/` when present).\n */\nconst ensureProxyOrMiddleware = async (\n rootDir: string,\n srcDir: string,\n isNext16: boolean\n): Promise<void> => {\n const baseDir = srcDir || '.';\n const proxyCandidates = [\n 'proxy.ts',\n 'proxy.js',\n 'middleware.ts',\n 'middleware.js',\n ];\n\n for (const candidate of proxyCandidates) {\n if (await exists(rootDir, join(baseDir, candidate))) {\n logger(\n `${v} ${colorizePath(join(baseDir, candidate))} already exists, leaving it untouched`\n );\n return;\n }\n }\n\n const fileName = isNext16 ? 'proxy.ts' : 'middleware.ts';\n const content = isNext16 ? PROXY_TEMPLATE : MIDDLEWARE_TEMPLATE;\n const targetPath = join(baseDir, fileName);\n\n if (srcDir) await ensureDirectory(rootDir, srcDir);\n await writeFileToRoot(rootDir, targetPath, content);\n logger(`${v} Created ${colorizePath(targetPath)} for locale detection`);\n};\n\n/** Logs the outcome of a layout provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped-client':\n logger(\n `${x} ${colorizePath(filePath)} is a client component — add the Intlayer provider manually.`,\n { level: 'warn' }\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wire it manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * Next.js App Router adapter. Scaffolds the locale proxy/middleware, restructures\n * the app into a `[locale]` segment, and wraps the layout with the unified\n * Intlayer provider — all idempotently and without overwriting recognizable\n * user code. Pages are never wrapped: `IntlayerProvider` in the locale layout\n * covers them.\n */\nexport const nextAppRouterAdapter: FrameworkAdapter = {\n name: 'Next.js App Router',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!allDeps.next) return false;\n return (await detectNextAppDir(rootDir)) !== null;\n },\n\n setup: async ({ rootDir, allDeps, useTypeScript }: FrameworkSetupContext) => {\n const appDirInfo = await detectNextAppDir(rootDir);\n if (!appDirInfo) return;\n\n const { appDir, srcDir } = appDirInfo;\n const isNext16 = isVersionAtLeast(allDeps.next, 16);\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n logger(\n colorize('Setting up Next.js App Router integration...', ANSIColors.CYAN)\n );\n\n // 1. Locale detection proxy / middleware (create only when absent).\n await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);\n\n // 2. Move routable files under a `[locale]` segment (idempotent).\n const restructureResult = await restructureAppIntoLocale(rootDir, appDir);\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured app routes under ${colorizePath(join(appDir, '[locale]'))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(appDir, restructureResult.localeSegment))} already exists, skipping restructure`\n );\n }\n\n // When the app already uses a different locale-prefix scheme (e.g. an\n // `[...locale]` / `[[...locale]]` catch-all), respect the user's routing:\n // don't scaffold a second, conflicting `[locale]` segment.\n if (\n restructureResult.status === 'already-structured' &&\n restructureResult.localeSegment !== '[locale]'\n ) {\n logger(\n `${v} Detected existing locale routing (${colorize(restructureResult.localeSegment, ANSIColors.MAGENTA)}), skipping locale layout/page scaffold`\n );\n return;\n }\n\n const localeDir = join(appDir, '[locale]');\n await ensureDirectory(rootDir, localeDir);\n\n // 3. Minimal pass-through root layout (the `[locale]` layout owns `<html>`).\n await createIfMissing(\n rootDir,\n join(appDir, `layout.${scriptExtension}`),\n useTypeScript ? ROOT_LAYOUT_TEMPLATE_TS : ROOT_LAYOUT_TEMPLATE_JS,\n 'root layout'\n );\n\n // 4. Locale layout — transform an existing one, else scaffold from template.\n const existingLayout = await findAppFile(rootDir, localeDir, 'layout');\n if (existingLayout) {\n await transformExistingFile(\n rootDir,\n existingLayout,\n wrapLayoutWithProvider\n );\n } else {\n await createIfMissing(\n rootDir,\n join(localeDir, `layout.${scriptExtension}`),\n useTypeScript ? LOCALE_LAYOUT_TEMPLATE_TS : LOCALE_LAYOUT_TEMPLATE_JS,\n 'locale layout'\n );\n }\n\n // 5. Locale page — only scaffolded when absent. An existing page needs no\n // transform: the locale layout's `IntlayerProvider` already covers it.\n const existingPage = await findAppFile(rootDir, localeDir, 'page');\n if (!existingPage) {\n await createIfMissing(\n rootDir,\n join(localeDir, `page.${scriptExtension}`),\n useTypeScript ? LOCALE_PAGE_TEMPLATE_TS : LOCALE_PAGE_TEMPLATE_JS,\n 'locale page'\n );\n }\n },\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["exists","join","v","colorizePath","PROXY_TEMPLATE","MIDDLEWARE_TEMPLATE","ensureDirectory","writeFileToRoot","x","readFileFromRoot","readdir","isLocaleSegment","findAppFile","wrapLayoutWithProvider","UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS","UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS","UNPREFIXED_PAGE_TEMPLATE","detectNextAppDir","isVersionAtLeast","colorize","ANSIColors","usesLocalePathSegment","restructureAppIntoLocale","ROOT_LAYOUT_TEMPLATE_TS","ROOT_LAYOUT_TEMPLATE_JS","LOCALE_LAYOUT_TEMPLATE_TS","LOCALE_LAYOUT_TEMPLATE_JS","LOCALE_PAGE_TEMPLATE_TS","LOCALE_PAGE_TEMPLATE_JS"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/index.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport { usesLocalePathSegment } from '../localeRouting';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectNextAppDir, findAppFile, isVersionAtLeast } from './detect';\nimport { isLocaleSegment, restructureAppIntoLocale } from './restructure';\nimport {\n LOCALE_LAYOUT_TEMPLATE_JS,\n LOCALE_LAYOUT_TEMPLATE_TS,\n LOCALE_PAGE_TEMPLATE_JS,\n LOCALE_PAGE_TEMPLATE_TS,\n MIDDLEWARE_TEMPLATE,\n PROXY_TEMPLATE,\n ROOT_LAYOUT_TEMPLATE_JS,\n ROOT_LAYOUT_TEMPLATE_TS,\n UNPREFIXED_PAGE_TEMPLATE,\n UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS,\n UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS,\n} from './templates';\nimport { type TransformResult, wrapLayoutWithProvider } from './transforms';\n\n/**\n * Creates the locale-detection proxy (Next >= 16) or middleware (Next < 16),\n * but only when neither already exists, so a user's custom file is never\n * touched. Placed next to the app directory's parent (`src/` when present).\n */\nconst ensureProxyOrMiddleware = async (\n rootDir: string,\n srcDir: string,\n isNext16: boolean\n): Promise<void> => {\n const baseDir = srcDir || '.';\n const proxyCandidates = [\n 'proxy.ts',\n 'proxy.js',\n 'middleware.ts',\n 'middleware.js',\n ];\n\n for (const candidate of proxyCandidates) {\n if (await exists(rootDir, join(baseDir, candidate))) {\n logger(\n `${v} ${colorizePath(join(baseDir, candidate))} already exists, leaving it untouched`\n );\n return;\n }\n }\n\n const fileName = isNext16 ? 'proxy.ts' : 'middleware.ts';\n const content = isNext16 ? PROXY_TEMPLATE : MIDDLEWARE_TEMPLATE;\n const targetPath = join(baseDir, fileName);\n\n if (srcDir) await ensureDirectory(rootDir, srcDir);\n await writeFileToRoot(rootDir, targetPath, content);\n logger(`${v} Created ${colorizePath(targetPath)} for locale detection`);\n};\n\n/** Logs the outcome of a layout provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped-client':\n logger(\n `${x} ${colorizePath(filePath)} is a client component — add the Intlayer provider manually.`,\n { level: 'warn' }\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wire it manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * Wires an app whose URLs carry no locale segment (`no-prefix`,\n * `search-params`, or no proxy): routes stay at the app root and the root\n * layout provides the locale resolved by `getLocale()`. An app already nested\n * under a locale segment is left untouched, with guidance.\n */\nconst setupUnprefixedApp = async (\n rootDir: string,\n appDir: string,\n useTypeScript: boolean\n): Promise<void> => {\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n const entries = await readdir(join(rootDir, appDir));\n const existingLocaleSegment = entries.find(isLocaleSegment);\n if (existingLocaleSegment) {\n logger(\n `${x} Routes live under ${colorizePath(join(appDir, existingLocaleSegment))} but the chosen routing has no locale in the URL — move them back to ${colorizePath(appDir)} manually.`,\n { level: 'warn' }\n );\n return;\n }\n\n const existingLayout = await findAppFile(rootDir, appDir, 'layout');\n if (existingLayout) {\n await transformExistingFile(rootDir, existingLayout, (code) =>\n wrapLayoutWithProvider(code, { exportStaticParams: false })\n );\n } else {\n await createIfMissing(\n rootDir,\n join(appDir, `layout.${scriptExtension}`),\n useTypeScript\n ? UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS\n : UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS,\n 'root layout'\n );\n }\n\n if (!(await findAppFile(rootDir, appDir, 'page'))) {\n await createIfMissing(\n rootDir,\n join(appDir, `page.${scriptExtension}`),\n UNPREFIXED_PAGE_TEMPLATE,\n 'page'\n );\n }\n};\n\n/**\n * Next.js App Router adapter. Scaffolds the locale proxy/middleware (when the\n * proxy is enabled), restructures the app into a `[locale]` segment (prefix\n * routing modes only), and wraps the layout with the unified Intlayer provider\n * — all idempotently and without overwriting recognizable user code. Pages are\n * never wrapped: `IntlayerProvider` in the layout covers them.\n */\nexport const nextAppRouterAdapter: FrameworkAdapter = {\n name: 'Next.js App Router',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!allDeps.next) return false;\n return (await detectNextAppDir(rootDir)) !== null;\n },\n\n setup: async ({\n rootDir,\n allDeps,\n useTypeScript,\n routingMode,\n enableProxy,\n }: FrameworkSetupContext) => {\n const appDirInfo = await detectNextAppDir(rootDir);\n if (!appDirInfo) return;\n\n const { appDir, srcDir } = appDirInfo;\n const isNext16 = isVersionAtLeast(allDeps.next, 16);\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n logger(\n colorize('Setting up Next.js App Router integration...', ANSIColors.CYAN)\n );\n\n // 1. Locale detection proxy / middleware (create only when absent).\n if (enableProxy) {\n await ensureProxyOrMiddleware(rootDir, srcDir, isNext16);\n }\n\n // Without a locale path segment, routes stay where they are.\n if (!usesLocalePathSegment({ routingMode, enableProxy })) {\n await setupUnprefixedApp(rootDir, appDir, useTypeScript);\n return;\n }\n\n // 2. Move routable files under a `[locale]` segment (idempotent).\n const restructureResult = await restructureAppIntoLocale(rootDir, appDir);\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured app routes under ${colorizePath(join(appDir, '[locale]'))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(appDir, restructureResult.localeSegment))} already exists, skipping restructure`\n );\n }\n\n // When the app already uses a different locale-prefix scheme (e.g. an\n // `[...locale]` / `[[...locale]]` catch-all), respect the user's routing:\n // don't scaffold a second, conflicting `[locale]` segment.\n if (\n restructureResult.status === 'already-structured' &&\n restructureResult.localeSegment !== '[locale]'\n ) {\n logger(\n `${v} Detected existing locale routing (${colorize(restructureResult.localeSegment, ANSIColors.MAGENTA)}), skipping locale layout/page scaffold`\n );\n return;\n }\n\n const localeDir = join(appDir, '[locale]');\n await ensureDirectory(rootDir, localeDir);\n\n // 3. Minimal pass-through root layout (the `[locale]` layout owns `<html>`).\n await createIfMissing(\n rootDir,\n join(appDir, `layout.${scriptExtension}`),\n useTypeScript ? ROOT_LAYOUT_TEMPLATE_TS : ROOT_LAYOUT_TEMPLATE_JS,\n 'root layout'\n );\n\n // 4. Locale layout — transform an existing one, else scaffold from template.\n const existingLayout = await findAppFile(rootDir, localeDir, 'layout');\n if (existingLayout) {\n await transformExistingFile(\n rootDir,\n existingLayout,\n wrapLayoutWithProvider\n );\n } else {\n await createIfMissing(\n rootDir,\n join(localeDir, `layout.${scriptExtension}`),\n useTypeScript ? LOCALE_LAYOUT_TEMPLATE_TS : LOCALE_LAYOUT_TEMPLATE_JS,\n 'locale layout'\n );\n }\n\n // 5. Locale page — only scaffolded when absent. An existing page needs no\n // transform: the locale layout's `IntlayerProvider` already covers it.\n const existingPage = await findAppFile(rootDir, localeDir, 'page');\n if (!existingPage) {\n await createIfMissing(\n rootDir,\n join(localeDir, `page.${scriptExtension}`),\n useTypeScript ? LOCALE_PAGE_TEMPLATE_TS : LOCALE_PAGE_TEMPLATE_JS,\n 'locale page'\n );\n }\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_utils_babelParser = require('../../../utils/babelParser.cjs');
|
|
4
|
-
let node_fs_promises = require("node:fs/promises");
|
|
5
4
|
let node_path = require("node:path");
|
|
6
5
|
let fast_glob = require("fast-glob");
|
|
7
6
|
fast_glob = require_runtime.__toESM(fast_glob);
|
|
7
|
+
let node_fs_promises = require("node:fs/promises");
|
|
8
8
|
let recast = require("recast");
|
|
9
9
|
recast = require_runtime.__toESM(recast);
|
|
10
10
|
|
|
@@ -108,6 +108,59 @@ const LOCALE_PAGE_TEMPLATE_JS = `const Page = async ({ params }) => {
|
|
|
108
108
|
);
|
|
109
109
|
};
|
|
110
110
|
|
|
111
|
+
export default Page;
|
|
112
|
+
`;
|
|
113
|
+
/**
|
|
114
|
+
* Root layout (`app/layout.tsx`) for routing modes without a locale path
|
|
115
|
+
* segment (`no-prefix`, `search-params`, or no proxy at all). Owns `<html>` and
|
|
116
|
+
* resolves the locale from the request (cookie / header) via `getLocale()`.
|
|
117
|
+
*/
|
|
118
|
+
const UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS = `import type { PropsWithChildren } from "react";
|
|
119
|
+
import { getHTMLTextDir } from "intlayer";
|
|
120
|
+
import { getLocale, IntlayerProvider } from "next-intlayer/server";
|
|
121
|
+
|
|
122
|
+
const RootLayout = async ({ children }: PropsWithChildren) => {
|
|
123
|
+
const locale = await getLocale();
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
127
|
+
<body>
|
|
128
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
129
|
+
</body>
|
|
130
|
+
</html>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export default RootLayout;
|
|
135
|
+
`;
|
|
136
|
+
const UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS = `import { getHTMLTextDir } from "intlayer";
|
|
137
|
+
import { getLocale, IntlayerProvider } from "next-intlayer/server";
|
|
138
|
+
|
|
139
|
+
const RootLayout = async ({ children }) => {
|
|
140
|
+
const locale = await getLocale();
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<html lang={locale} dir={getHTMLTextDir(locale)}>
|
|
144
|
+
<body>
|
|
145
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
146
|
+
</body>
|
|
147
|
+
</html>
|
|
148
|
+
);
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
export default RootLayout;
|
|
152
|
+
`;
|
|
153
|
+
/**
|
|
154
|
+
* Home page (`app/page.tsx`) for routing modes without a locale path segment.
|
|
155
|
+
* Identical for TypeScript and JavaScript projects.
|
|
156
|
+
*/
|
|
157
|
+
const UNPREFIXED_PAGE_TEMPLATE = `const Page = () => (
|
|
158
|
+
<main>
|
|
159
|
+
<h1>Hello</h1>
|
|
160
|
+
<p>Get started by editing this page.</p>
|
|
161
|
+
</main>
|
|
162
|
+
);
|
|
163
|
+
|
|
111
164
|
export default Page;
|
|
112
165
|
`;
|
|
113
166
|
|
|
@@ -120,4 +173,7 @@ exports.MIDDLEWARE_TEMPLATE = MIDDLEWARE_TEMPLATE;
|
|
|
120
173
|
exports.PROXY_TEMPLATE = PROXY_TEMPLATE;
|
|
121
174
|
exports.ROOT_LAYOUT_TEMPLATE_JS = ROOT_LAYOUT_TEMPLATE_JS;
|
|
122
175
|
exports.ROOT_LAYOUT_TEMPLATE_TS = ROOT_LAYOUT_TEMPLATE_TS;
|
|
176
|
+
exports.UNPREFIXED_PAGE_TEMPLATE = UNPREFIXED_PAGE_TEMPLATE;
|
|
177
|
+
exports.UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS = UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS;
|
|
178
|
+
exports.UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS = UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS;
|
|
123
179
|
//# sourceMappingURL=templates.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.cjs","names":[],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/templates.ts"],"sourcesContent":["/**\n * File templates for a fresh Next.js App Router integration. These are only\n * written when the target file does not exist (or, for the locale layout/page,\n * when the app is effectively empty) — they never overwrite user code.\n */\n\n/** Next.js >= 16 locale-detection proxy (`src/proxy.ts`). */\nexport const PROXY_TEMPLATE = `export { intlayerProxy as proxy } from \"next-intlayer/proxy\";\n\nexport const config = {\n matcher:\n \"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\\\\\\\..*|_next).*)\",\n};\n`;\n\n/** Next.js < 16 locale-detection middleware (`src/middleware.ts`). */\nexport const MIDDLEWARE_TEMPLATE = `export { intlayerMiddleware as middleware } from \"next-intlayer/middleware\";\n\nexport const config = {\n matcher:\n \"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\\\\\\\..*|_next).*)\",\n};\n`;\n\n/** Minimal pass-through root layout (`app/layout.tsx`), lets `[locale]/layout` own `<html>`. */\nexport const ROOT_LAYOUT_TEMPLATE_TS = `import type { PropsWithChildren, FC } from \"react\";\n\nconst RootLayout: FC<PropsWithChildren> = ({ children }) => <>{children}</>;\n\nexport default RootLayout;\n`;\n\nexport const ROOT_LAYOUT_TEMPLATE_JS = `const RootLayout = ({ children }) => <>{children}</>;\n\nexport default RootLayout;\n`;\n\n/**\n * Locale layout (`app/[locale]/layout.tsx`) providing `<html>` + the unified\n * provider. `IntlayerProvider` seeds both the server context (read by server\n * hooks and by any page below, without per-page wrapping) and the client\n * provider in one mount.\n */\nexport const LOCALE_LAYOUT_TEMPLATE_TS = `import { type NextLayoutIntlayer } from \"next-intlayer\";\nimport { IntlayerProvider } from \"next-intlayer/server\";\nimport { getHTMLTextDir } from \"intlayer\";\n\nexport { generateStaticParams } from \"next-intlayer\";\n\nconst LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {\n const { locale } = await params;\n\n return (\n <html lang={locale} dir={getHTMLTextDir(locale)}>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n </body>\n </html>\n );\n};\n\nexport default LocaleLayout;\n`;\n\nexport const LOCALE_LAYOUT_TEMPLATE_JS = `import { IntlayerProvider } from \"next-intlayer/server\";\nimport { getHTMLTextDir } from \"intlayer\";\n\nexport { generateStaticParams } from \"next-intlayer\";\n\nconst LocaleLayout = async ({ children, params }) => {\n const { locale } = await params;\n\n return (\n <html lang={locale} dir={getHTMLTextDir(locale)}>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n </body>\n </html>\n );\n};\n\nexport default LocaleLayout;\n`;\n\n/**\n * Locale home page (`app/[locale]/page.tsx`). Self-contained starter that does\n * not depend on an example content declaration — add Intlayer content (a\n * `*.content.ts` file consumed via `useIntlayer`) as the next step.\n */\nexport const LOCALE_PAGE_TEMPLATE_TS = `import { type NextPageIntlayer } from \"next-intlayer\";\n\nconst Page: NextPageIntlayer = async ({ params }) => {\n const { locale } = await params;\n\n return (\n <main>\n <h1>{locale}</h1>\n <p>Get started by editing this page.</p>\n </main>\n );\n};\n\nexport default Page;\n`;\n\nexport const LOCALE_PAGE_TEMPLATE_JS = `const Page = async ({ params }) => {\n const { locale } = await params;\n\n return (\n <main>\n <h1>{locale}</h1>\n <p>Get started by editing this page.</p>\n </main>\n );\n};\n\nexport default Page;\n`;\n"],"mappings":";;;;;;;;AAOA,MAAa,iBAAiB;;;;;;;;AAS9B,MAAa,sBAAsB;;;;;;;;AASnC,MAAa,0BAA0B;;;;;;AAOvC,MAAa,0BAA0B;;;;;;;;;;AAWvC,MAAa,4BAA4B;;;;;;;;;;;;;;;;;;;;AAqBzC,MAAa,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;AAyBzC,MAAa,0BAA0B;;;;;;;;;;;;;;;AAgBvC,MAAa,0BAA0B"}
|
|
1
|
+
{"version":3,"file":"templates.cjs","names":[],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/templates.ts"],"sourcesContent":["/**\n * File templates for a fresh Next.js App Router integration. These are only\n * written when the target file does not exist (or, for the locale layout/page,\n * when the app is effectively empty) — they never overwrite user code.\n */\n\n/** Next.js >= 16 locale-detection proxy (`src/proxy.ts`). */\nexport const PROXY_TEMPLATE = `export { intlayerProxy as proxy } from \"next-intlayer/proxy\";\n\nexport const config = {\n matcher:\n \"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\\\\\\\..*|_next).*)\",\n};\n`;\n\n/** Next.js < 16 locale-detection middleware (`src/middleware.ts`). */\nexport const MIDDLEWARE_TEMPLATE = `export { intlayerMiddleware as middleware } from \"next-intlayer/middleware\";\n\nexport const config = {\n matcher:\n \"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\\\\\\\..*|_next).*)\",\n};\n`;\n\n/** Minimal pass-through root layout (`app/layout.tsx`), lets `[locale]/layout` own `<html>`. */\nexport const ROOT_LAYOUT_TEMPLATE_TS = `import type { PropsWithChildren, FC } from \"react\";\n\nconst RootLayout: FC<PropsWithChildren> = ({ children }) => <>{children}</>;\n\nexport default RootLayout;\n`;\n\nexport const ROOT_LAYOUT_TEMPLATE_JS = `const RootLayout = ({ children }) => <>{children}</>;\n\nexport default RootLayout;\n`;\n\n/**\n * Locale layout (`app/[locale]/layout.tsx`) providing `<html>` + the unified\n * provider. `IntlayerProvider` seeds both the server context (read by server\n * hooks and by any page below, without per-page wrapping) and the client\n * provider in one mount.\n */\nexport const LOCALE_LAYOUT_TEMPLATE_TS = `import { type NextLayoutIntlayer } from \"next-intlayer\";\nimport { IntlayerProvider } from \"next-intlayer/server\";\nimport { getHTMLTextDir } from \"intlayer\";\n\nexport { generateStaticParams } from \"next-intlayer\";\n\nconst LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {\n const { locale } = await params;\n\n return (\n <html lang={locale} dir={getHTMLTextDir(locale)}>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n </body>\n </html>\n );\n};\n\nexport default LocaleLayout;\n`;\n\nexport const LOCALE_LAYOUT_TEMPLATE_JS = `import { IntlayerProvider } from \"next-intlayer/server\";\nimport { getHTMLTextDir } from \"intlayer\";\n\nexport { generateStaticParams } from \"next-intlayer\";\n\nconst LocaleLayout = async ({ children, params }) => {\n const { locale } = await params;\n\n return (\n <html lang={locale} dir={getHTMLTextDir(locale)}>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n </body>\n </html>\n );\n};\n\nexport default LocaleLayout;\n`;\n\n/**\n * Locale home page (`app/[locale]/page.tsx`). Self-contained starter that does\n * not depend on an example content declaration — add Intlayer content (a\n * `*.content.ts` file consumed via `useIntlayer`) as the next step.\n */\nexport const LOCALE_PAGE_TEMPLATE_TS = `import { type NextPageIntlayer } from \"next-intlayer\";\n\nconst Page: NextPageIntlayer = async ({ params }) => {\n const { locale } = await params;\n\n return (\n <main>\n <h1>{locale}</h1>\n <p>Get started by editing this page.</p>\n </main>\n );\n};\n\nexport default Page;\n`;\n\nexport const LOCALE_PAGE_TEMPLATE_JS = `const Page = async ({ params }) => {\n const { locale } = await params;\n\n return (\n <main>\n <h1>{locale}</h1>\n <p>Get started by editing this page.</p>\n </main>\n );\n};\n\nexport default Page;\n`;\n\n/**\n * Root layout (`app/layout.tsx`) for routing modes without a locale path\n * segment (`no-prefix`, `search-params`, or no proxy at all). Owns `<html>` and\n * resolves the locale from the request (cookie / header) via `getLocale()`.\n */\nexport const UNPREFIXED_ROOT_LAYOUT_TEMPLATE_TS = `import type { PropsWithChildren } from \"react\";\nimport { getHTMLTextDir } from \"intlayer\";\nimport { getLocale, IntlayerProvider } from \"next-intlayer/server\";\n\nconst RootLayout = async ({ children }: PropsWithChildren) => {\n const locale = await getLocale();\n\n return (\n <html lang={locale} dir={getHTMLTextDir(locale)}>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n </body>\n </html>\n );\n};\n\nexport default RootLayout;\n`;\n\nexport const UNPREFIXED_ROOT_LAYOUT_TEMPLATE_JS = `import { getHTMLTextDir } from \"intlayer\";\nimport { getLocale, IntlayerProvider } from \"next-intlayer/server\";\n\nconst RootLayout = async ({ children }) => {\n const locale = await getLocale();\n\n return (\n <html lang={locale} dir={getHTMLTextDir(locale)}>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n </body>\n </html>\n );\n};\n\nexport default RootLayout;\n`;\n\n/**\n * Home page (`app/page.tsx`) for routing modes without a locale path segment.\n * Identical for TypeScript and JavaScript projects.\n */\nexport const UNPREFIXED_PAGE_TEMPLATE = `const Page = () => (\n <main>\n <h1>Hello</h1>\n <p>Get started by editing this page.</p>\n </main>\n);\n\nexport default Page;\n`;\n"],"mappings":";;;;;;;;AAOA,MAAa,iBAAiB;;;;;;;;AAS9B,MAAa,sBAAsB;;;;;;;;AASnC,MAAa,0BAA0B;;;;;;AAOvC,MAAa,0BAA0B;;;;;;;;;;AAWvC,MAAa,4BAA4B;;;;;;;;;;;;;;;;;;;;AAqBzC,MAAa,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;AAyBzC,MAAa,0BAA0B;;;;;;;;;;;;;;;AAgBvC,MAAa,0BAA0B;;;;;;;;;;;;;;;;;;AAmBvC,MAAa,qCAAqC;;;;;;;;;;;;;;;;;;AAmBlD,MAAa,qCAAqC;;;;;;;;;;;;;;;;;;;;;AAsBlD,MAAa,2BAA2B"}
|
|
@@ -91,7 +91,7 @@ const setHtmlLang = (ast) => {
|
|
|
91
91
|
* pages below the locale layout read locale/variant from it without wrapping
|
|
92
92
|
* themselves individually (see the removed `wrapPageWithProvider`).
|
|
93
93
|
*/
|
|
94
|
-
const wrapLayoutWithProvider = (code) => {
|
|
94
|
+
const wrapLayoutWithProvider = (code, { exportStaticParams = true } = {}) => {
|
|
95
95
|
const ast = parseTsx(code);
|
|
96
96
|
if (isClientComponent(ast)) return {
|
|
97
97
|
code,
|
|
@@ -123,7 +123,7 @@ const wrapLayoutWithProvider = (code) => {
|
|
|
123
123
|
};
|
|
124
124
|
require_init_utils_astImports.ensureNamedImport(ast, "IntlayerProvider", "next-intlayer/server");
|
|
125
125
|
require_init_utils_astImports.ensureNamedImport(ast, "getLocale", "next-intlayer/server");
|
|
126
|
-
ensureExportFrom(ast, "generateStaticParams", "next-intlayer");
|
|
126
|
+
if (exportStaticParams) ensureExportFrom(ast, "generateStaticParams", "next-intlayer");
|
|
127
127
|
ensureAwaitedLocale(funcNode);
|
|
128
128
|
setHtmlLang(ast);
|
|
129
129
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transforms.cjs","names":["babelTsParser","firstInsertIndex"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/transforms.ts"],"sourcesContent":["import * as recast from 'recast';\nimport { babelTsParser } from '../../../utils/babelParser';\nimport { ensureNamedImport, firstInsertIndex } from '../../utils/astImports';\n\nconst { builders: b } = recast.types;\n\n/** babel-ts parser handles TypeScript *and* JSX (the `typescript` parser does not). */\nconst parseTsx = (code: string): any =>\n recast.parse(code, { parser: babelTsParser });\n\n/** Result of a source transform. `code` is unchanged for any non-`wrapped` status. */\nexport type TransformResult = {\n code: string;\n status: 'wrapped' | 'already' | 'skipped-client' | 'skipped';\n};\n\n/** Detects a top-level `'use client'` directive (client components can't be async server providers). */\nconst isClientComponent = (ast: any): boolean => {\n const directives = ast.program.directives ?? [];\n if (\n directives.some((directive: any) => directive.value?.value === 'use client')\n ) {\n return true;\n }\n return ast.program.body.some(\n (stmt: any) =>\n stmt.type === 'ExpressionStatement' &&\n stmt.expression?.type === 'StringLiteral' &&\n stmt.expression.value === 'use client'\n );\n};\n\n/** Finds the function node behind `export default`, following an identifier reference if needed. */\nconst findDefaultExportFunction = (ast: any): any => {\n const body = ast.program.body;\n\n const asFunction = (node: any): any =>\n node &&\n (node.type === 'ArrowFunctionExpression' ||\n node.type === 'FunctionExpression' ||\n node.type === 'FunctionDeclaration')\n ? node\n : null;\n\n for (const stmt of body) {\n if (stmt.type !== 'ExportDefaultDeclaration') continue;\n\n const direct = asFunction(stmt.declaration);\n if (direct) return direct;\n\n if (stmt.declaration?.type === 'Identifier') {\n const name = stmt.declaration.name;\n for (const candidate of body) {\n if (candidate.type === 'VariableDeclaration') {\n for (const declarator of candidate.declarations) {\n if (\n declarator.id?.type === 'Identifier' &&\n declarator.id.name === name\n ) {\n const fn = asFunction(declarator.init);\n if (fn) return fn;\n }\n }\n }\n if (\n candidate.type === 'FunctionDeclaration' &&\n candidate.id?.name === name\n ) {\n return candidate;\n }\n }\n }\n }\n\n return null;\n};\n\n/** Ensures `export { exportedName } from source`, skipping when already declared/re-exported. */\nconst ensureExportFrom = (\n ast: any,\n exportedName: string,\n source: string\n): void => {\n const body = ast.program.body;\n\n const alreadyPresent = body.some((stmt: any) => {\n if (\n stmt.type === 'ExportNamedDeclaration' &&\n stmt.source?.value === source\n ) {\n return stmt.specifiers.some(\n (spec: any) => spec.exported?.name === exportedName\n );\n }\n // Locally declared `export const/function generateStaticParams`\n if (stmt.type === 'ExportNamedDeclaration' && stmt.declaration) {\n const decl = stmt.declaration;\n if (decl.type === 'FunctionDeclaration' && decl.id?.name === exportedName)\n return true;\n if (decl.type === 'VariableDeclaration') {\n return decl.declarations.some(\n (d: any) => d.id?.type === 'Identifier' && d.id.name === exportedName\n );\n }\n }\n return false;\n });\n\n if (alreadyPresent) return;\n\n const exportNode = parseTsx(`export { ${exportedName} } from \"${source}\";`)\n .program.body[0];\n ast.program.body.splice(firstInsertIndex(ast), 0, exportNode);\n};\n\n/** Makes the function async and inserts `const locale = await getLocale();` once, at the top of its body. */\nconst ensureAwaitedLocale = (funcNode: any): void => {\n funcNode.async = true;\n\n if (funcNode.body.type !== 'BlockStatement') {\n funcNode.body = b.blockStatement([b.returnStatement(funcNode.body)]);\n }\n\n const hasLocale = funcNode.body.body.some(\n (stmt: any) =>\n stmt.type === 'VariableDeclaration' &&\n stmt.declarations.some(\n (d: any) =>\n // const locale = ...\n (d.id?.type === 'Identifier' && d.id.name === 'locale') ||\n // const { locale } = ... or const { locale: locale } = ...\n (d.id?.type === 'ObjectPattern' &&\n d.id.properties?.some(\n (prop: any) =>\n prop.value?.type === 'Identifier' &&\n prop.value?.name === 'locale'\n ))\n )\n );\n\n if (!hasLocale) {\n const localeStatement = parseTsx('const locale = await getLocale();')\n .program.body[0];\n funcNode.body.body.unshift(localeStatement);\n }\n};\n\n/** Builds `<providerName locale={locale}>{child}</providerName>` around an existing JSX child node. */\nconst buildProviderElement = (providerName: string, childNode: any): any => {\n const template = parseTsx(\n `const __wrap = <${providerName} locale={locale}>{__child__}</${providerName}>;`\n );\n const providerElement = template.program.body[0].declarations[0].init;\n providerElement.children = [childNode];\n return providerElement;\n};\n\n/** Sets `lang={locale}` on the first `<html>` element, if present. */\nconst setHtmlLang = (ast: any): void => {\n recast.visit(ast, {\n visitJSXOpeningElement(path) {\n const node = path.node;\n if (node.name?.type === 'JSXIdentifier' && node.name.name === 'html') {\n const langAttr = node.attributes?.find(\n (attr: any) =>\n attr.type === 'JSXAttribute' && attr.name?.name === 'lang'\n ) as any;\n const localeExpression = b.jsxExpressionContainer(\n b.identifier('locale')\n );\n if (langAttr) {\n langAttr.value = localeExpression;\n } else {\n node.attributes.push(\n b.jsxAttribute(b.jsxIdentifier('lang'), localeExpression)\n );\n }\n return false;\n }\n this.traverse(path);\n },\n });\n};\n\n/**\n * Wraps the `{children}` of a Next.js App Router **layout** with the unified\n * `IntlayerProvider`, deriving the locale via `getLocale()`. Safe and\n * idempotent: bails (returns the original code) for client components, when no\n * `{children}` placeholder is found, or when there is no default export.\n *\n * `IntlayerProvider` seeds both the server context and the client provider in\n * one mount, so this is the only provider a Next.js App Router app needs —\n * pages below the locale layout read locale/variant from it without wrapping\n * themselves individually (see the removed `wrapPageWithProvider`).\n */\nexport const wrapLayoutWithProvider = (code: string): TransformResult => {\n const ast = parseTsx(code);\n\n if (isClientComponent(ast)) return { code, status: 'skipped-client' };\n if (code.includes('IntlayerProvider')) return { code, status: 'already' };\n\n const funcNode = findDefaultExportFunction(ast);\n if (!funcNode) return { code, status: 'skipped' };\n\n let wrapped = false;\n recast.visit(funcNode, {\n visitJSXExpressionContainer(path) {\n if (wrapped) return false;\n const expression = path.node.expression;\n if (expression?.type === 'Identifier' && expression.name === 'children') {\n path.replace(buildProviderElement('IntlayerProvider', path.node));\n wrapped = true;\n return false;\n }\n this.traverse(path);\n },\n });\n\n if (!wrapped) return { code, status: 'skipped' };\n\n ensureNamedImport(ast, 'IntlayerProvider', 'next-intlayer/server');\n ensureNamedImport(ast, 'getLocale', 'next-intlayer/server');\n ensureExportFrom(ast, 'generateStaticParams', 'next-intlayer');\n ensureAwaitedLocale(funcNode);\n setHtmlLang(ast);\n\n return { code: recast.print(ast).code, status: 'wrapped' };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"transforms.cjs","names":["babelTsParser","firstInsertIndex"],"sources":["../../../../../src/init/frameworkSetup/nextAppRouter/transforms.ts"],"sourcesContent":["import * as recast from 'recast';\nimport { babelTsParser } from '../../../utils/babelParser';\nimport { ensureNamedImport, firstInsertIndex } from '../../utils/astImports';\n\nconst { builders: b } = recast.types;\n\n/** babel-ts parser handles TypeScript *and* JSX (the `typescript` parser does not). */\nconst parseTsx = (code: string): any =>\n recast.parse(code, { parser: babelTsParser });\n\n/** Result of a source transform. `code` is unchanged for any non-`wrapped` status. */\nexport type TransformResult = {\n code: string;\n status: 'wrapped' | 'already' | 'skipped-client' | 'skipped';\n};\n\n/** Detects a top-level `'use client'` directive (client components can't be async server providers). */\nconst isClientComponent = (ast: any): boolean => {\n const directives = ast.program.directives ?? [];\n if (\n directives.some((directive: any) => directive.value?.value === 'use client')\n ) {\n return true;\n }\n return ast.program.body.some(\n (stmt: any) =>\n stmt.type === 'ExpressionStatement' &&\n stmt.expression?.type === 'StringLiteral' &&\n stmt.expression.value === 'use client'\n );\n};\n\n/** Finds the function node behind `export default`, following an identifier reference if needed. */\nconst findDefaultExportFunction = (ast: any): any => {\n const body = ast.program.body;\n\n const asFunction = (node: any): any =>\n node &&\n (node.type === 'ArrowFunctionExpression' ||\n node.type === 'FunctionExpression' ||\n node.type === 'FunctionDeclaration')\n ? node\n : null;\n\n for (const stmt of body) {\n if (stmt.type !== 'ExportDefaultDeclaration') continue;\n\n const direct = asFunction(stmt.declaration);\n if (direct) return direct;\n\n if (stmt.declaration?.type === 'Identifier') {\n const name = stmt.declaration.name;\n for (const candidate of body) {\n if (candidate.type === 'VariableDeclaration') {\n for (const declarator of candidate.declarations) {\n if (\n declarator.id?.type === 'Identifier' &&\n declarator.id.name === name\n ) {\n const fn = asFunction(declarator.init);\n if (fn) return fn;\n }\n }\n }\n if (\n candidate.type === 'FunctionDeclaration' &&\n candidate.id?.name === name\n ) {\n return candidate;\n }\n }\n }\n }\n\n return null;\n};\n\n/** Ensures `export { exportedName } from source`, skipping when already declared/re-exported. */\nconst ensureExportFrom = (\n ast: any,\n exportedName: string,\n source: string\n): void => {\n const body = ast.program.body;\n\n const alreadyPresent = body.some((stmt: any) => {\n if (\n stmt.type === 'ExportNamedDeclaration' &&\n stmt.source?.value === source\n ) {\n return stmt.specifiers.some(\n (spec: any) => spec.exported?.name === exportedName\n );\n }\n // Locally declared `export const/function generateStaticParams`\n if (stmt.type === 'ExportNamedDeclaration' && stmt.declaration) {\n const decl = stmt.declaration;\n if (decl.type === 'FunctionDeclaration' && decl.id?.name === exportedName)\n return true;\n if (decl.type === 'VariableDeclaration') {\n return decl.declarations.some(\n (d: any) => d.id?.type === 'Identifier' && d.id.name === exportedName\n );\n }\n }\n return false;\n });\n\n if (alreadyPresent) return;\n\n const exportNode = parseTsx(`export { ${exportedName} } from \"${source}\";`)\n .program.body[0];\n ast.program.body.splice(firstInsertIndex(ast), 0, exportNode);\n};\n\n/** Makes the function async and inserts `const locale = await getLocale();` once, at the top of its body. */\nconst ensureAwaitedLocale = (funcNode: any): void => {\n funcNode.async = true;\n\n if (funcNode.body.type !== 'BlockStatement') {\n funcNode.body = b.blockStatement([b.returnStatement(funcNode.body)]);\n }\n\n const hasLocale = funcNode.body.body.some(\n (stmt: any) =>\n stmt.type === 'VariableDeclaration' &&\n stmt.declarations.some(\n (d: any) =>\n // const locale = ...\n (d.id?.type === 'Identifier' && d.id.name === 'locale') ||\n // const { locale } = ... or const { locale: locale } = ...\n (d.id?.type === 'ObjectPattern' &&\n d.id.properties?.some(\n (prop: any) =>\n prop.value?.type === 'Identifier' &&\n prop.value?.name === 'locale'\n ))\n )\n );\n\n if (!hasLocale) {\n const localeStatement = parseTsx('const locale = await getLocale();')\n .program.body[0];\n funcNode.body.body.unshift(localeStatement);\n }\n};\n\n/** Builds `<providerName locale={locale}>{child}</providerName>` around an existing JSX child node. */\nconst buildProviderElement = (providerName: string, childNode: any): any => {\n const template = parseTsx(\n `const __wrap = <${providerName} locale={locale}>{__child__}</${providerName}>;`\n );\n const providerElement = template.program.body[0].declarations[0].init;\n providerElement.children = [childNode];\n return providerElement;\n};\n\n/** Sets `lang={locale}` on the first `<html>` element, if present. */\nconst setHtmlLang = (ast: any): void => {\n recast.visit(ast, {\n visitJSXOpeningElement(path) {\n const node = path.node;\n if (node.name?.type === 'JSXIdentifier' && node.name.name === 'html') {\n const langAttr = node.attributes?.find(\n (attr: any) =>\n attr.type === 'JSXAttribute' && attr.name?.name === 'lang'\n ) as any;\n const localeExpression = b.jsxExpressionContainer(\n b.identifier('locale')\n );\n if (langAttr) {\n langAttr.value = localeExpression;\n } else {\n node.attributes.push(\n b.jsxAttribute(b.jsxIdentifier('lang'), localeExpression)\n );\n }\n return false;\n }\n this.traverse(path);\n },\n });\n};\n\n/** Options of {@link wrapLayoutWithProvider}. */\nexport type WrapLayoutOptions = {\n /**\n * Re-export `generateStaticParams` from `next-intlayer`. Only meaningful for a\n * layout under a `[locale]` segment; a root layout of an unprefixed app has\n * no locale param to pre-render. Default: `true`.\n */\n exportStaticParams?: boolean;\n};\n\n/**\n * Wraps the `{children}` of a Next.js App Router **layout** with the unified\n * `IntlayerProvider`, deriving the locale via `getLocale()`. Safe and\n * idempotent: bails (returns the original code) for client components, when no\n * `{children}` placeholder is found, or when there is no default export.\n *\n * `IntlayerProvider` seeds both the server context and the client provider in\n * one mount, so this is the only provider a Next.js App Router app needs —\n * pages below the locale layout read locale/variant from it without wrapping\n * themselves individually (see the removed `wrapPageWithProvider`).\n */\nexport const wrapLayoutWithProvider = (\n code: string,\n { exportStaticParams = true }: WrapLayoutOptions = {}\n): TransformResult => {\n const ast = parseTsx(code);\n\n if (isClientComponent(ast)) return { code, status: 'skipped-client' };\n if (code.includes('IntlayerProvider')) return { code, status: 'already' };\n\n const funcNode = findDefaultExportFunction(ast);\n if (!funcNode) return { code, status: 'skipped' };\n\n let wrapped = false;\n recast.visit(funcNode, {\n visitJSXExpressionContainer(path) {\n if (wrapped) return false;\n const expression = path.node.expression;\n if (expression?.type === 'Identifier' && expression.name === 'children') {\n path.replace(buildProviderElement('IntlayerProvider', path.node));\n wrapped = true;\n return false;\n }\n this.traverse(path);\n },\n });\n\n if (!wrapped) return { code, status: 'skipped' };\n\n ensureNamedImport(ast, 'IntlayerProvider', 'next-intlayer/server');\n ensureNamedImport(ast, 'getLocale', 'next-intlayer/server');\n if (exportStaticParams) {\n ensureExportFrom(ast, 'generateStaticParams', 'next-intlayer');\n }\n ensureAwaitedLocale(funcNode);\n setHtmlLang(ast);\n\n return { code: recast.print(ast).code, status: 'wrapped' };\n};\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_init_utils_fileSystem = require('../../utils/fileSystem.cjs');
|
|
4
|
+
const require_init_frameworkSetup_localeRouting = require('../localeRouting.cjs');
|
|
4
5
|
const require_init_frameworkSetup_nextAppRouter_detect = require('../nextAppRouter/detect.cjs');
|
|
5
6
|
const require_init_frameworkSetup_tanstackStart_detect = require('./detect.cjs');
|
|
6
7
|
const require_init_frameworkSetup_tanstackStart_restructure = require('./restructure.cjs');
|
|
@@ -10,6 +11,7 @@ let node_path = require("node:path");
|
|
|
10
11
|
let _intlayer_config_colors = require("@intlayer/config/colors");
|
|
11
12
|
_intlayer_config_colors = require_runtime.__toESM(_intlayer_config_colors);
|
|
12
13
|
let _intlayer_config_logger = require("@intlayer/config/logger");
|
|
14
|
+
let node_fs_promises = require("node:fs/promises");
|
|
13
15
|
|
|
14
16
|
//#region src/init/frameworkSetup/tanstackStart/index.ts
|
|
15
17
|
/** Logs the outcome of the root-document provider-wrap transform. */
|
|
@@ -38,8 +40,28 @@ const createIfMissing = async (rootDir, filePath, content, description) => {
|
|
|
38
40
|
return true;
|
|
39
41
|
};
|
|
40
42
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
+
* Wires routes whose URLs carry no locale segment (`no-prefix`,
|
|
44
|
+
* `search-params`, or no proxy): routes stay in place and the root document
|
|
45
|
+
* provides the locale resolved per request. Routes already nested under a
|
|
46
|
+
* locale segment are left untouched, with guidance.
|
|
47
|
+
*/
|
|
48
|
+
const setupUnprefixedRoutes = async (rootDir, routesDir, useTypeScript) => {
|
|
49
|
+
const existingLocaleSegment = (await (0, node_fs_promises.readdir)((0, node_path.join)(rootDir, routesDir))).find(require_init_frameworkSetup_tanstackStart_restructure.isLocaleSegment);
|
|
50
|
+
if (existingLocaleSegment) {
|
|
51
|
+
(0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.x} Routes live under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, existingLocaleSegment))} but the chosen routing has no locale in the URL — move them back to ${(0, _intlayer_config_logger.colorizePath)(routesDir)} manually.`, { level: "warn" });
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const existingRoot = await require_init_frameworkSetup_nextAppRouter_detect.findAppFile(rootDir, routesDir, "__root");
|
|
55
|
+
if (existingRoot) {
|
|
56
|
+
await transformExistingFile(rootDir, existingRoot, require_init_frameworkSetup_tanstackStart_transforms.wrapRootWithRequestLocaleProvider);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
await createIfMissing(rootDir, (0, node_path.join)(routesDir, `__root.${useTypeScript ? "tsx" : "jsx"}`), useTypeScript ? require_init_frameworkSetup_tanstackStart_templates.UNPREFIXED_ROOT_TEMPLATE_TS : require_init_frameworkSetup_tanstackStart_templates.UNPREFIXED_ROOT_TEMPLATE_JS, "root document");
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* TanStack Start adapter. For prefix routing modes, restructures the file-based
|
|
63
|
+
* routes under a `{-$locale}` / `$locale` segment and scaffolds the locale
|
|
64
|
+
* segment route; for the others, keeps routes in place. Wraps the root document with
|
|
43
65
|
* the Intlayer provider — all idempotently and without overwriting user code it
|
|
44
66
|
* cannot confidently transform.
|
|
45
67
|
*/
|
|
@@ -49,13 +71,20 @@ const tanStackStartAdapter = {
|
|
|
49
71
|
if (!require_init_frameworkSetup_tanstackStart_detect.hasTanStackStartDeps(allDeps)) return false;
|
|
50
72
|
return await require_init_frameworkSetup_tanstackStart_detect.detectTanStackRoutesDir(rootDir) !== null;
|
|
51
73
|
},
|
|
52
|
-
setup: async ({ rootDir, useTypeScript, routingMode }) => {
|
|
74
|
+
setup: async ({ rootDir, useTypeScript, routingMode, enableProxy }) => {
|
|
53
75
|
const routesInfo = await require_init_frameworkSetup_tanstackStart_detect.detectTanStackRoutesDir(rootDir);
|
|
54
76
|
if (!routesInfo) return;
|
|
55
77
|
const { routesDir } = routesInfo;
|
|
56
78
|
const scriptExtension = useTypeScript ? "tsx" : "jsx";
|
|
57
79
|
const targetLocaleSegment = require_init_frameworkSetup_tanstackStart_restructure.getLocaleSegment(routingMode);
|
|
58
80
|
(0, _intlayer_config_logger.logger)((0, _intlayer_config_logger.colorize)("Setting up TanStack Start integration...", _intlayer_config_colors.CYAN));
|
|
81
|
+
if (!require_init_frameworkSetup_localeRouting.usesLocalePathSegment({
|
|
82
|
+
routingMode,
|
|
83
|
+
enableProxy
|
|
84
|
+
})) {
|
|
85
|
+
await setupUnprefixedRoutes(rootDir, routesDir, useTypeScript);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
59
88
|
const restructureResult = await require_init_frameworkSetup_tanstackStart_restructure.restructureRoutesIntoLocale(rootDir, routesDir, targetLocaleSegment);
|
|
60
89
|
if (restructureResult.status === "moved") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} Restructured routes under ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, targetLocaleSegment))}: ${restructureResult.movedEntries.map((entry) => (0, _intlayer_config_logger.colorize)(entry, _intlayer_config_colors.MAGENTA)).join(", ")}`);
|
|
61
90
|
else if (restructureResult.status === "already-structured") (0, _intlayer_config_logger.logger)(`${_intlayer_config_logger.v} ${(0, _intlayer_config_logger.colorizePath)((0, node_path.join)(routesDir, restructureResult.localeSegment))} already exists, skipping restructure`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["v","colorizePath","x","readFileFromRoot","writeFileToRoot","exists","hasTanStackStartDeps","detectTanStackRoutesDir","getLocaleSegment","colorize","ANSIColors","restructureRoutesIntoLocale","join","ensureDirectory","buildLocaleRouteTemplate","findAppFile","wrapRootWithProvider","buildRootTemplateTs","buildRootTemplateJs"],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/index.ts"],"sourcesContent":["import { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport { findAppFile } from '../nextAppRouter/detect';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectTanStackRoutesDir, hasTanStackStartDeps } from './detect';\nimport { getLocaleSegment, restructureRoutesIntoLocale } from './restructure';\nimport {\n buildLocaleRouteTemplate,\n buildRootTemplateJs,\n buildRootTemplateTs,\n} from './templates';\nimport { type TransformResult, wrapRootWithProvider } from './transforms';\n\n/** Logs the outcome of the root-document provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wrap the document's {children} with <IntlayerProvider locale={locale}> manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * TanStack Start adapter. Restructures the file-based routes under a `{-$locale}`\n * segment, scaffolds the locale segment route, and wraps the root document with\n * the Intlayer provider — all idempotently and without overwriting user code it\n * cannot confidently transform.\n */\nexport const tanStackStartAdapter: FrameworkAdapter = {\n name: 'TanStack Start',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!hasTanStackStartDeps(allDeps)) return false;\n return (await detectTanStackRoutesDir(rootDir)) !== null;\n },\n\n setup: async ({\n rootDir,\n useTypeScript,\n routingMode,\n }: FrameworkSetupContext) => {\n const routesInfo = await detectTanStackRoutesDir(rootDir);\n if (!routesInfo) return;\n\n const { routesDir } = routesInfo;\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n // `prefix-all` needs the required `$locale` segment; every other mode uses\n // the optional `{-$locale}` segment so the default locale stays prefix-free.\n const targetLocaleSegment = getLocaleSegment(routingMode);\n\n logger(\n colorize('Setting up TanStack Start integration...', ANSIColors.CYAN)\n );\n\n // 1. Move routable route entries under the locale segment (idempotent).\n const restructureResult = await restructureRoutesIntoLocale(\n rootDir,\n routesDir,\n targetLocaleSegment\n );\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured routes under ${colorizePath(join(routesDir, targetLocaleSegment))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(routesDir, restructureResult.localeSegment))} already exists, skipping restructure`\n );\n }\n\n // Scaffold the locale route for the segment actually in use: a pre-existing\n // segment (e.g. a prefix-all `$locale` the user already set up) wins over the\n // target, so we never create a second, conflicting locale segment.\n const activeLocaleSegment =\n restructureResult.status === 'already-structured'\n ? restructureResult.localeSegment\n : targetLocaleSegment;\n\n const localeDir = join(routesDir, activeLocaleSegment);\n await ensureDirectory(rootDir, localeDir);\n\n // 2. Locale segment route (`<segment>/route.tsx`) — create when absent.\n await createIfMissing(\n rootDir,\n join(localeDir, `route.${scriptExtension}`),\n buildLocaleRouteTemplate(activeLocaleSegment),\n 'locale route'\n );\n\n // 3. Root document — transform an existing `__root`, else scaffold one.\n const existingRoot = await findAppFile(rootDir, routesDir, '__root');\n if (existingRoot) {\n await transformExistingFile(rootDir, existingRoot, (code) =>\n wrapRootWithProvider(code, activeLocaleSegment)\n );\n } else {\n await createIfMissing(\n rootDir,\n join(routesDir, `__root.${scriptExtension}`),\n useTypeScript\n ? buildRootTemplateTs(activeLocaleSegment)\n : buildRootTemplateJs(activeLocaleSegment),\n 'root document'\n );\n }\n },\n};\n"],"mappings":";;;;;;;;;;;;;;;AAqBA,MAAM,uBACJ,UACA,WACS;CACT,QAAQ,OAAO,QAAf;EACE,KAAK;GACH,oCAAO,GAAGA,0BAAE,kCAA8BC,sCAAa,QAAQ,GAAG;GAClE;EACF,KAAK;GACH,oCACE,GAAGD,0BAAE,OAAGC,sCAAa,QAAQ,EAAE,qCACjC;GACA;EACF,KAAK,WACH,oCACE,GAAGC,0BAAE,qDAAiDD,sCAAa,QAAQ,EAAE,6FAC7E,EAAE,OAAO,OAAO,CAClB;CAEJ;AACF;;AAGA,MAAM,wBAAwB,OAC5B,SACA,UACA,cACkB;CAElB,MAAM,SAAS,UAAU,MADNE,+CAAiB,SAAS,QAAQ,CACxB;CAC7B,IAAI,OAAO,WAAW,WACpB,MAAMC,8CAAgB,SAAS,UAAU,OAAO,IAAI;CAEtD,oBAAoB,UAAU,MAAM;AACtC;;AAGA,MAAM,kBAAkB,OACtB,SACA,UACA,SACA,gBACqB;CACrB,IAAI,MAAMC,qCAAO,SAAS,QAAQ,GAAG,OAAO;CAC5C,MAAMD,8CAAgB,SAAS,UAAU,OAAO;CAChD,oCAAO,GAAGJ,0BAAE,WAAW,YAAY,OAAGC,sCAAa,QAAQ,GAAG;CAC9D,OAAO;AACT;;;;;;;AAQA,MAAa,uBAAyC;CACpD,MAAM;CAEN,QAAQ,OAAO,EAAE,SAAS,cAAc;EACtC,IAAI,CAACK,sEAAqB,OAAO,GAAG,OAAO;EAC3C,OAAQ,MAAMC,yEAAwB,OAAO,MAAO;CACtD;CAEA,OAAO,OAAO,EACZ,SACA,eACA,kBAC2B;EAC3B,MAAM,aAAa,MAAMA,yEAAwB,OAAO;EACxD,IAAI,CAAC,YAAY;EAEjB,MAAM,EAAE,cAAc;EACtB,MAAM,kBAAkB,gBAAgB,QAAQ;EAIhD,MAAM,sBAAsBC,uEAAiB,WAAW;EAExD,wCACEC,kCAAS,4CAA4CC,wBAAW,IAAI,CACtE;EAGA,MAAM,oBAAoB,MAAMC,kFAC9B,SACA,WACA,mBACF;EACA,IAAI,kBAAkB,WAAW,SAC/B,oCACE,GAAGX,0BAAE,iCAA6BC,0CAAaW,gBAAK,WAAW,mBAAmB,CAAC,EAAE,IAAI,kBAAkB,aACxG,KAAK,cAAUH,kCAAS,OAAOC,wBAAW,OAAO,CAAC,CAAC,CACnD,KAAK,IAAI,GACd;OACK,IAAI,kBAAkB,WAAW,sBACtC,oCACE,GAAGV,0BAAE,OAAGC,0CAAaW,gBAAK,WAAW,kBAAkB,aAAa,CAAC,EAAE,sCACzE;EAMF,MAAM,sBACJ,kBAAkB,WAAW,uBACzB,kBAAkB,gBAClB;EAEN,MAAM,gBAAYA,gBAAK,WAAW,mBAAmB;EACrD,MAAMC,8CAAgB,SAAS,SAAS;EAGxC,MAAM,gBACJ,aACAD,gBAAK,WAAW,SAAS,iBAAiB,GAC1CE,6EAAyB,mBAAmB,GAC5C,cACF;EAGA,MAAM,eAAe,MAAMC,6DAAY,SAAS,WAAW,QAAQ;EACnE,IAAI,cACF,MAAM,sBAAsB,SAAS,eAAe,SAClDC,0EAAqB,MAAM,mBAAmB,CAChD;OAEA,MAAM,gBACJ,aACAJ,gBAAK,WAAW,UAAU,iBAAiB,GAC3C,gBACIK,wEAAoB,mBAAmB,IACvCC,wEAAoB,mBAAmB,GAC3C,eACF;CAEJ;AACF"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["v","colorizePath","x","readFileFromRoot","writeFileToRoot","exists","readdir","join","isLocaleSegment","findAppFile","wrapRootWithRequestLocaleProvider","UNPREFIXED_ROOT_TEMPLATE_TS","UNPREFIXED_ROOT_TEMPLATE_JS","hasTanStackStartDeps","detectTanStackRoutesDir","getLocaleSegment","colorize","ANSIColors","usesLocalePathSegment","restructureRoutesIntoLocale","ensureDirectory","buildLocaleRouteTemplate","wrapRootWithProvider","buildRootTemplateTs","buildRootTemplateJs"],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/index.ts"],"sourcesContent":["import { readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, colorizePath, logger, v, x } from '@intlayer/config/logger';\nimport {\n ensureDirectory,\n exists,\n readFileFromRoot,\n writeFileToRoot,\n} from '../../utils/fileSystem';\nimport { usesLocalePathSegment } from '../localeRouting';\nimport { findAppFile } from '../nextAppRouter/detect';\nimport type { FrameworkAdapter, FrameworkSetupContext } from '../types';\nimport { detectTanStackRoutesDir, hasTanStackStartDeps } from './detect';\nimport {\n getLocaleSegment,\n isLocaleSegment,\n restructureRoutesIntoLocale,\n} from './restructure';\nimport {\n buildLocaleRouteTemplate,\n buildRootTemplateJs,\n buildRootTemplateTs,\n UNPREFIXED_ROOT_TEMPLATE_JS,\n UNPREFIXED_ROOT_TEMPLATE_TS,\n} from './templates';\nimport {\n type TransformResult,\n wrapRootWithProvider,\n wrapRootWithRequestLocaleProvider,\n} from './transforms';\n\n/** Logs the outcome of the root-document provider-wrap transform. */\nconst logTransformOutcome = (\n filePath: string,\n result: TransformResult\n): void => {\n switch (result.status) {\n case 'wrapped':\n logger(`${v} Added Intlayer provider to ${colorizePath(filePath)}`);\n break;\n case 'already':\n logger(\n `${v} ${colorizePath(filePath)} already wraps the Intlayer provider`\n );\n break;\n case 'skipped':\n logger(\n `${x} Could not safely add the Intlayer provider to ${colorizePath(filePath)} — please wrap the document's {children} with <IntlayerProvider locale={locale}> manually.`,\n { level: 'warn' }\n );\n break;\n }\n};\n\n/** Transforms an existing file in place, writing it back only when changed. */\nconst transformExistingFile = async (\n rootDir: string,\n filePath: string,\n transform: (code: string) => TransformResult\n): Promise<void> => {\n const code = await readFileFromRoot(rootDir, filePath);\n const result = transform(code);\n if (result.status === 'wrapped') {\n await writeFileToRoot(rootDir, filePath, result.code);\n }\n logTransformOutcome(filePath, result);\n};\n\n/** Creates a file from a template only when it does not already exist. */\nconst createIfMissing = async (\n rootDir: string,\n filePath: string,\n content: string,\n description: string\n): Promise<boolean> => {\n if (await exists(rootDir, filePath)) return false;\n await writeFileToRoot(rootDir, filePath, content);\n logger(`${v} Created ${description} ${colorizePath(filePath)}`);\n return true;\n};\n\n/**\n * Wires routes whose URLs carry no locale segment (`no-prefix`,\n * `search-params`, or no proxy): routes stay in place and the root document\n * provides the locale resolved per request. Routes already nested under a\n * locale segment are left untouched, with guidance.\n */\nconst setupUnprefixedRoutes = async (\n rootDir: string,\n routesDir: string,\n useTypeScript: boolean\n): Promise<void> => {\n const entries = await readdir(join(rootDir, routesDir));\n const existingLocaleSegment = entries.find(isLocaleSegment);\n if (existingLocaleSegment) {\n logger(\n `${x} Routes live under ${colorizePath(join(routesDir, existingLocaleSegment))} but the chosen routing has no locale in the URL — move them back to ${colorizePath(routesDir)} manually.`,\n { level: 'warn' }\n );\n return;\n }\n\n const existingRoot = await findAppFile(rootDir, routesDir, '__root');\n if (existingRoot) {\n await transformExistingFile(\n rootDir,\n existingRoot,\n wrapRootWithRequestLocaleProvider\n );\n return;\n }\n\n await createIfMissing(\n rootDir,\n join(routesDir, `__root.${useTypeScript ? 'tsx' : 'jsx'}`),\n useTypeScript ? UNPREFIXED_ROOT_TEMPLATE_TS : UNPREFIXED_ROOT_TEMPLATE_JS,\n 'root document'\n );\n};\n\n/**\n * TanStack Start adapter. For prefix routing modes, restructures the file-based\n * routes under a `{-$locale}` / `$locale` segment and scaffolds the locale\n * segment route; for the others, keeps routes in place. Wraps the root document with\n * the Intlayer provider — all idempotently and without overwriting user code it\n * cannot confidently transform.\n */\nexport const tanStackStartAdapter: FrameworkAdapter = {\n name: 'TanStack Start',\n\n detect: async ({ rootDir, allDeps }) => {\n if (!hasTanStackStartDeps(allDeps)) return false;\n return (await detectTanStackRoutesDir(rootDir)) !== null;\n },\n\n setup: async ({\n rootDir,\n useTypeScript,\n routingMode,\n enableProxy,\n }: FrameworkSetupContext) => {\n const routesInfo = await detectTanStackRoutesDir(rootDir);\n if (!routesInfo) return;\n\n const { routesDir } = routesInfo;\n const scriptExtension = useTypeScript ? 'tsx' : 'jsx';\n\n // `prefix-all` needs the required `$locale` segment; every other mode uses\n // the optional `{-$locale}` segment so the default locale stays prefix-free.\n const targetLocaleSegment = getLocaleSegment(routingMode);\n\n logger(\n colorize('Setting up TanStack Start integration...', ANSIColors.CYAN)\n );\n\n if (!usesLocalePathSegment({ routingMode, enableProxy })) {\n await setupUnprefixedRoutes(rootDir, routesDir, useTypeScript);\n return;\n }\n\n // 1. Move routable route entries under the locale segment (idempotent).\n const restructureResult = await restructureRoutesIntoLocale(\n rootDir,\n routesDir,\n targetLocaleSegment\n );\n if (restructureResult.status === 'moved') {\n logger(\n `${v} Restructured routes under ${colorizePath(join(routesDir, targetLocaleSegment))}: ${restructureResult.movedEntries\n .map((entry) => colorize(entry, ANSIColors.MAGENTA))\n .join(', ')}`\n );\n } else if (restructureResult.status === 'already-structured') {\n logger(\n `${v} ${colorizePath(join(routesDir, restructureResult.localeSegment))} already exists, skipping restructure`\n );\n }\n\n // Scaffold the locale route for the segment actually in use: a pre-existing\n // segment (e.g. a prefix-all `$locale` the user already set up) wins over the\n // target, so we never create a second, conflicting locale segment.\n const activeLocaleSegment =\n restructureResult.status === 'already-structured'\n ? restructureResult.localeSegment\n : targetLocaleSegment;\n\n const localeDir = join(routesDir, activeLocaleSegment);\n await ensureDirectory(rootDir, localeDir);\n\n // 2. Locale segment route (`<segment>/route.tsx`) — create when absent.\n await createIfMissing(\n rootDir,\n join(localeDir, `route.${scriptExtension}`),\n buildLocaleRouteTemplate(activeLocaleSegment),\n 'locale route'\n );\n\n // 3. Root document — transform an existing `__root`, else scaffold one.\n const existingRoot = await findAppFile(rootDir, routesDir, '__root');\n if (existingRoot) {\n await transformExistingFile(rootDir, existingRoot, (code) =>\n wrapRootWithProvider(code, activeLocaleSegment)\n );\n } else {\n await createIfMissing(\n rootDir,\n join(routesDir, `__root.${scriptExtension}`),\n useTypeScript\n ? buildRootTemplateTs(activeLocaleSegment)\n : buildRootTemplateJs(activeLocaleSegment),\n 'root document'\n );\n }\n },\n};\n"],"mappings":"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"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('../../../_virtual/_rolldown/runtime.cjs');
|
|
3
3
|
const require_init_frameworkSetup_nextAppRouter_restructure = require('../nextAppRouter/restructure.cjs');
|
|
4
|
-
let node_fs_promises = require("node:fs/promises");
|
|
5
4
|
let node_path = require("node:path");
|
|
6
5
|
let fast_glob = require("fast-glob");
|
|
7
6
|
fast_glob = require_runtime.__toESM(fast_glob);
|
|
7
|
+
let node_fs_promises = require("node:fs/promises");
|
|
8
8
|
|
|
9
9
|
//#region src/init/frameworkSetup/tanstackStart/restructure.ts
|
|
10
10
|
/** Source file extensions whose relative imports must be rewritten after a move. */
|
|
@@ -104,8 +104,66 @@ function RootDocument({ children }) {
|
|
|
104
104
|
);
|
|
105
105
|
}
|
|
106
106
|
`;
|
|
107
|
+
/**
|
|
108
|
+
* Module-scope server function resolving the request locale from the locale
|
|
109
|
+
* cookie / headers (`Accept-Language` fallback). Shared by the unprefixed root
|
|
110
|
+
* template and the root transform.
|
|
111
|
+
*/
|
|
112
|
+
const REQUEST_LOCALE_SERVER_FUNCTION = `const getRequestLocale = createServerFn().handler(() =>
|
|
113
|
+
getLocale({
|
|
114
|
+
getCookie: (name) => getCookie(name, getRequestHeader("cookie")),
|
|
115
|
+
getHeader: (name) => getRequestHeader(name),
|
|
116
|
+
})
|
|
117
|
+
);`;
|
|
118
|
+
/**
|
|
119
|
+
* Root route document (`routes/__root.tsx`) for routing modes without a locale
|
|
120
|
+
* path segment (`no-prefix`, `search-params`, or no proxy). The locale is
|
|
121
|
+
* resolved on the server per request and exposed through the root loader, so
|
|
122
|
+
* server and client render the same locale. Identical for TypeScript and
|
|
123
|
+
* JavaScript projects apart from the `children` prop type.
|
|
124
|
+
*/
|
|
125
|
+
const buildUnprefixedRootTemplate = (childrenPropType) => `import {
|
|
126
|
+
createRootRoute,
|
|
127
|
+
HeadContent,
|
|
128
|
+
Scripts,
|
|
129
|
+
} from "@tanstack/react-router";
|
|
130
|
+
import { createServerFn } from "@tanstack/react-start";
|
|
131
|
+
import { getRequestHeader } from "@tanstack/react-start/server";
|
|
132
|
+
import { getCookie, getHTMLTextDir, getLocale } from "intlayer";${childrenPropType ? "\nimport type { ReactNode } from \"react\";" : ""}
|
|
133
|
+
import { IntlayerProvider } from "react-intlayer";
|
|
134
|
+
|
|
135
|
+
${REQUEST_LOCALE_SERVER_FUNCTION}
|
|
136
|
+
|
|
137
|
+
export const Route = createRootRoute({
|
|
138
|
+
loader: () => getRequestLocale(),
|
|
139
|
+
shellComponent: RootDocument,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
function RootDocument({ children }${childrenPropType}) {
|
|
143
|
+
const locale = Route.useLoaderData();
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<html dir={getHTMLTextDir(locale)} lang={locale}>
|
|
147
|
+
<head>
|
|
148
|
+
<HeadContent />
|
|
149
|
+
</head>
|
|
150
|
+
<body>
|
|
151
|
+
<IntlayerProvider locale={locale}>{children}</IntlayerProvider>
|
|
152
|
+
<Scripts />
|
|
153
|
+
</body>
|
|
154
|
+
</html>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
`;
|
|
158
|
+
/** {@link buildUnprefixedRootTemplate} for TypeScript projects. */
|
|
159
|
+
const UNPREFIXED_ROOT_TEMPLATE_TS = buildUnprefixedRootTemplate(": { children: ReactNode }");
|
|
160
|
+
/** {@link buildUnprefixedRootTemplate} for JavaScript projects. */
|
|
161
|
+
const UNPREFIXED_ROOT_TEMPLATE_JS = buildUnprefixedRootTemplate("");
|
|
107
162
|
|
|
108
163
|
//#endregion
|
|
164
|
+
exports.REQUEST_LOCALE_SERVER_FUNCTION = REQUEST_LOCALE_SERVER_FUNCTION;
|
|
165
|
+
exports.UNPREFIXED_ROOT_TEMPLATE_JS = UNPREFIXED_ROOT_TEMPLATE_JS;
|
|
166
|
+
exports.UNPREFIXED_ROOT_TEMPLATE_TS = UNPREFIXED_ROOT_TEMPLATE_TS;
|
|
109
167
|
exports.buildLocaleRouteTemplate = buildLocaleRouteTemplate;
|
|
110
168
|
exports.buildRootTemplateJs = buildRootTemplateJs;
|
|
111
169
|
exports.buildRootTemplateTs = buildRootTemplateTs;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.cjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/templates.ts"],"sourcesContent":["/**\n * File templates for a fresh TanStack Start integration. These are only written\n * when the target file does not exist — they never overwrite user code.\n */\n\n/**\n * Builds the locale segment route (`routes/<localeSegment>/route.tsx`) for the\n * given segment. The optional `{-$locale}` param makes the default locale\n * prefix-free, while the required `$locale` param (`prefix-all`) prefixes every\n * locale; in both cases `validatePrefix` redirects unknown prefixes to a valid\n * one. Identical for TypeScript and JavaScript projects.\n */\nexport const buildLocaleRouteTemplate = (\n localeSegment: string\n): string => `import { createFileRoute, Outlet, redirect } from \"@tanstack/react-router\";\nimport { validatePrefix } from \"intlayer\";\n\nexport const Route = createFileRoute(\"/${localeSegment}\")({\n beforeLoad: ({ params }) => {\n // beforeLoad runs on both client and server, so resolve the locale from the\n // route params rather than from request headers.\n const { isValid, localePrefix } = validatePrefix(params.locale);\n\n // A valid (or absent, i.e. default) locale prefix is fine as-is.\n if (isValid) return;\n\n // Otherwise redirect to the same route with a valid locale prefix.\n throw redirect({\n params: { locale: localePrefix },\n to: \"/${localeSegment}\",\n });\n },\n component: Outlet,\n});\n`;\n\n/**\n * Root route document (`routes/__root.tsx`) providing `<html>` + the Intlayer\n * provider, with the locale read from the locale segment route params.\n *\n * The route is reached through `getRouteApi(<route id>)` rather than by\n * importing `<segment>/route`, so the root never imports a child route module —\n * the recommended way to consume another route's typed hooks.\n */\nexport const buildRootTemplateTs = (localeSegment: string): string => `import {\n createRootRoute,\n getRouteApi,\n HeadContent,\n Scripts,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport type { ReactNode } from \"react\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nconst localeRoute = getRouteApi(\"/${localeSegment}\");\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }: { children: ReactNode }) {\n const { locale = defaultLocale } = localeRoute.useParams();\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n\n/** JavaScript counterpart of {@link buildRootTemplateTs}. */\nexport const buildRootTemplateJs = (localeSegment: string): string => `import {\n createRootRoute,\n getRouteApi,\n HeadContent,\n Scripts,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nconst localeRoute = getRouteApi(\"/${localeSegment}\");\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }) {\n const { locale = defaultLocale } = localeRoute.useParams();\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAa,4BACX,kBACW;;;yCAG4B,cAAc;;;;;;;;;;;;cAYzC,cAAc;;;;;;;;;;;;;;AAe5B,MAAa,uBAAuB,kBAAkC;;;;;;;;;;oCAUlC,cAAc;;;;;;;;;;;;;;;;;;;;;;;AAwBlD,MAAa,uBAAuB,kBAAkC;;;;;;;;;oCASlC,cAAc"}
|
|
1
|
+
{"version":3,"file":"templates.cjs","names":[],"sources":["../../../../../src/init/frameworkSetup/tanstackStart/templates.ts"],"sourcesContent":["/**\n * File templates for a fresh TanStack Start integration. These are only written\n * when the target file does not exist — they never overwrite user code.\n */\n\n/**\n * Builds the locale segment route (`routes/<localeSegment>/route.tsx`) for the\n * given segment. The optional `{-$locale}` param makes the default locale\n * prefix-free, while the required `$locale` param (`prefix-all`) prefixes every\n * locale; in both cases `validatePrefix` redirects unknown prefixes to a valid\n * one. Identical for TypeScript and JavaScript projects.\n */\nexport const buildLocaleRouteTemplate = (\n localeSegment: string\n): string => `import { createFileRoute, Outlet, redirect } from \"@tanstack/react-router\";\nimport { validatePrefix } from \"intlayer\";\n\nexport const Route = createFileRoute(\"/${localeSegment}\")({\n beforeLoad: ({ params }) => {\n // beforeLoad runs on both client and server, so resolve the locale from the\n // route params rather than from request headers.\n const { isValid, localePrefix } = validatePrefix(params.locale);\n\n // A valid (or absent, i.e. default) locale prefix is fine as-is.\n if (isValid) return;\n\n // Otherwise redirect to the same route with a valid locale prefix.\n throw redirect({\n params: { locale: localePrefix },\n to: \"/${localeSegment}\",\n });\n },\n component: Outlet,\n});\n`;\n\n/**\n * Root route document (`routes/__root.tsx`) providing `<html>` + the Intlayer\n * provider, with the locale read from the locale segment route params.\n *\n * The route is reached through `getRouteApi(<route id>)` rather than by\n * importing `<segment>/route`, so the root never imports a child route module —\n * the recommended way to consume another route's typed hooks.\n */\nexport const buildRootTemplateTs = (localeSegment: string): string => `import {\n createRootRoute,\n getRouteApi,\n HeadContent,\n Scripts,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport type { ReactNode } from \"react\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nconst localeRoute = getRouteApi(\"/${localeSegment}\");\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }: { children: ReactNode }) {\n const { locale = defaultLocale } = localeRoute.useParams();\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n\n/** JavaScript counterpart of {@link buildRootTemplateTs}. */\nexport const buildRootTemplateJs = (localeSegment: string): string => `import {\n createRootRoute,\n getRouteApi,\n HeadContent,\n Scripts,\n} from \"@tanstack/react-router\";\nimport { defaultLocale, getHTMLTextDir } from \"intlayer\";\nimport { IntlayerProvider } from \"react-intlayer\";\n\nconst localeRoute = getRouteApi(\"/${localeSegment}\");\n\nexport const Route = createRootRoute({\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }) {\n const { locale = defaultLocale } = localeRoute.useParams();\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n\n/**\n * Module-scope server function resolving the request locale from the locale\n * cookie / headers (`Accept-Language` fallback). Shared by the unprefixed root\n * template and the root transform.\n */\nexport const REQUEST_LOCALE_SERVER_FUNCTION = `const getRequestLocale = createServerFn().handler(() =>\n getLocale({\n getCookie: (name) => getCookie(name, getRequestHeader(\"cookie\")),\n getHeader: (name) => getRequestHeader(name),\n })\n);`;\n\n/**\n * Root route document (`routes/__root.tsx`) for routing modes without a locale\n * path segment (`no-prefix`, `search-params`, or no proxy). The locale is\n * resolved on the server per request and exposed through the root loader, so\n * server and client render the same locale. Identical for TypeScript and\n * JavaScript projects apart from the `children` prop type.\n */\nconst buildUnprefixedRootTemplate = (\n childrenPropType: string\n): string => `import {\n createRootRoute,\n HeadContent,\n Scripts,\n} from \"@tanstack/react-router\";\nimport { createServerFn } from \"@tanstack/react-start\";\nimport { getRequestHeader } from \"@tanstack/react-start/server\";\nimport { getCookie, getHTMLTextDir, getLocale } from \"intlayer\";${childrenPropType ? '\\nimport type { ReactNode } from \"react\";' : ''}\nimport { IntlayerProvider } from \"react-intlayer\";\n\n${REQUEST_LOCALE_SERVER_FUNCTION}\n\nexport const Route = createRootRoute({\n loader: () => getRequestLocale(),\n shellComponent: RootDocument,\n});\n\nfunction RootDocument({ children }${childrenPropType}) {\n const locale = Route.useLoaderData();\n\n return (\n <html dir={getHTMLTextDir(locale)} lang={locale}>\n <head>\n <HeadContent />\n </head>\n <body>\n <IntlayerProvider locale={locale}>{children}</IntlayerProvider>\n <Scripts />\n </body>\n </html>\n );\n}\n`;\n\n/** {@link buildUnprefixedRootTemplate} for TypeScript projects. */\nexport const UNPREFIXED_ROOT_TEMPLATE_TS = buildUnprefixedRootTemplate(\n ': { children: ReactNode }'\n);\n\n/** {@link buildUnprefixedRootTemplate} for JavaScript projects. */\nexport const UNPREFIXED_ROOT_TEMPLATE_JS = buildUnprefixedRootTemplate('');\n"],"mappings":";;;;;;;;;;;;;AAYA,MAAa,4BACX,kBACW;;;yCAG4B,cAAc;;;;;;;;;;;;cAYzC,cAAc;;;;;;;;;;;;;;AAe5B,MAAa,uBAAuB,kBAAkC;;;;;;;;;;oCAUlC,cAAc;;;;;;;;;;;;;;;;;;;;;;;AAwBlD,MAAa,uBAAuB,kBAAkC;;;;;;;;;oCASlC,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BlD,MAAa,iCAAiC;;;;;;;;;;;;;AAc9C,MAAM,+BACJ,qBACW;;;;;;;kEAOqD,mBAAmB,gDAA8C,GAAG;;;EAGpI,+BAA+B;;;;;;;oCAOG,iBAAiB;;;;;;;;;;;;;;;;;AAkBrD,MAAa,8BAA8B,4BACzC,2BACF;;AAGA,MAAa,8BAA8B,4BAA4B,EAAE"}
|