vite-intlayer 8.5.2 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,10 @@ import { join } from "node:path";
3
3
  import { intlayerOptimizeBabelPlugin } from "@intlayer/babel";
4
4
  import * as ANSIColors from "@intlayer/config/colors";
5
5
  import { colorize, getAppLogger } from "@intlayer/config/logger";
6
- import { transformAsync } from "@babel/core";
7
6
  import { buildComponentFilesList, runOnce } from "@intlayer/chokidar/utils";
8
- import { IMPORT_MODE } from "@intlayer/config/defaultValues";
9
7
  import { getDictionaries } from "@intlayer/dictionaries-entry";
8
+ import { transformAsync } from "@babel/core";
9
+ import { IMPORT_MODE } from "@intlayer/config/defaultValues";
10
10
 
11
11
  //#region src/intlayerOptimizePlugin.ts
12
12
  const INTLAYER_USAGE_REGEX = /\b(use|get)Intlayer\b/;
@@ -4,9 +4,10 @@ import { resolve } from "node:path";
4
4
  import { getConfiguration } from "@intlayer/config/node";
5
5
  import { prepareIntlayer } from "@intlayer/chokidar/build";
6
6
  import { logConfigDetails } from "@intlayer/chokidar/cli";
7
+ import { getNodeTypeDefineVars, getUsedNodeTypes } from "@intlayer/chokidar/utils";
7
8
  import { watch } from "@intlayer/chokidar/watcher";
8
9
  import { getAlias } from "@intlayer/config/utils";
9
- import { mergeConfig } from "vite";
10
+ import { getDictionaries } from "@intlayer/dictionaries-entry";
10
11
 
11
12
  //#region src/intlayerPlugin.ts
12
13
  /**
@@ -51,11 +52,12 @@ const intlayerPlugin = (configOptions) => {
51
52
  cacheTimeoutMs: isBuildCommand ? 1e3 * 30 : 1e3 * 60 * 60,
52
53
  env: isBuildCommand ? "prod" : "dev"
53
54
  });
54
- return mergeConfig(config, {
55
+ return {
56
+ define: isBuildCommand ? Object.fromEntries(Object.entries(getNodeTypeDefineVars(getUsedNodeTypes(getDictionaries(intlayerConfig)))).map(([k, v]) => [`process.env.${k}`, JSON.stringify(v)])) : {},
55
57
  resolve: { alias },
56
58
  optimizeDeps: { exclude: aliasPackages },
57
59
  ssr: { noExternal: [/(^@intlayer\/|intlayer$)/] }
58
- });
60
+ };
59
61
  },
60
62
  configureServer: async (server) => {
61
63
  if (server.config.mode === "development") watch({ configuration: intlayerConfig });
@@ -1 +1 @@
1
- {"version":3,"file":"intlayerPlugin.mjs","names":[],"sources":["../../src/intlayerPlugin.ts"],"sourcesContent":["import { resolve } from 'node:path';\nimport { prepareIntlayer } from '@intlayer/chokidar/build';\nimport { logConfigDetails } from '@intlayer/chokidar/cli';\nimport { watch } from '@intlayer/chokidar/watcher';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getAlias } from '@intlayer/config/utils';\n// @ts-ignore - Fix error Module '\"vite\"' has no exported member\nimport { mergeConfig, type PluginOption } from 'vite';\nimport { intlayerEditorPlugin } from './intlayerEditorPlugin';\nimport { intlayerOptimize } from './intlayerOptimizePlugin';\n\n/**\n * Vite plugin that integrates Intlayer into the Vite build process.\n *\n * It handles:\n * 1. Preparing Intlayer resources (dictionaries) before build.\n * 2. Configuring Vite aliases for dictionary access.\n * 3. Setting up dev-server watchers for content changes.\n * 4. Applying build optimizations (tree-shaking dictionaries).\n *\n * @param configOptions - Optional configuration to override default Intlayer settings.\n * @returns A Vite plugin option.\n *\n * @example\n * ```ts\n * import { intlayer } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayer()],\n * });\n *\n * ```\n * @deprecated Rename to intlayer instead\n */\nexport const intlayerPlugin = (\n configOptions?: GetConfigurationOptions\n): PluginOption => {\n const intlayerConfig = getConfiguration(configOptions);\n logConfigDetails(configOptions);\n\n const alias = getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value),\n });\n\n const aliasPackages = Object.keys(alias);\n\n const plugins: PluginOption[] = [\n {\n name: 'vite-intlayer-plugin',\n\n config: async (config, env) => {\n const { mode } = intlayerConfig.build;\n\n const isDevCommand =\n env.command === 'serve' && env.mode === 'development';\n const isBuildCommand = env.command === 'build';\n\n // Only call prepareIntlayer during `dev` or `build` (not during `start`)\n // If prod: clean and rebuild once\n // If dev: rebuild only once if it's more than 1 hour since last rebuild\n if (isDevCommand || isBuildCommand || mode === 'auto') {\n // prepareIntlayer use runOnce to ensure to run only once because will run twice on client and server side otherwise\n await prepareIntlayer(intlayerConfig, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build (to ensure to rebuild all dictionaries)\n : 1000 * 60 * 60, // 1 hour for dev (default cache timeout)\n env: isBuildCommand ? 'prod' : 'dev',\n });\n }\n\n // mergeConfig handles both array and record alias formats,\n // and correctly appends to optimizeDeps.exclude / ssr.noExternal\n return mergeConfig(config, {\n resolve: {\n alias,\n },\n optimizeDeps: {\n // Exclude alias entry points since they're local files, not npm packages\n exclude: aliasPackages,\n },\n ssr: {\n // Ensure intlayer packages are bundled so aliases are applied\n noExternal: [/(^@intlayer\\/|intlayer$)/],\n },\n });\n },\n\n configureServer: async (server) => {\n if (server.config.mode === 'development') {\n // Start watching (assuming watch is also async)\n watch({ configuration: intlayerConfig });\n }\n },\n },\n ];\n\n plugins.push(intlayerEditorPlugin(intlayerConfig));\n\n // Add Babel transform plugin if enabled\n plugins.push(intlayerOptimize(intlayerConfig));\n\n return plugins;\n};\n\n/**\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n */\nexport const intlayer = intlayerPlugin;\n/**\n * @deprecated Rename to intlayer instead\n *\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n */\nexport const intLayerPlugin = intlayerPlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,kBACX,kBACiB;CACjB,MAAM,iBAAiB,iBAAiB,cAAc;AACtD,kBAAiB,cAAc;CAE/B,MAAM,QAAQ,SAAS;EACrB,eAAe;EACf,YAAY,UAAkB,QAAQ,MAAM;EAC7C,CAAC;CAEF,MAAM,gBAAgB,OAAO,KAAK,MAAM;CAExC,MAAM,UAA0B,CAC9B;EACE,MAAM;EAEN,QAAQ,OAAO,QAAQ,QAAQ;GAC7B,MAAM,EAAE,SAAS,eAAe;GAEhC,MAAM,eACJ,IAAI,YAAY,WAAW,IAAI,SAAS;GAC1C,MAAM,iBAAiB,IAAI,YAAY;AAKvC,OAAI,gBAAgB,kBAAkB,SAAS,OAE7C,OAAM,gBAAgB,gBAAgB;IACpC,OAAO;IACP,gBAAgB,iBACZ,MAAO,KACP,MAAO,KAAK;IAChB,KAAK,iBAAiB,SAAS;IAChC,CAAC;AAKJ,UAAO,YAAY,QAAQ;IACzB,SAAS,EACP,OACD;IACD,cAAc,EAEZ,SAAS,eACV;IACD,KAAK,EAEH,YAAY,CAAC,2BAA2B,EACzC;IACF,CAAC;;EAGJ,iBAAiB,OAAO,WAAW;AACjC,OAAI,OAAO,OAAO,SAAS,cAEzB,OAAM,EAAE,eAAe,gBAAgB,CAAC;;EAG7C,CACF;AAED,SAAQ,KAAK,qBAAqB,eAAe,CAAC;AAGlD,SAAQ,KAAK,iBAAiB,eAAe,CAAC;AAE9C,QAAO;;;;;;;;;;;;AAaT,MAAa,WAAW;;;;;;;;;;;;;AAaxB,MAAa,iBAAiB"}
1
+ {"version":3,"file":"intlayerPlugin.mjs","names":[],"sources":["../../src/intlayerPlugin.ts"],"sourcesContent":["import { resolve } from 'node:path';\nimport { prepareIntlayer } from '@intlayer/chokidar/build';\nimport { logConfigDetails } from '@intlayer/chokidar/cli';\nimport {\n getNodeTypeDefineVars,\n getUsedNodeTypes,\n} from '@intlayer/chokidar/utils';\nimport { watch } from '@intlayer/chokidar/watcher';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport { getAlias } from '@intlayer/config/utils';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\n// @ts-ignore - Fix error Module '\"vite\"' has no exported member\nimport type { PluginOption } from 'vite';\nimport { intlayerEditorPlugin } from './intlayerEditorPlugin';\nimport { intlayerOptimize } from './intlayerOptimizePlugin';\n\n/**\n * Vite plugin that integrates Intlayer into the Vite build process.\n *\n * It handles:\n * 1. Preparing Intlayer resources (dictionaries) before build.\n * 2. Configuring Vite aliases for dictionary access.\n * 3. Setting up dev-server watchers for content changes.\n * 4. Applying build optimizations (tree-shaking dictionaries).\n *\n * @param configOptions - Optional configuration to override default Intlayer settings.\n * @returns A Vite plugin option.\n *\n * @example\n * ```ts\n * import { intlayer } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayer()],\n * });\n *\n * ```\n * @deprecated Rename to intlayer instead\n */\nexport const intlayerPlugin = (\n configOptions?: GetConfigurationOptions\n): PluginOption => {\n const intlayerConfig = getConfiguration(configOptions);\n logConfigDetails(configOptions);\n\n const alias = getAlias({\n configuration: intlayerConfig,\n formatter: (value: string) => resolve(value),\n });\n\n const aliasPackages = Object.keys(alias);\n\n const plugins: PluginOption[] = [\n {\n name: 'vite-intlayer-plugin',\n\n config: async (config, env) => {\n const { mode } = intlayerConfig.build;\n\n const isDevCommand =\n env.command === 'serve' && env.mode === 'development';\n const isBuildCommand = env.command === 'build';\n\n // Only call prepareIntlayer during `dev` or `build` (not during `start`)\n // If prod: clean and rebuild once\n // If dev: rebuild only once if it's more than 1 hour since last rebuild\n if (isDevCommand || isBuildCommand || mode === 'auto') {\n // prepareIntlayer use runOnce to ensure to run only once because will run twice on client and server side otherwise\n await prepareIntlayer(intlayerConfig, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build (to ensure to rebuild all dictionaries)\n : 1000 * 60 * 60, // 1 hour for dev (default cache timeout)\n env: isBuildCommand ? 'prod' : 'dev',\n });\n }\n\n const nodeTypeDefineVars = isBuildCommand\n ? Object.fromEntries(\n Object.entries(\n getNodeTypeDefineVars(\n getUsedNodeTypes(getDictionaries(intlayerConfig))\n )\n ).map(([k, v]) => [`process.env.${k}`, JSON.stringify(v)])\n )\n : {};\n\n // mergeConfig handles both array and record alias formats,\n // and correctly appends to optimizeDeps.exclude / ssr.noExternal\n return {\n define: nodeTypeDefineVars,\n resolve: {\n alias,\n },\n optimizeDeps: {\n // Exclude alias entry points since they're local files, not npm packages\n exclude: aliasPackages,\n },\n ssr: {\n // Ensure intlayer packages are bundled so aliases are applied\n noExternal: [/(^@intlayer\\/|intlayer$)/],\n },\n };\n },\n\n configureServer: async (server) => {\n if (server.config.mode === 'development') {\n // Start watching (assuming watch is also async)\n watch({ configuration: intlayerConfig });\n }\n },\n },\n ];\n\n plugins.push(intlayerEditorPlugin(intlayerConfig));\n\n // Add Babel transform plugin if enabled\n plugins.push(intlayerOptimize(intlayerConfig));\n\n return plugins;\n};\n\n/**\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n */\nexport const intlayer = intlayerPlugin;\n/**\n * @deprecated Rename to intlayer instead\n *\n * A Vite plugin that integrates Intlayer configuration into the build process\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayer() ],\n * });\n * ```\n */\nexport const intLayerPlugin = intlayerPlugin;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAa,kBACX,kBACiB;CACjB,MAAM,iBAAiB,iBAAiB,cAAc;AACtD,kBAAiB,cAAc;CAE/B,MAAM,QAAQ,SAAS;EACrB,eAAe;EACf,YAAY,UAAkB,QAAQ,MAAM;EAC7C,CAAC;CAEF,MAAM,gBAAgB,OAAO,KAAK,MAAM;CAExC,MAAM,UAA0B,CAC9B;EACE,MAAM;EAEN,QAAQ,OAAO,QAAQ,QAAQ;GAC7B,MAAM,EAAE,SAAS,eAAe;GAEhC,MAAM,eACJ,IAAI,YAAY,WAAW,IAAI,SAAS;GAC1C,MAAM,iBAAiB,IAAI,YAAY;AAKvC,OAAI,gBAAgB,kBAAkB,SAAS,OAE7C,OAAM,gBAAgB,gBAAgB;IACpC,OAAO;IACP,gBAAgB,iBACZ,MAAO,KACP,MAAO,KAAK;IAChB,KAAK,iBAAiB,SAAS;IAChC,CAAC;AAeJ,UAAO;IACL,QAbyB,iBACvB,OAAO,YACL,OAAO,QACL,sBACE,iBAAiB,gBAAgB,eAAe,CAAC,CAClD,CACF,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,eAAe,KAAK,KAAK,UAAU,EAAE,CAAC,CAAC,CAC3D,GACD,EAAE;IAMJ,SAAS,EACP,OACD;IACD,cAAc,EAEZ,SAAS,eACV;IACD,KAAK,EAEH,YAAY,CAAC,2BAA2B,EACzC;IACF;;EAGH,iBAAiB,OAAO,WAAW;AACjC,OAAI,OAAO,OAAO,SAAS,cAEzB,OAAM,EAAE,eAAe,gBAAgB,CAAC;;EAG7C,CACF;AAED,SAAQ,KAAK,qBAAqB,eAAe,CAAC;AAGlD,SAAQ,KAAK,iBAAiB,eAAe,CAAC;AAE9C,QAAO;;;;;;;;;;;;AAaT,MAAa,WAAW;;;;;;;;;;;;;AAaxB,MAAa,iBAAiB"}
@@ -2,7 +2,7 @@ import { getConfiguration } from "@intlayer/config/node";
2
2
  import { ROUTING_MODE } from "@intlayer/config/defaultValues";
3
3
  import { parse } from "node:url";
4
4
  import { getCanonicalPath, getLocalizedPath, getRewriteRules, localeDetector } from "@intlayer/core/localization";
5
- import { getCookie, getLocaleFromStorage, setLocaleInStorage } from "@intlayer/core/utils";
5
+ import { getCookie, getLocaleFromStorageServer, setLocaleInStorageServer } from "@intlayer/core/utils";
6
6
 
7
7
  //#region src/intlayerProxyPlugin.ts
8
8
  /**
@@ -37,7 +37,7 @@ const intlayerProxy = (configOptions, options) => {
37
37
  * Retrieves the locale from storage (cookies, localStorage, sessionStorage).
38
38
  */
39
39
  const getStorageLocale = (req) => {
40
- return getLocaleFromStorage({ getCookie: (name) => getCookie(name, req.headers.cookie) });
40
+ return getLocaleFromStorageServer({ getCookie: (name) => getCookie(name, req.headers.cookie) });
41
41
  };
42
42
  /**
43
43
  * Appends locale to search params when routing mode is 'search-params'.
@@ -82,7 +82,7 @@ const intlayerProxy = (configOptions, options) => {
82
82
  */
83
83
  const rewriteUrl = (req, res, newUrl, locale) => {
84
84
  if (req.url !== newUrl) req.url = newUrl;
85
- if (locale) setLocaleInStorage(locale, { setHeader: (name, value) => {
85
+ if (locale) setLocaleInStorageServer(locale, { setHeader: (name, value) => {
86
86
  res.setHeader(name, value);
87
87
  req.headers[name] = value;
88
88
  } });
@@ -1 +1 @@
1
- {"version":3,"file":"intlayerProxyPlugin.mjs","names":[],"sources":["../../src/intlayerProxyPlugin.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { parse } from 'node:url';\nimport { ROUTING_MODE } from '@intlayer/config/defaultValues';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getCanonicalPath,\n getLocalizedPath,\n getRewriteRules,\n localeDetector,\n} from '@intlayer/core/localization';\nimport {\n getCookie,\n getLocaleFromStorage,\n setLocaleInStorage,\n} from '@intlayer/core/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\n/* @ts-ignore - Vite types error */\nimport type { Connect, Plugin } from 'vite';\n\ntype IntlayerProxyPluginOptions = {\n /**\n * A function that allows you to ignore specific requests from the intlayer proxy.\n *\n * @example\n * ```ts\n * export default defineConfig({\n * plugins: [ intlayerProxyPlugin({ ignore: (req) => req.url?.startsWith('/api') }) ],\n * });\n * ```\n *\n * @param req - The incoming request.\n * @returns A boolean value indicating whether to ignore the request.\n */\n ignore?: (req: IncomingMessage) => boolean | undefined;\n};\n\n/**\n * Vite plugin that provides a development middleware for locale-based routing.\n *\n * This plugin mimics the behavior of the Intlayer middleware in Next.js,\n * handling locale detection, redirects, and rewrites during development.\n *\n * @param configOptions - Optional configuration for Intlayer.\n * @param options - Plugin-specific options, like ignoring certain paths.\n * @returns A Vite plugin.\n *\n * @example\n * ```ts\n * import { intlayerProxy } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayerProxy()],\n * });\n * ```\n */\nexport const intlayerProxy = (\n configOptions?: GetConfigurationOptions,\n options?: IntlayerProxyPluginOptions\n): Plugin => {\n const intlayerConfig = getConfiguration(configOptions);\n\n const { internationalization, routing } = intlayerConfig;\n const { locales: supportedLocales, defaultLocale } = internationalization;\n\n const { basePath = '', mode = ROUTING_MODE, rewrite } = routing;\n\n // Track redirect counts per request to detect loops\n const redirectCounts = new Map<string, number>();\n const MAX_REDIRECTS = 10;\n\n // Derived flags from routing.mode\n const noPrefix = mode === 'no-prefix' || mode === 'search-params';\n const prefixDefault = mode === 'prefix-all';\n\n const rewriteRules = getRewriteRules(rewrite, 'url');\n\n /* --------------------------------------------------------------------\n * Helper & Utility Functions\n * --------------------------------------------------------------------\n */\n\n /**\n * Retrieves the locale from storage (cookies, localStorage, sessionStorage).\n */\n const getStorageLocale = (req: IncomingMessage): Locale | undefined => {\n const locale = getLocaleFromStorage({\n getCookie: (name: string) => getCookie(name, req.headers.cookie),\n });\n return locale;\n };\n\n /**\n * Appends locale to search params when routing mode is 'search-params'.\n */\n const appendLocaleSearchIfNeeded = (\n search: string | undefined,\n locale: Locale\n ): string | undefined => {\n if (mode !== 'search-params') return search;\n\n const params = new URLSearchParams(search ?? '');\n\n params.set('locale', locale);\n\n return `?${params.toString()}`;\n };\n\n /**\n * Extracts the locale from the URL pathname if present as the first segment.\n */\n const getPathLocale = (pathname: string): Locale | undefined => {\n // e.g. if pathname is /en/some/page or /en\n // we check if \"en\" is in your supportedLocales\n const segments = pathname.split('/').filter(Boolean);\n const firstSegment = segments[0];\n if (firstSegment && supportedLocales.includes(firstSegment as Locale)) {\n return firstSegment as Locale;\n }\n return undefined;\n };\n\n /**\n * Writes a 301 redirect response with the given new URL.\n */\n const redirectUrl = (\n res: ServerResponse<IncomingMessage>,\n newUrl: string,\n reason?: string,\n originalUrl?: string\n ) => {\n // Track redirect count to detect loops\n if (originalUrl) {\n const count = (redirectCounts.get(originalUrl) || 0) + 1;\n redirectCounts.set(originalUrl, count);\n\n if (count > MAX_REDIRECTS) {\n console.error('[REDIRECT LOOP DETECTED!]', {\n originalUrl,\n redirectCount: count,\n lastRedirectTo: newUrl,\n reason,\n });\n res.writeHead(500, { 'Content-Type': 'text/plain' });\n return res.end(\n `Redirect loop detected: ${count} redirects from ${originalUrl}`\n );\n }\n }\n\n res.writeHead(301, { Location: newUrl });\n return res.end();\n };\n\n /**\n * \"Rewrite\" the request internally by adjusting req.url;\n * we also set the locale in the response header if needed.\n */\n const rewriteUrl = (\n req: Connect.IncomingMessage,\n res: ServerResponse<IncomingMessage>,\n newUrl: string,\n locale?: Locale\n ) => {\n if (req.url !== newUrl) {\n req.url = newUrl;\n }\n // If you want to mimic Next.js's behavior of setting a header for the locale:\n if (locale) {\n setLocaleInStorage(locale, {\n setHeader: (name: string, value: string) => {\n res.setHeader(name, value);\n req.headers[name] = value;\n },\n });\n }\n };\n\n /**\n * Constructs a new path string, optionally including a locale prefix, basePath, and search parameters.\n * - basePath: (e.g., '/myapp')\n * - locale: (e.g., 'en')\n * - currentPath:(e.g., '/products/shoes')\n * - search: (e.g., '?foo=bar')\n */\n const constructPath = (\n locale: Locale,\n currentPath: string,\n search?: string\n ) => {\n // Strip any incoming locale prefix if present\n const pathWithoutPrefix = currentPath.startsWith(`/${locale}`)\n ? currentPath.slice(`/${locale}`.length)\n : currentPath;\n\n // Ensure basePath always starts with '/', and remove trailing slash if needed\n const cleanBasePath = basePath.startsWith('/') ? basePath : `/${basePath}`;\n const normalizedBasePath = cleanBasePath.endsWith('/')\n ? cleanBasePath.slice(0, -1)\n : cleanBasePath;\n\n // In 'search-params' and 'no-prefix' modes, do not prefix the path with the locale\n if (mode === 'no-prefix' || mode === 'search-params') {\n const newPath = search\n ? `${pathWithoutPrefix || '/'}${search}`\n : pathWithoutPrefix || '/';\n return newPath;\n }\n\n // Check if path already starts with locale to avoid double-prefixing\n const pathWithLocalePrefix = currentPath.startsWith(`/${locale}`)\n ? currentPath\n : `/${locale}${currentPath === '/' ? '' : currentPath}`;\n\n let newPath = `${normalizedBasePath}${pathWithLocalePrefix}`;\n\n // Special case: if prefixDefault is false and locale is defaultLocale, remove the locale prefix\n if (!prefixDefault && locale === defaultLocale) {\n newPath = `${normalizedBasePath}${pathWithoutPrefix || '/'}`;\n }\n\n // Append search parameters if provided\n if (search) {\n newPath += search;\n }\n\n return newPath;\n };\n\n /* --------------------------------------------------------------------\n * Handlers that mirror Next.js style logic\n * --------------------------------------------------------------------\n */\n\n /**\n * If `noPrefix` is true, we never prefix the locale in the URL.\n * We simply rewrite the request to the same path, but with the best-chosen locale\n * in a header or search params if desired.\n */\n const handleNoPrefix = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n storageLocale?: Locale;\n originalUrl?: string;\n }) => {\n const pathLocale = getPathLocale(originalPath);\n // Determine the best locale\n let locale = storageLocale ?? defaultLocale;\n\n // Use fallback to localeDetector if no storage locale\n if (!storageLocale) {\n const detectedLocale = localeDetector(\n req.headers as Record<string, string>,\n supportedLocales,\n defaultLocale\n );\n locale = detectedLocale as Locale;\n }\n\n if (pathLocale) {\n const pathWithoutLocale =\n originalPath.slice(`/${pathLocale}`.length) || '/';\n\n const canonicalPath = getCanonicalPath(\n pathWithoutLocale,\n pathLocale,\n rewriteRules\n );\n\n const search = appendLocaleSearchIfNeeded(searchParams, pathLocale);\n\n const redirectPath = search\n ? `${canonicalPath}${search}`\n : `${canonicalPath}${searchParams ?? ''}`;\n\n return redirectUrl(res, redirectPath, undefined, originalUrl);\n }\n\n const canonicalPath = getCanonicalPath(originalPath, locale, rewriteRules);\n\n // In search-params mode, we need to redirect to add the locale search param\n if (mode === 'search-params') {\n // Check if locale search param already exists and matches the detected locale\n const existingSearchParams = new URLSearchParams(searchParams ?? '');\n const existingLocale = existingSearchParams.get('locale');\n\n // If the existing locale matches the detected locale, no redirect needed\n if (existingLocale === locale) {\n // For internal routing, we need to add the locale prefix so the framework can match [locale] param\n const internalPath = `/${locale}${\n canonicalPath === '/' ? '' : canonicalPath\n }`;\n const rewritePath = `${internalPath}${searchParams ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but internally routes to /[locale]/path)\n rewriteUrl(req, res, rewritePath, locale);\n return next();\n }\n\n // Locale param missing or doesn't match - redirect to add/update it\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const redirectPath = search\n ? `${originalPath}${search}`\n : `${originalPath}${searchParams ?? ''}`;\n\n // Redirect to add/update the locale search param (URL changes in browser)\n return redirectUrl(res, redirectPath, undefined, originalUrl);\n }\n\n // For no-prefix mode (not search-params), add locale prefix internally for routing\n const internalPath = `/${locale}${\n canonicalPath === '/' ? '' : canonicalPath\n }`;\n\n // Add search params if needed\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const rewritePath = search\n ? `${internalPath}${search}`\n : `${internalPath}${searchParams ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but internally routes to /[locale]/path)\n rewriteUrl(req, res, rewritePath, locale);\n\n return next();\n };\n\n /**\n * The main prefix logic:\n * - If there's no pathLocale in the URL, we might want to detect & redirect or rewrite\n * - If there is a pathLocale, handle storage mismatch or default locale special cases\n */\n const handlePrefix = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n storageLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale?: Locale;\n storageLocale?: Locale;\n originalUrl?: string;\n }) => {\n // 1. If pathLocale is missing, handle\n if (!pathLocale) {\n handleMissingPathLocale({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n originalUrl,\n });\n return;\n }\n\n // 2. If pathLocale exists, handle it\n handleExistingPathLocale({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n originalUrl,\n });\n };\n\n /**\n * Handles requests where the locale is missing from the URL pathname.\n * We detect a locale from storage / headers / default, then either redirect or rewrite.\n */\n const handleMissingPathLocale = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n storageLocale?: Locale;\n originalUrl?: string;\n }) => {\n // 1. Choose the best locale\n let locale = (storageLocale ??\n localeDetector(\n req.headers as Record<string, string>,\n supportedLocales,\n defaultLocale\n )) as Locale;\n\n // If still invalid, fallback\n if (!supportedLocales.includes(locale)) {\n locale = defaultLocale;\n }\n\n // Resolve to canonical path.\n // If user visits /a-propos (implied 'fr'), we resolve to /about\n const canonicalPath = getCanonicalPath(originalPath, locale, rewriteRules);\n\n // Determine target localized path for redirection\n // /about + 'fr' -> /a-propos\n const targetLocalizedPathResult = getLocalizedPath(\n canonicalPath,\n locale,\n rewriteRules\n );\n const targetLocalizedPath =\n typeof targetLocalizedPathResult === 'string'\n ? targetLocalizedPathResult\n : targetLocalizedPathResult.path;\n\n // Construct new path - preserving original search params\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const newPath = constructPath(locale, targetLocalizedPath, search);\n\n // If we always prefix default or if this is not the default locale, do a 301 redirect\n // so that the user sees the locale in the URL.\n if (prefixDefault || locale !== defaultLocale) {\n return redirectUrl(res, newPath, undefined, originalUrl);\n }\n\n // If we do NOT prefix the default locale, just rewrite in place using canonical path for framework matching.\n // searchParams MUST be preserved here — dropping them causes the framework (e.g. TanStack Start) to\n // see a URL with no search params, trigger a validateSearch normalisation redirect to the prefixed URL\n // (e.g. /en?page=1&...), which the middleware then strips back to /?..., creating an infinite loop.\n rewriteUrl(\n req,\n res,\n `/${locale}${canonicalPath === '/' ? '' : canonicalPath}${searchParams}`,\n locale\n );\n return next();\n };\n\n /**\n * Handles requests where the locale prefix is present in the pathname.\n */\n const handleExistingPathLocale = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale: Locale;\n originalUrl?: string;\n }) => {\n const rawPath = originalPath.slice(`/${pathLocale}`.length);\n\n // Identify the Canonical Path (Internal path)\n // Ex: /a-propos (from URL) -> /about (Canonical)\n const canonicalPath = getCanonicalPath(rawPath, pathLocale, rewriteRules);\n\n // When rewrite rules are configured and the URL is already a valid localized pretty URL\n // (e.g. /fr/essais which maps to canonical /fr/tests), do NOT redirect to canonical.\n //\n // Why: the SPA router (Solid, React Router, Vue Router…) is expected to define routes using\n // the localized paths (e.g. <Route path=\"/essais\">) so the browser URL must stay as-is.\n // A 301 redirect to canonical would:\n // 1. Change the browser URL to the canonical form (/fr/tests)\n // 2. Break subsequent client-side navigation because <A> links produced by getLocalizedUrl\n // point back to the localized URL (/fr/essais) which then has no matching route.\n //\n // We set the locale header and call next() so Vite serves index.html at the pretty URL.\n if (canonicalPath !== rawPath) {\n const newPath = searchParams\n ? `${originalPath}${searchParams}`\n : originalPath;\n rewriteUrl(req, res, newPath, pathLocale);\n return next();\n }\n\n // In prefix modes, respect the URL path locale\n // The path locale takes precedence, and we'll update storage to match\n handleDefaultLocaleRedirect({\n req,\n res,\n next,\n searchParams,\n pathLocale,\n canonicalPath,\n originalUrl,\n });\n };\n\n /**\n * If the path locale is the default locale but we don't want to prefix the default, remove it.\n */\n const handleDefaultLocaleRedirect = ({\n req,\n res,\n next,\n searchParams,\n pathLocale,\n canonicalPath,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n searchParams: string;\n pathLocale: Locale;\n canonicalPath: string;\n originalUrl?: string;\n }) => {\n // If we don't prefix default AND the path locale is the default locale -> remove it\n if (!prefixDefault && pathLocale === defaultLocale) {\n const targetLocalizedPathResult = getLocalizedPath(\n canonicalPath,\n pathLocale,\n rewriteRules\n );\n const targetLocalizedPath =\n typeof targetLocalizedPathResult === 'string'\n ? targetLocalizedPathResult\n : targetLocalizedPathResult.path;\n\n // Construct path without prefix\n const cleanBasePath = basePath.startsWith('/')\n ? basePath\n : `/${basePath}`;\n const normalizedBasePath = cleanBasePath.endsWith('/')\n ? cleanBasePath.slice(0, -1)\n : cleanBasePath;\n\n let finalPath = targetLocalizedPath;\n if (finalPath.startsWith('/')) finalPath = finalPath.slice(1);\n\n const fullPath = `${normalizedBasePath}/${finalPath}`.replace(\n /\\/+/g,\n '/'\n );\n\n return redirectUrl(\n res,\n fullPath + (searchParams ?? ''),\n undefined,\n originalUrl\n );\n }\n\n // If we do prefix default or pathLocale != default, keep as is, but rewrite to canonical internally\n const internalUrl = `/${pathLocale}${\n canonicalPath === '/' ? '' : canonicalPath\n }`;\n const newPath = searchParams\n ? `${internalUrl}${searchParams}`\n : internalUrl;\n\n rewriteUrl(req, res, newPath, pathLocale);\n return next();\n };\n\n return {\n name: 'vite-intlayer-middleware-plugin',\n configureServer: (server) => {\n server.middlewares.use((req, res, next) => {\n // Bypass assets and special Vite endpoints\n if (\n // Custom ignore function\n (options?.ignore?.(req) ?? false) ||\n req.url?.startsWith('/node_modules') ||\n /**\n * /^@vite/ # HMR client and helpers\n * /^@fs/ # file-system import serving\n * /^@id/ # virtual module ids\n * /^@tanstack/start-router-manifest # Tanstack Start Router manifest\n */\n req.url?.startsWith('/@') ||\n /**\n * /^__vite_ping$ # health ping\n * /^__open-in-editor$\n * /^__manifest$ # Remix/RR7 lazyRouteDiscovery\n */\n req.url?.startsWith('/_') ||\n /**\n * ./myFile.js\n */\n req.url?.split('?')[0].match(/\\.[a-z]+$/i) // checks for file extensions\n ) {\n return next();\n }\n\n // Parse original URL for path and query\n const parsedUrl = parse(req.url ?? '/', true);\n const originalPath = parsedUrl.pathname ?? '/';\n const searchParams = parsedUrl.search ?? '';\n\n // Check if there's a locale prefix in the path FIRST\n const pathLocale = getPathLocale(originalPath);\n\n // Attempt to read the locale from storage (cookies, localStorage, etc.)\n const storageLocale = getStorageLocale(req);\n\n // CRITICAL FIX: If there's a valid pathLocale, it takes precedence over storage\n // This prevents race conditions when cookies are stale during locale switches\n const effectiveStorageLocale =\n pathLocale && supportedLocales.includes(pathLocale)\n ? pathLocale\n : storageLocale;\n\n // Store original URL for redirect tracking\n const originalUrl = req.url;\n\n // If noPrefix is true, we skip prefix logic altogether\n if (noPrefix) {\n handleNoPrefix({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale: effectiveStorageLocale,\n originalUrl,\n });\n return;\n }\n\n // Otherwise, handle prefix logic\n handlePrefix({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n storageLocale: effectiveStorageLocale,\n originalUrl,\n });\n });\n\n // Clean up redirect counts periodically (every 100 requests)\n if (redirectCounts.size > 100) {\n redirectCounts.clear();\n }\n },\n };\n};\n\n/**\n * @deprecated Rename to intlayerProxy instead\n *\n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerMiddleware() ],\n * });\n * ```\n */\nexport const intlayerMiddleware = intlayerProxy;\n\n/**\n * @deprecated Rename to intlayerProxy instead\n * \n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerMiddleware() ],\n * });\n * ```\n */\nexport const intLayerMiddlewarePlugin = intlayerProxy;\n"],"mappings":"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"}
1
+ {"version":3,"file":"intlayerProxyPlugin.mjs","names":[],"sources":["../../src/intlayerProxyPlugin.ts"],"sourcesContent":["import type { IncomingMessage, ServerResponse } from 'node:http';\nimport { parse } from 'node:url';\nimport { ROUTING_MODE } from '@intlayer/config/defaultValues';\nimport {\n type GetConfigurationOptions,\n getConfiguration,\n} from '@intlayer/config/node';\nimport {\n getCanonicalPath,\n getLocalizedPath,\n getRewriteRules,\n localeDetector,\n} from '@intlayer/core/localization';\nimport {\n getCookie,\n getLocaleFromStorageServer,\n setLocaleInStorageServer,\n} from '@intlayer/core/utils';\nimport type { Locale } from '@intlayer/types/allLocales';\n/* @ts-ignore - Vite types error */\nimport type { Connect, Plugin } from 'vite';\n\ntype IntlayerProxyPluginOptions = {\n /**\n * A function that allows you to ignore specific requests from the intlayer proxy.\n *\n * @example\n * ```ts\n * export default defineConfig({\n * plugins: [ intlayerProxyPlugin({ ignore: (req) => req.url?.startsWith('/api') }) ],\n * });\n * ```\n *\n * @param req - The incoming request.\n * @returns A boolean value indicating whether to ignore the request.\n */\n ignore?: (req: IncomingMessage) => boolean | undefined;\n};\n\n/**\n * Vite plugin that provides a development middleware for locale-based routing.\n *\n * This plugin mimics the behavior of the Intlayer middleware in Next.js,\n * handling locale detection, redirects, and rewrites during development.\n *\n * @param configOptions - Optional configuration for Intlayer.\n * @param options - Plugin-specific options, like ignoring certain paths.\n * @returns A Vite plugin.\n *\n * @example\n * ```ts\n * import { intlayerProxy } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayerProxy()],\n * });\n * ```\n */\nexport const intlayerProxy = (\n configOptions?: GetConfigurationOptions,\n options?: IntlayerProxyPluginOptions\n): Plugin => {\n const intlayerConfig = getConfiguration(configOptions);\n\n const { internationalization, routing } = intlayerConfig;\n const { locales: supportedLocales, defaultLocale } = internationalization;\n\n const { basePath = '', mode = ROUTING_MODE, rewrite } = routing;\n\n // Track redirect counts per request to detect loops\n const redirectCounts = new Map<string, number>();\n const MAX_REDIRECTS = 10;\n\n // Derived flags from routing.mode\n const noPrefix = mode === 'no-prefix' || mode === 'search-params';\n const prefixDefault = mode === 'prefix-all';\n\n const rewriteRules = getRewriteRules(rewrite, 'url');\n\n /* --------------------------------------------------------------------\n * Helper & Utility Functions\n * --------------------------------------------------------------------\n */\n\n /**\n * Retrieves the locale from storage (cookies, localStorage, sessionStorage).\n */\n const getStorageLocale = (req: IncomingMessage): Locale | undefined => {\n const locale = getLocaleFromStorageServer({\n getCookie: (name: string) => getCookie(name, req.headers.cookie),\n });\n return locale;\n };\n\n /**\n * Appends locale to search params when routing mode is 'search-params'.\n */\n const appendLocaleSearchIfNeeded = (\n search: string | undefined,\n locale: Locale\n ): string | undefined => {\n if (mode !== 'search-params') return search;\n\n const params = new URLSearchParams(search ?? '');\n\n params.set('locale', locale);\n\n return `?${params.toString()}`;\n };\n\n /**\n * Extracts the locale from the URL pathname if present as the first segment.\n */\n const getPathLocale = (pathname: string): Locale | undefined => {\n // e.g. if pathname is /en/some/page or /en\n // we check if \"en\" is in your supportedLocales\n const segments = pathname.split('/').filter(Boolean);\n const firstSegment = segments[0];\n if (firstSegment && supportedLocales.includes(firstSegment as Locale)) {\n return firstSegment as Locale;\n }\n return undefined;\n };\n\n /**\n * Writes a 301 redirect response with the given new URL.\n */\n const redirectUrl = (\n res: ServerResponse<IncomingMessage>,\n newUrl: string,\n reason?: string,\n originalUrl?: string\n ) => {\n // Track redirect count to detect loops\n if (originalUrl) {\n const count = (redirectCounts.get(originalUrl) || 0) + 1;\n redirectCounts.set(originalUrl, count);\n\n if (count > MAX_REDIRECTS) {\n console.error('[REDIRECT LOOP DETECTED!]', {\n originalUrl,\n redirectCount: count,\n lastRedirectTo: newUrl,\n reason,\n });\n res.writeHead(500, { 'Content-Type': 'text/plain' });\n return res.end(\n `Redirect loop detected: ${count} redirects from ${originalUrl}`\n );\n }\n }\n\n res.writeHead(301, { Location: newUrl });\n return res.end();\n };\n\n /**\n * \"Rewrite\" the request internally by adjusting req.url;\n * we also set the locale in the response header if needed.\n */\n const rewriteUrl = (\n req: Connect.IncomingMessage,\n res: ServerResponse<IncomingMessage>,\n newUrl: string,\n locale?: Locale\n ) => {\n if (req.url !== newUrl) {\n req.url = newUrl;\n }\n // If you want to mimic Next.js's behavior of setting a header for the locale:\n if (locale) {\n setLocaleInStorageServer(locale, {\n setHeader: (name: string, value: string) => {\n res.setHeader(name, value);\n req.headers[name] = value;\n },\n });\n }\n };\n\n /**\n * Constructs a new path string, optionally including a locale prefix, basePath, and search parameters.\n * - basePath: (e.g., '/myapp')\n * - locale: (e.g., 'en')\n * - currentPath:(e.g., '/products/shoes')\n * - search: (e.g., '?foo=bar')\n */\n const constructPath = (\n locale: Locale,\n currentPath: string,\n search?: string\n ) => {\n // Strip any incoming locale prefix if present\n const pathWithoutPrefix = currentPath.startsWith(`/${locale}`)\n ? currentPath.slice(`/${locale}`.length)\n : currentPath;\n\n // Ensure basePath always starts with '/', and remove trailing slash if needed\n const cleanBasePath = basePath.startsWith('/') ? basePath : `/${basePath}`;\n const normalizedBasePath = cleanBasePath.endsWith('/')\n ? cleanBasePath.slice(0, -1)\n : cleanBasePath;\n\n // In 'search-params' and 'no-prefix' modes, do not prefix the path with the locale\n if (mode === 'no-prefix' || mode === 'search-params') {\n const newPath = search\n ? `${pathWithoutPrefix || '/'}${search}`\n : pathWithoutPrefix || '/';\n return newPath;\n }\n\n // Check if path already starts with locale to avoid double-prefixing\n const pathWithLocalePrefix = currentPath.startsWith(`/${locale}`)\n ? currentPath\n : `/${locale}${currentPath === '/' ? '' : currentPath}`;\n\n let newPath = `${normalizedBasePath}${pathWithLocalePrefix}`;\n\n // Special case: if prefixDefault is false and locale is defaultLocale, remove the locale prefix\n if (!prefixDefault && locale === defaultLocale) {\n newPath = `${normalizedBasePath}${pathWithoutPrefix || '/'}`;\n }\n\n // Append search parameters if provided\n if (search) {\n newPath += search;\n }\n\n return newPath;\n };\n\n /* --------------------------------------------------------------------\n * Handlers that mirror Next.js style logic\n * --------------------------------------------------------------------\n */\n\n /**\n * If `noPrefix` is true, we never prefix the locale in the URL.\n * We simply rewrite the request to the same path, but with the best-chosen locale\n * in a header or search params if desired.\n */\n const handleNoPrefix = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n storageLocale?: Locale;\n originalUrl?: string;\n }) => {\n const pathLocale = getPathLocale(originalPath);\n // Determine the best locale\n let locale = storageLocale ?? defaultLocale;\n\n // Use fallback to localeDetector if no storage locale\n if (!storageLocale) {\n const detectedLocale = localeDetector(\n req.headers as Record<string, string>,\n supportedLocales,\n defaultLocale\n );\n locale = detectedLocale as Locale;\n }\n\n if (pathLocale) {\n const pathWithoutLocale =\n originalPath.slice(`/${pathLocale}`.length) || '/';\n\n const canonicalPath = getCanonicalPath(\n pathWithoutLocale,\n pathLocale,\n rewriteRules\n );\n\n const search = appendLocaleSearchIfNeeded(searchParams, pathLocale);\n\n const redirectPath = search\n ? `${canonicalPath}${search}`\n : `${canonicalPath}${searchParams ?? ''}`;\n\n return redirectUrl(res, redirectPath, undefined, originalUrl);\n }\n\n const canonicalPath = getCanonicalPath(originalPath, locale, rewriteRules);\n\n // In search-params mode, we need to redirect to add the locale search param\n if (mode === 'search-params') {\n // Check if locale search param already exists and matches the detected locale\n const existingSearchParams = new URLSearchParams(searchParams ?? '');\n const existingLocale = existingSearchParams.get('locale');\n\n // If the existing locale matches the detected locale, no redirect needed\n if (existingLocale === locale) {\n // For internal routing, we need to add the locale prefix so the framework can match [locale] param\n const internalPath = `/${locale}${\n canonicalPath === '/' ? '' : canonicalPath\n }`;\n const rewritePath = `${internalPath}${searchParams ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but internally routes to /[locale]/path)\n rewriteUrl(req, res, rewritePath, locale);\n return next();\n }\n\n // Locale param missing or doesn't match - redirect to add/update it\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const redirectPath = search\n ? `${originalPath}${search}`\n : `${originalPath}${searchParams ?? ''}`;\n\n // Redirect to add/update the locale search param (URL changes in browser)\n return redirectUrl(res, redirectPath, undefined, originalUrl);\n }\n\n // For no-prefix mode (not search-params), add locale prefix internally for routing\n const internalPath = `/${locale}${\n canonicalPath === '/' ? '' : canonicalPath\n }`;\n\n // Add search params if needed\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const rewritePath = search\n ? `${internalPath}${search}`\n : `${internalPath}${searchParams ?? ''}`;\n\n // Rewrite internally (URL stays the same in browser, but internally routes to /[locale]/path)\n rewriteUrl(req, res, rewritePath, locale);\n\n return next();\n };\n\n /**\n * The main prefix logic:\n * - If there's no pathLocale in the URL, we might want to detect & redirect or rewrite\n * - If there is a pathLocale, handle storage mismatch or default locale special cases\n */\n const handlePrefix = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n storageLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale?: Locale;\n storageLocale?: Locale;\n originalUrl?: string;\n }) => {\n // 1. If pathLocale is missing, handle\n if (!pathLocale) {\n handleMissingPathLocale({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n originalUrl,\n });\n return;\n }\n\n // 2. If pathLocale exists, handle it\n handleExistingPathLocale({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n originalUrl,\n });\n };\n\n /**\n * Handles requests where the locale is missing from the URL pathname.\n * We detect a locale from storage / headers / default, then either redirect or rewrite.\n */\n const handleMissingPathLocale = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n storageLocale?: Locale;\n originalUrl?: string;\n }) => {\n // 1. Choose the best locale\n let locale = (storageLocale ??\n localeDetector(\n req.headers as Record<string, string>,\n supportedLocales,\n defaultLocale\n )) as Locale;\n\n // If still invalid, fallback\n if (!supportedLocales.includes(locale)) {\n locale = defaultLocale;\n }\n\n // Resolve to canonical path.\n // If user visits /a-propos (implied 'fr'), we resolve to /about\n const canonicalPath = getCanonicalPath(originalPath, locale, rewriteRules);\n\n // Determine target localized path for redirection\n // /about + 'fr' -> /a-propos\n const targetLocalizedPathResult = getLocalizedPath(\n canonicalPath,\n locale,\n rewriteRules\n );\n const targetLocalizedPath =\n typeof targetLocalizedPathResult === 'string'\n ? targetLocalizedPathResult\n : targetLocalizedPathResult.path;\n\n // Construct new path - preserving original search params\n const search = appendLocaleSearchIfNeeded(searchParams, locale);\n const newPath = constructPath(locale, targetLocalizedPath, search);\n\n // If we always prefix default or if this is not the default locale, do a 301 redirect\n // so that the user sees the locale in the URL.\n if (prefixDefault || locale !== defaultLocale) {\n return redirectUrl(res, newPath, undefined, originalUrl);\n }\n\n // If we do NOT prefix the default locale, just rewrite in place using canonical path for framework matching.\n // searchParams MUST be preserved here — dropping them causes the framework (e.g. TanStack Start) to\n // see a URL with no search params, trigger a validateSearch normalisation redirect to the prefixed URL\n // (e.g. /en?page=1&...), which the middleware then strips back to /?..., creating an infinite loop.\n rewriteUrl(\n req,\n res,\n `/${locale}${canonicalPath === '/' ? '' : canonicalPath}${searchParams}`,\n locale\n );\n return next();\n };\n\n /**\n * Handles requests where the locale prefix is present in the pathname.\n */\n const handleExistingPathLocale = ({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n originalPath: string;\n searchParams: string;\n pathLocale: Locale;\n originalUrl?: string;\n }) => {\n const rawPath = originalPath.slice(`/${pathLocale}`.length);\n\n // Identify the Canonical Path (Internal path)\n // Ex: /a-propos (from URL) -> /about (Canonical)\n const canonicalPath = getCanonicalPath(rawPath, pathLocale, rewriteRules);\n\n // When rewrite rules are configured and the URL is already a valid localized pretty URL\n // (e.g. /fr/essais which maps to canonical /fr/tests), do NOT redirect to canonical.\n //\n // Why: the SPA router (Solid, React Router, Vue Router…) is expected to define routes using\n // the localized paths (e.g. <Route path=\"/essais\">) so the browser URL must stay as-is.\n // A 301 redirect to canonical would:\n // 1. Change the browser URL to the canonical form (/fr/tests)\n // 2. Break subsequent client-side navigation because <A> links produced by getLocalizedUrl\n // point back to the localized URL (/fr/essais) which then has no matching route.\n //\n // We set the locale header and call next() so Vite serves index.html at the pretty URL.\n if (canonicalPath !== rawPath) {\n const newPath = searchParams\n ? `${originalPath}${searchParams}`\n : originalPath;\n rewriteUrl(req, res, newPath, pathLocale);\n return next();\n }\n\n // In prefix modes, respect the URL path locale\n // The path locale takes precedence, and we'll update storage to match\n handleDefaultLocaleRedirect({\n req,\n res,\n next,\n searchParams,\n pathLocale,\n canonicalPath,\n originalUrl,\n });\n };\n\n /**\n * If the path locale is the default locale but we don't want to prefix the default, remove it.\n */\n const handleDefaultLocaleRedirect = ({\n req,\n res,\n next,\n searchParams,\n pathLocale,\n canonicalPath,\n originalUrl,\n }: {\n req: Connect.IncomingMessage;\n res: ServerResponse<IncomingMessage>;\n next: Connect.NextFunction;\n searchParams: string;\n pathLocale: Locale;\n canonicalPath: string;\n originalUrl?: string;\n }) => {\n // If we don't prefix default AND the path locale is the default locale -> remove it\n if (!prefixDefault && pathLocale === defaultLocale) {\n const targetLocalizedPathResult = getLocalizedPath(\n canonicalPath,\n pathLocale,\n rewriteRules\n );\n const targetLocalizedPath =\n typeof targetLocalizedPathResult === 'string'\n ? targetLocalizedPathResult\n : targetLocalizedPathResult.path;\n\n // Construct path without prefix\n const cleanBasePath = basePath.startsWith('/')\n ? basePath\n : `/${basePath}`;\n const normalizedBasePath = cleanBasePath.endsWith('/')\n ? cleanBasePath.slice(0, -1)\n : cleanBasePath;\n\n let finalPath = targetLocalizedPath;\n if (finalPath.startsWith('/')) finalPath = finalPath.slice(1);\n\n const fullPath = `${normalizedBasePath}/${finalPath}`.replace(\n /\\/+/g,\n '/'\n );\n\n return redirectUrl(\n res,\n fullPath + (searchParams ?? ''),\n undefined,\n originalUrl\n );\n }\n\n // If we do prefix default or pathLocale != default, keep as is, but rewrite to canonical internally\n const internalUrl = `/${pathLocale}${\n canonicalPath === '/' ? '' : canonicalPath\n }`;\n const newPath = searchParams\n ? `${internalUrl}${searchParams}`\n : internalUrl;\n\n rewriteUrl(req, res, newPath, pathLocale);\n return next();\n };\n\n return {\n name: 'vite-intlayer-middleware-plugin',\n configureServer: (server) => {\n server.middlewares.use((req, res, next) => {\n // Bypass assets and special Vite endpoints\n if (\n // Custom ignore function\n (options?.ignore?.(req) ?? false) ||\n req.url?.startsWith('/node_modules') ||\n /**\n * /^@vite/ # HMR client and helpers\n * /^@fs/ # file-system import serving\n * /^@id/ # virtual module ids\n * /^@tanstack/start-router-manifest # Tanstack Start Router manifest\n */\n req.url?.startsWith('/@') ||\n /**\n * /^__vite_ping$ # health ping\n * /^__open-in-editor$\n * /^__manifest$ # Remix/RR7 lazyRouteDiscovery\n */\n req.url?.startsWith('/_') ||\n /**\n * ./myFile.js\n */\n req.url?.split('?')[0].match(/\\.[a-z]+$/i) // checks for file extensions\n ) {\n return next();\n }\n\n // Parse original URL for path and query\n const parsedUrl = parse(req.url ?? '/', true);\n const originalPath = parsedUrl.pathname ?? '/';\n const searchParams = parsedUrl.search ?? '';\n\n // Check if there's a locale prefix in the path FIRST\n const pathLocale = getPathLocale(originalPath);\n\n // Attempt to read the locale from storage (cookies, localStorage, etc.)\n const storageLocale = getStorageLocale(req);\n\n // CRITICAL FIX: If there's a valid pathLocale, it takes precedence over storage\n // This prevents race conditions when cookies are stale during locale switches\n const effectiveStorageLocale =\n pathLocale && supportedLocales.includes(pathLocale)\n ? pathLocale\n : storageLocale;\n\n // Store original URL for redirect tracking\n const originalUrl = req.url;\n\n // If noPrefix is true, we skip prefix logic altogether\n if (noPrefix) {\n handleNoPrefix({\n req,\n res,\n next,\n originalPath,\n searchParams,\n storageLocale: effectiveStorageLocale,\n originalUrl,\n });\n return;\n }\n\n // Otherwise, handle prefix logic\n handlePrefix({\n req,\n res,\n next,\n originalPath,\n searchParams,\n pathLocale,\n storageLocale: effectiveStorageLocale,\n originalUrl,\n });\n });\n\n // Clean up redirect counts periodically (every 100 requests)\n if (redirectCounts.size > 100) {\n redirectCounts.clear();\n }\n },\n };\n};\n\n/**\n * @deprecated Rename to intlayerProxy instead\n *\n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n *\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerMiddleware() ],\n * });\n * ```\n */\nexport const intlayerMiddleware = intlayerProxy;\n\n/**\n * @deprecated Rename to intlayerProxy instead\n * \n * A Vite plugin that integrates a logic similar to the Next.js intlayer middleware.\n\n * ```ts\n * // Example usage of the plugin in a Vite configuration\n * export default defineConfig({\n * plugins: [ intlayerMiddleware() ],\n * });\n * ```\n */\nexport const intLayerMiddlewarePlugin = intlayerProxy;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"intlayerPlugin.d.ts","names":[],"sources":["../../src/intlayerPlugin.ts"],"mappings":";;;;;;AAqCA;;;;;;;;;AAkFA;;;;;;;;;AAaA;;;cA/Fa,cAAA,GACX,aAAA,GAAgB,uBAAA,KACf,YAAA;;;;;;;;;;;cAgFU,QAAA,GAAQ,aAAA,GAjFH,uBAAA,KACf,YAAA;;;;;;;;;;;;;cA6FU,cAAA,GAAc,aAAA,GA9FT,uBAAA,KACf,YAAA"}
1
+ {"version":3,"file":"intlayerPlugin.d.ts","names":[],"sources":["../../src/intlayerPlugin.ts"],"mappings":";;;;;;AA0CA;;;;;;;;;AA6FA;;;;;;;;;AAaA;;;cA1Ga,cAAA,GACX,aAAA,GAAgB,uBAAA,KACf,YAAA;;;;;;;;;;;cA2FU,QAAA,GAAQ,aAAA,GA5FH,uBAAA,KACf,YAAA;;;;;;;;;;;;;cAwGU,cAAA,GAAc,aAAA,GAzGT,uBAAA,KACf,YAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-intlayer",
3
- "version": "8.5.2",
3
+ "version": "8.6.0",
4
4
  "private": false,
5
5
  "description": "A Vite plugin for seamless internationalization (i18n), providing locale detection, redirection, and environment-based configuration",
6
6
  "keywords": [
@@ -77,13 +77,13 @@
77
77
  },
78
78
  "dependencies": {
79
79
  "@babel/core": "7.29.0",
80
- "@intlayer/babel": "8.5.2",
81
- "@intlayer/chokidar": "8.5.2",
82
- "@intlayer/config": "8.5.2",
83
- "@intlayer/core": "8.5.2",
84
- "@intlayer/dictionaries-entry": "8.5.2",
85
- "@intlayer/types": "8.5.2",
86
- "intlayer": "8.5.2"
80
+ "@intlayer/babel": "8.6.0",
81
+ "@intlayer/chokidar": "8.6.0",
82
+ "@intlayer/config": "8.6.0",
83
+ "@intlayer/core": "8.6.0",
84
+ "@intlayer/dictionaries-entry": "8.6.0",
85
+ "@intlayer/types": "8.6.0",
86
+ "intlayer": "8.6.0"
87
87
  },
88
88
  "devDependencies": {
89
89
  "@types/babel__core": "7.20.5",
@@ -92,9 +92,9 @@
92
92
  "@utils/ts-config-types": "1.0.4",
93
93
  "@utils/tsdown-config": "1.0.4",
94
94
  "rimraf": "6.1.3",
95
- "tsdown": "0.21.4",
95
+ "tsdown": "0.21.7",
96
96
  "typescript": "6.0.2",
97
- "vitest": "4.1.1"
97
+ "vitest": "4.1.2"
98
98
  },
99
99
  "peerDependencies": {
100
100
  "@babel/core": ">=6.0.0",