@intlayer/config 8.7.12 → 8.7.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -190,7 +190,22 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
190
190
  <li><a href="https://intlayer.org/doc/environment/vite-and-react" rel=''>Vite + React</a></li>
191
191
  <li><a href="https://intlayer.org/doc/environment/vite-and-react" rel=''>Vite + React using Compiler</a></li>
192
192
  <li><a href="https://intlayer.org/doc/environment/vite-and-react/compiler" rel=''>React-router-v7</a></li>
193
- <li><a href="https://intlayer.org/doc/environment/vite-and-react/tanstack-start" rel=''>Tanstack start</a></li>
193
+ <li><a href="https://intlayer.org/doc/environment/tanstack-start" rel=''>Tanstack start</a>
194
+ <ul>
195
+ <li><a href="https://intlayer.org/doc/environment/tanstack-start/solid" rel=''>Solid</a></li>
196
+ </ul>
197
+ </li>
198
+ <li><a href="https://intlayer.org/doc/environment/astro" rel=''>Astro</a>
199
+ <ul>
200
+ <li><a href="https://intlayer.org/doc/environment/astro/react" rel=''>React</a></li>
201
+ <li><a href="https://intlayer.org/doc/environment/astro/vue" rel=''>Vue</a></li>
202
+ <li><a href="https://intlayer.org/doc/environment/astro/svelte" rel=''>Svelte</a></li>
203
+ <li><a href="https://intlayer.org/doc/environment/astro/solid" rel=''>Solid</a></li>
204
+ <li><a href="https://intlayer.org/doc/environment/astro/vanilla" rel=''>Vanilla JS</a></li>
205
+ <li><a href="https://intlayer.org/doc/environment/astro/lit" rel=''>Lit</a></li>
206
+ </ul>
207
+ </li>
208
+
194
209
  <li><a href="https://intlayer.org/doc/environment/react-native-and-expo" rel=''>React Native</a></li>
195
210
  <li><a href="https://intlayer.org/doc/environment/vite-and-svelte" rel=''>Vite + Svelte</a></li>
196
211
  <li><a href="https://intlayer.org/doc/environment/sveltekit" rel=''>SvelteKit</a></li>
@@ -212,6 +227,17 @@ Explore our comprehensive documentation to get started with Intlayer and learn h
212
227
  </ul>
213
228
  </details>
214
229
 
230
+ <details>
231
+ <summary style="font-size:16px; font-weight:bold;">📊 Benchmark</summary>
232
+ <ul>
233
+ <li><a href="https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/nextjs.md" rel=''>Next.js</a></li>
234
+ <li><a href="https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/tanstack.md" rel=''>TanStack Start</a></li>
235
+ <li><a href="https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/vue.md" rel=''>Vue</a></li>
236
+ <li><a href="https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/solid.md" rel=''>Solid</a></li>
237
+ <li><a href="https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/svelte.md" rel=''>Svelte</a></li>
238
+ </ul>
239
+ </details>
240
+
215
241
  <details>
216
242
  <summary style="font-size:16px; font-weight:bold;">📰 Blog</summary>
217
243
  <ul>
@@ -2,6 +2,15 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
 
3
3
  //#region src/envVars/envVars.ts
4
4
  /**
5
+ * Converts a camelCase node-type string to SCREAMING_SNAKE_CASE so that
6
+ * the generated env-var name matches what the plugin source files check.
7
+ *
8
+ * @example
9
+ * toScreamingSnakeCase('reactNode') // 'REACT_NODE'
10
+ * toScreamingSnakeCase('markdown') // 'MARKDOWN'
11
+ */
12
+ const toScreamingSnakeCase = (str) => str.replace(/([A-Z])/g, "_$1").toUpperCase().replace(/^_/, "");
13
+ /**
5
14
  * Converts a list of unused NodeType keys into env-var definitions.
6
15
  * Set to `"false"` so bundlers can eliminate the corresponding plugin code.
7
16
  *
@@ -9,11 +18,11 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
9
18
  * formatNodeTypeToEnvVar(['enumeration'])
10
19
  * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '"false"' }
11
20
  *
12
- * formatNodeTypeToEnvVar(['enumeration'], true)
13
- * // { 'process.env.INTLAYER_NODE_TYPE_ENUMERATION': '"false"' }
21
+ * formatNodeTypeToEnvVar(['reactNode'], (k) => `process.env.${k}`, (v) => `"${v}"`)
22
+ * // { 'process.env.INTLAYER_NODE_TYPE_REACT_NODE': '"false"' }
14
23
  */
15
24
  const formatNodeTypeToEnvVar = (nodeTypes, wrapKey = (key) => key, wrapValue = (value) => value) => nodeTypes.reduce((acc, nodeType) => {
16
- acc[wrapKey(`INTLAYER_NODE_TYPE_${nodeType.toUpperCase()}`)] = wrapValue("false");
25
+ acc[wrapKey(`INTLAYER_NODE_TYPE_${toScreamingSnakeCase(nodeType)}`)] = wrapValue("false");
17
26
  return acc;
18
27
  }, {});
19
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"envVars.cjs","names":[],"sources":["../../../src/envVars/envVars.ts"],"sourcesContent":["import type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Converts a list of unused NodeType keys into env-var definitions.\n * Set to `\"false\"` so bundlers can eliminate the corresponding plugin code.\n *\n * @example\n * formatNodeTypeToEnvVar(['enumeration'])\n * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '\"false\"' }\n *\n * formatNodeTypeToEnvVar(['enumeration'], true)\n * // { 'process.env.INTLAYER_NODE_TYPE_ENUMERATION': '\"false\"' }\n */\nexport const formatNodeTypeToEnvVar = (\n nodeTypes: string[],\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> =>\n nodeTypes.reduce(\n (acc, nodeType) => {\n acc[wrapKey(`INTLAYER_NODE_TYPE_${nodeType.toUpperCase()}`)] =\n wrapValue('false');\n return acc;\n },\n {} as Record<string, string>\n );\n\n/**\n * Returns env-var definitions for the full Intlayer config to be injected at\n * build time. Allows bundlers to dead-code-eliminate unused routing modes,\n * rewrite logic, storage mechanisms, and editor code.\n *\n * @example\n * getConfigEnvVars(config)\n * // { INTLAYER_ROUTING_MODE: '\"prefix-no-default\"', INTLAYER_ROUTING_REWRITE_RULES: '\"false\"', ... }\n *\n * getConfigEnvVars(config, true)\n * // { 'process.env.INTLAYER_ROUTING_MODE': '\"prefix-no-default\"', ... }\n */\nexport const getConfigEnvVars = (\n config: IntlayerConfig,\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> => {\n const { routing, editor } = config;\n\n const envVars: Record<string, string> = {\n [wrapKey('INTLAYER_ROUTING_MODE')]: wrapValue(routing.mode),\n };\n\n if (!routing.rewrite) {\n envVars[wrapKey('INTLAYER_ROUTING_REWRITE_RULES')] = wrapValue('false');\n }\n\n if (!routing.domains || Object.keys(routing.domains).length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_DOMAINS')] = wrapValue('false');\n }\n\n if (!routing.storage.cookies || routing.storage.cookies.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_COOKIES')] = wrapValue('false');\n }\n\n if (\n !routing.storage.localStorage ||\n routing.storage.localStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_LOCALSTORAGE')] =\n wrapValue('false');\n }\n\n if (\n !routing.storage.sessionStorage ||\n routing.storage.sessionStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE')] =\n wrapValue('false');\n }\n\n if (!routing.storage.headers || routing.storage.headers.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_HEADERS')] = wrapValue('false');\n }\n\n if (editor?.enabled === false) {\n envVars[wrapKey('INTLAYER_EDITOR_ENABLED')] = wrapValue('false');\n }\n\n return envVars;\n};\n"],"mappings":";;;;;;;;;;;;;;AAaA,MAAa,0BACX,WACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UAE/B,UAAU,QACP,KAAK,aAAa;AACjB,KAAI,QAAQ,sBAAsB,SAAS,aAAa,GAAG,IACzD,UAAU,QAAQ;AACpB,QAAO;GAET,EAAE,CACH;;;;;;;;;;;;;AAcH,MAAa,oBACX,QACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UACJ;CAC3B,MAAM,EAAE,SAAS,WAAW;CAE5B,MAAM,UAAkC,GACrC,QAAQ,wBAAwB,GAAG,UAAU,QAAQ,KAAK,EAC5D;AAED,KAAI,CAAC,QAAQ,QACX,SAAQ,QAAQ,iCAAiC,IAAI,UAAU,QAAQ;AAGzE,KAAI,CAAC,QAAQ,WAAW,OAAO,KAAK,QAAQ,QAAQ,CAAC,WAAW,EAC9D,SAAQ,QAAQ,2BAA2B,IAAI,UAAU,QAAQ;AAGnE,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KACE,CAAC,QAAQ,QAAQ,gBACjB,QAAQ,QAAQ,aAAa,WAAW,EAExC,SAAQ,QAAQ,wCAAwC,IACtD,UAAU,QAAQ;AAGtB,KACE,CAAC,QAAQ,QAAQ,kBACjB,QAAQ,QAAQ,eAAe,WAAW,EAE1C,SAAQ,QAAQ,0CAA0C,IACxD,UAAU,QAAQ;AAGtB,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KAAI,QAAQ,YAAY,MACtB,SAAQ,QAAQ,0BAA0B,IAAI,UAAU,QAAQ;AAGlE,QAAO"}
1
+ {"version":3,"file":"envVars.cjs","names":[],"sources":["../../../src/envVars/envVars.ts"],"sourcesContent":["import type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Converts a camelCase node-type string to SCREAMING_SNAKE_CASE so that\n * the generated env-var name matches what the plugin source files check.\n *\n * @example\n * toScreamingSnakeCase('reactNode') // 'REACT_NODE'\n * toScreamingSnakeCase('markdown') // 'MARKDOWN'\n */\nconst toScreamingSnakeCase = (str: string): string =>\n str\n .replace(/([A-Z])/g, '_$1')\n .toUpperCase()\n .replace(/^_/, ''); // strip any leading underscore\n\n/**\n * Converts a list of unused NodeType keys into env-var definitions.\n * Set to `\"false\"` so bundlers can eliminate the corresponding plugin code.\n *\n * @example\n * formatNodeTypeToEnvVar(['enumeration'])\n * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '\"false\"' }\n *\n * formatNodeTypeToEnvVar(['reactNode'], (k) => `process.env.${k}`, (v) => `\"${v}\"`)\n * // { 'process.env.INTLAYER_NODE_TYPE_REACT_NODE': '\"false\"' }\n */\nexport const formatNodeTypeToEnvVar = (\n nodeTypes: string[],\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> =>\n nodeTypes.reduce(\n (acc, nodeType) => {\n acc[wrapKey(`INTLAYER_NODE_TYPE_${toScreamingSnakeCase(nodeType)}`)] =\n wrapValue('false');\n return acc;\n },\n {} as Record<string, string>\n );\n\n/**\n * Returns env-var definitions for the full Intlayer config to be injected at\n * build time. Allows bundlers to dead-code-eliminate unused routing modes,\n * rewrite logic, storage mechanisms, and editor code.\n *\n * @example\n * getConfigEnvVars(config)\n * // { INTLAYER_ROUTING_MODE: '\"prefix-no-default\"', INTLAYER_ROUTING_REWRITE_RULES: '\"false\"', ... }\n *\n * getConfigEnvVars(config, true)\n * // { 'process.env.INTLAYER_ROUTING_MODE': '\"prefix-no-default\"', ... }\n */\nexport const getConfigEnvVars = (\n config: IntlayerConfig,\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> => {\n const { routing, editor } = config;\n\n const envVars: Record<string, string> = {\n [wrapKey('INTLAYER_ROUTING_MODE')]: wrapValue(routing.mode),\n };\n\n if (!routing.rewrite) {\n envVars[wrapKey('INTLAYER_ROUTING_REWRITE_RULES')] = wrapValue('false');\n }\n\n if (!routing.domains || Object.keys(routing.domains).length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_DOMAINS')] = wrapValue('false');\n }\n\n if (!routing.storage.cookies || routing.storage.cookies.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_COOKIES')] = wrapValue('false');\n }\n\n if (\n !routing.storage.localStorage ||\n routing.storage.localStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_LOCALSTORAGE')] =\n wrapValue('false');\n }\n\n if (\n !routing.storage.sessionStorage ||\n routing.storage.sessionStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE')] =\n wrapValue('false');\n }\n\n if (!routing.storage.headers || routing.storage.headers.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_HEADERS')] = wrapValue('false');\n }\n\n if (editor?.enabled === false) {\n envVars[wrapKey('INTLAYER_EDITOR_ENABLED')] = wrapValue('false');\n }\n\n return envVars;\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAM,wBAAwB,QAC5B,IACG,QAAQ,YAAY,MAAM,CAC1B,aAAa,CACb,QAAQ,MAAM,GAAG;;;;;;;;;;;;AAatB,MAAa,0BACX,WACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UAE/B,UAAU,QACP,KAAK,aAAa;AACjB,KAAI,QAAQ,sBAAsB,qBAAqB,SAAS,GAAG,IACjE,UAAU,QAAQ;AACpB,QAAO;GAET,EAAE,CACH;;;;;;;;;;;;;AAcH,MAAa,oBACX,QACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UACJ;CAC3B,MAAM,EAAE,SAAS,WAAW;CAE5B,MAAM,UAAkC,GACrC,QAAQ,wBAAwB,GAAG,UAAU,QAAQ,KAAK,EAC5D;AAED,KAAI,CAAC,QAAQ,QACX,SAAQ,QAAQ,iCAAiC,IAAI,UAAU,QAAQ;AAGzE,KAAI,CAAC,QAAQ,WAAW,OAAO,KAAK,QAAQ,QAAQ,CAAC,WAAW,EAC9D,SAAQ,QAAQ,2BAA2B,IAAI,UAAU,QAAQ;AAGnE,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KACE,CAAC,QAAQ,QAAQ,gBACjB,QAAQ,QAAQ,aAAa,WAAW,EAExC,SAAQ,QAAQ,wCAAwC,IACtD,UAAU,QAAQ;AAGtB,KACE,CAAC,QAAQ,QAAQ,kBACjB,QAAQ,QAAQ,eAAe,WAAW,EAE1C,SAAQ,QAAQ,0CAA0C,IACxD,UAAU,QAAQ;AAGtB,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KAAI,QAAQ,YAAY,MACtB,SAAQ,QAAQ,0BAA0B,IAAI,UAAU,QAAQ;AAGlE,QAAO"}
@@ -3,6 +3,18 @@ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
4
4
 
5
5
  //#region src/utils/getUsedNodeTypes.ts
6
+ /**
7
+ * Detect whether a plain object looks like a serialized React element.
8
+ * React serializes JSX as: { key, props, _owner, _store }.
9
+ * Preact serializes VNodes similarly with a `_store` field.
10
+ */
11
+ const isReactLikeElement = (obj) => typeof obj.props !== "undefined" && "key" in obj && typeof obj._store !== "undefined";
12
+ /**
13
+ * Detect whether a plain object looks like a serialized Solid element.
14
+ * Solid JSX is serialized as: { type, props } without the React-specific
15
+ * `_store` / `_owner` internal fields.
16
+ */
17
+ const isSolidLikeElement = (obj) => typeof obj.props !== "undefined" && typeof obj._store === "undefined" && typeof obj.nodeType === "undefined" && "type" in obj;
6
18
  /** Recursively collect every `nodeType` string found in a value. */
7
19
  const collectNodeTypes = (value, result) => {
8
20
  if (!value || typeof value !== "object") return;
@@ -12,6 +24,10 @@ const collectNodeTypes = (value, result) => {
12
24
  }
13
25
  const obj = value;
14
26
  if (typeof obj.nodeType === "string") result.add(obj.nodeType);
27
+ else if (isReactLikeElement(obj)) {
28
+ result.add(_intlayer_types_nodeType.REACT_NODE);
29
+ result.add(_intlayer_types_nodeType.PREACT_NODE);
30
+ } else if (isSolidLikeElement(obj)) result.add(_intlayer_types_nodeType.SOLID_NODE);
15
31
  for (const key of Object.keys(obj)) collectNodeTypes(obj[key], result);
16
32
  };
17
33
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"getUsedNodeTypes.cjs","names":["PLUGIN_NODE_TYPES"],"sources":["../../../src/utils/getUsedNodeTypes.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport { PLUGIN_NODE_TYPES } from '@intlayer/types/nodeType';\n\nexport type PluginNodeType = (typeof PLUGIN_NODE_TYPES)[number];\n\n/** Recursively collect every `nodeType` string found in a value. */\nconst collectNodeTypes = (value: unknown, result: Set<string>): void => {\n if (!value || typeof value !== 'object') return;\n\n if (Array.isArray(value)) {\n for (const item of value) collectNodeTypes(item, result);\n return;\n }\n\n const obj = value as Record<string, unknown>;\n\n if (typeof obj.nodeType === 'string') {\n result.add(obj.nodeType);\n }\n\n for (const key of Object.keys(obj)) {\n collectNodeTypes(obj[key], result);\n }\n};\n\n/**\n * Returns the set of NodeType strings actually used across the given\n * built dictionaries.\n *\n * @example\n * const used = getUsedNodeTypes(getDictionaries(config));\n * // Set { 'translation', 'enumeration' }\n */\nexport const getUsedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const result = new Set<PluginNodeType>();\n const dicts = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n for (const dict of dicts) {\n collectNodeTypes(dict.content, result);\n }\n\n return [...result];\n};\n\nexport const getUnusedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const usedNodeTypes = getUsedNodeTypes(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n\nexport const getUsedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const dictionariesArray = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n const results = await Promise.all(\n dictionariesArray.map(async (dictionary) => {\n const result = new Set<PluginNodeType>();\n\n collectNodeTypes(dictionary.content, result as Set<string>);\n\n return result;\n })\n );\n\n const finalResult = new Set<PluginNodeType>();\n\n for (const res of results) {\n for (const val of res) {\n finalResult.add(val);\n }\n }\n\n return [...finalResult];\n};\n\nexport const getUnusedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const usedNodeTypes = await getUsedNodeTypesAsync(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n"],"mappings":";;;;;;AAMA,MAAM,oBAAoB,OAAgB,WAA8B;AACtE,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AAEzC,KAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,OAAK,MAAM,QAAQ,MAAO,kBAAiB,MAAM,OAAO;AACxD;;CAGF,MAAM,MAAM;AAEZ,KAAI,OAAO,IAAI,aAAa,SAC1B,QAAO,IAAI,IAAI,SAAS;AAG1B,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAChC,kBAAiB,IAAI,MAAM,OAAO;;;;;;;;;;AAYtC,MAAa,oBACX,iBACqB;CACrB,MAAM,yBAAS,IAAI,KAAqB;CACxC,MAAM,QAAQ,MAAM,QAAQ,aAAa,GACrC,eACA,OAAO,OAAO,aAAa;AAE/B,MAAK,MAAM,QAAQ,MACjB,kBAAiB,KAAK,SAAS,OAAO;AAGxC,QAAO,CAAC,GAAG,OAAO;;AAGpB,MAAa,sBACX,iBACqB;CACrB,MAAM,gBAAgB,iBAAiB,aAAa;AAEpD,QAAOA,2CAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD;;AAGH,MAAa,wBAAwB,OACnC,iBAC8B;CAC9B,MAAM,oBAAoB,MAAM,QAAQ,aAAa,GACjD,eACA,OAAO,OAAO,aAAa;CAE/B,MAAM,UAAU,MAAM,QAAQ,IAC5B,kBAAkB,IAAI,OAAO,eAAe;EAC1C,MAAM,yBAAS,IAAI,KAAqB;AAExC,mBAAiB,WAAW,SAAS,OAAsB;AAE3D,SAAO;GACP,CACH;CAED,MAAM,8BAAc,IAAI,KAAqB;AAE7C,MAAK,MAAM,OAAO,QAChB,MAAK,MAAM,OAAO,IAChB,aAAY,IAAI,IAAI;AAIxB,QAAO,CAAC,GAAG,YAAY;;AAGzB,MAAa,0BAA0B,OACrC,iBAC8B;CAC9B,MAAM,gBAAgB,MAAM,sBAAsB,aAAa;AAE/D,QAAOA,2CAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD"}
1
+ {"version":3,"file":"getUsedNodeTypes.cjs","names":["REACT_NODE","PREACT_NODE","SOLID_NODE","PLUGIN_NODE_TYPES"],"sources":["../../../src/utils/getUsedNodeTypes.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport {\n PLUGIN_NODE_TYPES,\n PREACT_NODE,\n REACT_NODE,\n SOLID_NODE,\n} from '@intlayer/types/nodeType';\n\nexport type PluginNodeType = (typeof PLUGIN_NODE_TYPES)[number];\n\n/**\n * Detect whether a plain object looks like a serialized React element.\n * React serializes JSX as: { key, props, _owner, _store }.\n * Preact serializes VNodes similarly with a `_store` field.\n */\nconst isReactLikeElement = (obj: Record<string, unknown>): boolean =>\n typeof obj.props !== 'undefined' &&\n 'key' in obj &&\n typeof obj._store !== 'undefined';\n\n/**\n * Detect whether a plain object looks like a serialized Solid element.\n * Solid JSX is serialized as: { type, props } without the React-specific\n * `_store` / `_owner` internal fields.\n */\nconst isSolidLikeElement = (obj: Record<string, unknown>): boolean =>\n typeof obj.props !== 'undefined' &&\n typeof obj._store === 'undefined' &&\n typeof obj.nodeType === 'undefined' &&\n 'type' in obj;\n\n/** Recursively collect every `nodeType` string found in a value. */\nconst collectNodeTypes = (value: unknown, result: Set<string>): void => {\n if (!value || typeof value !== 'object') return;\n\n if (Array.isArray(value)) {\n for (const item of value) collectNodeTypes(item, result);\n return;\n }\n\n const obj = value as Record<string, unknown>;\n\n if (typeof obj.nodeType === 'string') {\n result.add(obj.nodeType);\n } else if (isReactLikeElement(obj)) {\n // Serialized React / Preact JSX element — both use { key, props, _store }\n result.add(REACT_NODE);\n result.add(PREACT_NODE);\n } else if (isSolidLikeElement(obj)) {\n result.add(SOLID_NODE);\n }\n\n for (const key of Object.keys(obj)) {\n collectNodeTypes(obj[key], result);\n }\n};\n\n/**\n * Returns the set of NodeType strings actually used across the given\n * built dictionaries.\n *\n * @example\n * const used = getUsedNodeTypes(getDictionaries(config));\n * // Set { 'translation', 'enumeration' }\n */\nexport const getUsedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const result = new Set<PluginNodeType>();\n const dicts = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n for (const dict of dicts) {\n collectNodeTypes(dict.content, result);\n }\n\n return [...result];\n};\n\nexport const getUnusedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const usedNodeTypes = getUsedNodeTypes(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n\nexport const getUsedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const dictionariesArray = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n const results = await Promise.all(\n dictionariesArray.map(async (dictionary) => {\n const result = new Set<PluginNodeType>();\n\n collectNodeTypes(dictionary.content, result as Set<string>);\n\n return result;\n })\n );\n\n const finalResult = new Set<PluginNodeType>();\n\n for (const res of results) {\n for (const val of res) {\n finalResult.add(val);\n }\n }\n\n return [...finalResult];\n};\n\nexport const getUnusedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const usedNodeTypes = await getUsedNodeTypesAsync(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n"],"mappings":";;;;;;;;;;AAeA,MAAM,sBAAsB,QAC1B,OAAO,IAAI,UAAU,eACrB,SAAS,OACT,OAAO,IAAI,WAAW;;;;;;AAOxB,MAAM,sBAAsB,QAC1B,OAAO,IAAI,UAAU,eACrB,OAAO,IAAI,WAAW,eACtB,OAAO,IAAI,aAAa,eACxB,UAAU;;AAGZ,MAAM,oBAAoB,OAAgB,WAA8B;AACtE,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AAEzC,KAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,OAAK,MAAM,QAAQ,MAAO,kBAAiB,MAAM,OAAO;AACxD;;CAGF,MAAM,MAAM;AAEZ,KAAI,OAAO,IAAI,aAAa,SAC1B,QAAO,IAAI,IAAI,SAAS;UACf,mBAAmB,IAAI,EAAE;AAElC,SAAO,IAAIA,oCAAW;AACtB,SAAO,IAAIC,qCAAY;YACd,mBAAmB,IAAI,CAChC,QAAO,IAAIC,oCAAW;AAGxB,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAChC,kBAAiB,IAAI,MAAM,OAAO;;;;;;;;;;AAYtC,MAAa,oBACX,iBACqB;CACrB,MAAM,yBAAS,IAAI,KAAqB;CACxC,MAAM,QAAQ,MAAM,QAAQ,aAAa,GACrC,eACA,OAAO,OAAO,aAAa;AAE/B,MAAK,MAAM,QAAQ,MACjB,kBAAiB,KAAK,SAAS,OAAO;AAGxC,QAAO,CAAC,GAAG,OAAO;;AAGpB,MAAa,sBACX,iBACqB;CACrB,MAAM,gBAAgB,iBAAiB,aAAa;AAEpD,QAAOC,2CAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD;;AAGH,MAAa,wBAAwB,OACnC,iBAC8B;CAC9B,MAAM,oBAAoB,MAAM,QAAQ,aAAa,GACjD,eACA,OAAO,OAAO,aAAa;CAE/B,MAAM,UAAU,MAAM,QAAQ,IAC5B,kBAAkB,IAAI,OAAO,eAAe;EAC1C,MAAM,yBAAS,IAAI,KAAqB;AAExC,mBAAiB,WAAW,SAAS,OAAsB;AAE3D,SAAO;GACP,CACH;CAED,MAAM,8BAAc,IAAI,KAAqB;AAE7C,MAAK,MAAM,OAAO,QAChB,MAAK,MAAM,OAAO,IAChB,aAAY,IAAI,IAAI;AAIxB,QAAO,CAAC,GAAG,YAAY;;AAGzB,MAAa,0BAA0B,OACrC,iBAC8B;CAC9B,MAAM,gBAAgB,MAAM,sBAAsB,aAAa;AAE/D,QAAOA,2CAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD"}
@@ -1,5 +1,14 @@
1
1
  //#region src/envVars/envVars.ts
2
2
  /**
3
+ * Converts a camelCase node-type string to SCREAMING_SNAKE_CASE so that
4
+ * the generated env-var name matches what the plugin source files check.
5
+ *
6
+ * @example
7
+ * toScreamingSnakeCase('reactNode') // 'REACT_NODE'
8
+ * toScreamingSnakeCase('markdown') // 'MARKDOWN'
9
+ */
10
+ const toScreamingSnakeCase = (str) => str.replace(/([A-Z])/g, "_$1").toUpperCase().replace(/^_/, "");
11
+ /**
3
12
  * Converts a list of unused NodeType keys into env-var definitions.
4
13
  * Set to `"false"` so bundlers can eliminate the corresponding plugin code.
5
14
  *
@@ -7,11 +16,11 @@
7
16
  * formatNodeTypeToEnvVar(['enumeration'])
8
17
  * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '"false"' }
9
18
  *
10
- * formatNodeTypeToEnvVar(['enumeration'], true)
11
- * // { 'process.env.INTLAYER_NODE_TYPE_ENUMERATION': '"false"' }
19
+ * formatNodeTypeToEnvVar(['reactNode'], (k) => `process.env.${k}`, (v) => `"${v}"`)
20
+ * // { 'process.env.INTLAYER_NODE_TYPE_REACT_NODE': '"false"' }
12
21
  */
13
22
  const formatNodeTypeToEnvVar = (nodeTypes, wrapKey = (key) => key, wrapValue = (value) => value) => nodeTypes.reduce((acc, nodeType) => {
14
- acc[wrapKey(`INTLAYER_NODE_TYPE_${nodeType.toUpperCase()}`)] = wrapValue("false");
23
+ acc[wrapKey(`INTLAYER_NODE_TYPE_${toScreamingSnakeCase(nodeType)}`)] = wrapValue("false");
15
24
  return acc;
16
25
  }, {});
17
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"envVars.mjs","names":[],"sources":["../../../src/envVars/envVars.ts"],"sourcesContent":["import type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Converts a list of unused NodeType keys into env-var definitions.\n * Set to `\"false\"` so bundlers can eliminate the corresponding plugin code.\n *\n * @example\n * formatNodeTypeToEnvVar(['enumeration'])\n * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '\"false\"' }\n *\n * formatNodeTypeToEnvVar(['enumeration'], true)\n * // { 'process.env.INTLAYER_NODE_TYPE_ENUMERATION': '\"false\"' }\n */\nexport const formatNodeTypeToEnvVar = (\n nodeTypes: string[],\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> =>\n nodeTypes.reduce(\n (acc, nodeType) => {\n acc[wrapKey(`INTLAYER_NODE_TYPE_${nodeType.toUpperCase()}`)] =\n wrapValue('false');\n return acc;\n },\n {} as Record<string, string>\n );\n\n/**\n * Returns env-var definitions for the full Intlayer config to be injected at\n * build time. Allows bundlers to dead-code-eliminate unused routing modes,\n * rewrite logic, storage mechanisms, and editor code.\n *\n * @example\n * getConfigEnvVars(config)\n * // { INTLAYER_ROUTING_MODE: '\"prefix-no-default\"', INTLAYER_ROUTING_REWRITE_RULES: '\"false\"', ... }\n *\n * getConfigEnvVars(config, true)\n * // { 'process.env.INTLAYER_ROUTING_MODE': '\"prefix-no-default\"', ... }\n */\nexport const getConfigEnvVars = (\n config: IntlayerConfig,\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> => {\n const { routing, editor } = config;\n\n const envVars: Record<string, string> = {\n [wrapKey('INTLAYER_ROUTING_MODE')]: wrapValue(routing.mode),\n };\n\n if (!routing.rewrite) {\n envVars[wrapKey('INTLAYER_ROUTING_REWRITE_RULES')] = wrapValue('false');\n }\n\n if (!routing.domains || Object.keys(routing.domains).length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_DOMAINS')] = wrapValue('false');\n }\n\n if (!routing.storage.cookies || routing.storage.cookies.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_COOKIES')] = wrapValue('false');\n }\n\n if (\n !routing.storage.localStorage ||\n routing.storage.localStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_LOCALSTORAGE')] =\n wrapValue('false');\n }\n\n if (\n !routing.storage.sessionStorage ||\n routing.storage.sessionStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE')] =\n wrapValue('false');\n }\n\n if (!routing.storage.headers || routing.storage.headers.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_HEADERS')] = wrapValue('false');\n }\n\n if (editor?.enabled === false) {\n envVars[wrapKey('INTLAYER_EDITOR_ENABLED')] = wrapValue('false');\n }\n\n return envVars;\n};\n"],"mappings":";;;;;;;;;;;;AAaA,MAAa,0BACX,WACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UAE/B,UAAU,QACP,KAAK,aAAa;AACjB,KAAI,QAAQ,sBAAsB,SAAS,aAAa,GAAG,IACzD,UAAU,QAAQ;AACpB,QAAO;GAET,EAAE,CACH;;;;;;;;;;;;;AAcH,MAAa,oBACX,QACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UACJ;CAC3B,MAAM,EAAE,SAAS,WAAW;CAE5B,MAAM,UAAkC,GACrC,QAAQ,wBAAwB,GAAG,UAAU,QAAQ,KAAK,EAC5D;AAED,KAAI,CAAC,QAAQ,QACX,SAAQ,QAAQ,iCAAiC,IAAI,UAAU,QAAQ;AAGzE,KAAI,CAAC,QAAQ,WAAW,OAAO,KAAK,QAAQ,QAAQ,CAAC,WAAW,EAC9D,SAAQ,QAAQ,2BAA2B,IAAI,UAAU,QAAQ;AAGnE,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KACE,CAAC,QAAQ,QAAQ,gBACjB,QAAQ,QAAQ,aAAa,WAAW,EAExC,SAAQ,QAAQ,wCAAwC,IACtD,UAAU,QAAQ;AAGtB,KACE,CAAC,QAAQ,QAAQ,kBACjB,QAAQ,QAAQ,eAAe,WAAW,EAE1C,SAAQ,QAAQ,0CAA0C,IACxD,UAAU,QAAQ;AAGtB,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KAAI,QAAQ,YAAY,MACtB,SAAQ,QAAQ,0BAA0B,IAAI,UAAU,QAAQ;AAGlE,QAAO"}
1
+ {"version":3,"file":"envVars.mjs","names":[],"sources":["../../../src/envVars/envVars.ts"],"sourcesContent":["import type { IntlayerConfig } from '@intlayer/types/config';\n\n/**\n * Converts a camelCase node-type string to SCREAMING_SNAKE_CASE so that\n * the generated env-var name matches what the plugin source files check.\n *\n * @example\n * toScreamingSnakeCase('reactNode') // 'REACT_NODE'\n * toScreamingSnakeCase('markdown') // 'MARKDOWN'\n */\nconst toScreamingSnakeCase = (str: string): string =>\n str\n .replace(/([A-Z])/g, '_$1')\n .toUpperCase()\n .replace(/^_/, ''); // strip any leading underscore\n\n/**\n * Converts a list of unused NodeType keys into env-var definitions.\n * Set to `\"false\"` so bundlers can eliminate the corresponding plugin code.\n *\n * @example\n * formatNodeTypeToEnvVar(['enumeration'])\n * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '\"false\"' }\n *\n * formatNodeTypeToEnvVar(['reactNode'], (k) => `process.env.${k}`, (v) => `\"${v}\"`)\n * // { 'process.env.INTLAYER_NODE_TYPE_REACT_NODE': '\"false\"' }\n */\nexport const formatNodeTypeToEnvVar = (\n nodeTypes: string[],\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> =>\n nodeTypes.reduce(\n (acc, nodeType) => {\n acc[wrapKey(`INTLAYER_NODE_TYPE_${toScreamingSnakeCase(nodeType)}`)] =\n wrapValue('false');\n return acc;\n },\n {} as Record<string, string>\n );\n\n/**\n * Returns env-var definitions for the full Intlayer config to be injected at\n * build time. Allows bundlers to dead-code-eliminate unused routing modes,\n * rewrite logic, storage mechanisms, and editor code.\n *\n * @example\n * getConfigEnvVars(config)\n * // { INTLAYER_ROUTING_MODE: '\"prefix-no-default\"', INTLAYER_ROUTING_REWRITE_RULES: '\"false\"', ... }\n *\n * getConfigEnvVars(config, true)\n * // { 'process.env.INTLAYER_ROUTING_MODE': '\"prefix-no-default\"', ... }\n */\nexport const getConfigEnvVars = (\n config: IntlayerConfig,\n wrapKey = (key: string) => key,\n wrapValue = (value: string) => value\n): Record<string, string> => {\n const { routing, editor } = config;\n\n const envVars: Record<string, string> = {\n [wrapKey('INTLAYER_ROUTING_MODE')]: wrapValue(routing.mode),\n };\n\n if (!routing.rewrite) {\n envVars[wrapKey('INTLAYER_ROUTING_REWRITE_RULES')] = wrapValue('false');\n }\n\n if (!routing.domains || Object.keys(routing.domains).length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_DOMAINS')] = wrapValue('false');\n }\n\n if (!routing.storage.cookies || routing.storage.cookies.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_COOKIES')] = wrapValue('false');\n }\n\n if (\n !routing.storage.localStorage ||\n routing.storage.localStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_LOCALSTORAGE')] =\n wrapValue('false');\n }\n\n if (\n !routing.storage.sessionStorage ||\n routing.storage.sessionStorage.length === 0\n ) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_SESSIONSTORAGE')] =\n wrapValue('false');\n }\n\n if (!routing.storage.headers || routing.storage.headers.length === 0) {\n envVars[wrapKey('INTLAYER_ROUTING_STORAGE_HEADERS')] = wrapValue('false');\n }\n\n if (editor?.enabled === false) {\n envVars[wrapKey('INTLAYER_EDITOR_ENABLED')] = wrapValue('false');\n }\n\n return envVars;\n};\n"],"mappings":";;;;;;;;;AAUA,MAAM,wBAAwB,QAC5B,IACG,QAAQ,YAAY,MAAM,CAC1B,aAAa,CACb,QAAQ,MAAM,GAAG;;;;;;;;;;;;AAatB,MAAa,0BACX,WACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UAE/B,UAAU,QACP,KAAK,aAAa;AACjB,KAAI,QAAQ,sBAAsB,qBAAqB,SAAS,GAAG,IACjE,UAAU,QAAQ;AACpB,QAAO;GAET,EAAE,CACH;;;;;;;;;;;;;AAcH,MAAa,oBACX,QACA,WAAW,QAAgB,KAC3B,aAAa,UAAkB,UACJ;CAC3B,MAAM,EAAE,SAAS,WAAW;CAE5B,MAAM,UAAkC,GACrC,QAAQ,wBAAwB,GAAG,UAAU,QAAQ,KAAK,EAC5D;AAED,KAAI,CAAC,QAAQ,QACX,SAAQ,QAAQ,iCAAiC,IAAI,UAAU,QAAQ;AAGzE,KAAI,CAAC,QAAQ,WAAW,OAAO,KAAK,QAAQ,QAAQ,CAAC,WAAW,EAC9D,SAAQ,QAAQ,2BAA2B,IAAI,UAAU,QAAQ;AAGnE,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KACE,CAAC,QAAQ,QAAQ,gBACjB,QAAQ,QAAQ,aAAa,WAAW,EAExC,SAAQ,QAAQ,wCAAwC,IACtD,UAAU,QAAQ;AAGtB,KACE,CAAC,QAAQ,QAAQ,kBACjB,QAAQ,QAAQ,eAAe,WAAW,EAE1C,SAAQ,QAAQ,0CAA0C,IACxD,UAAU,QAAQ;AAGtB,KAAI,CAAC,QAAQ,QAAQ,WAAW,QAAQ,QAAQ,QAAQ,WAAW,EACjE,SAAQ,QAAQ,mCAAmC,IAAI,UAAU,QAAQ;AAG3E,KAAI,QAAQ,YAAY,MACtB,SAAQ,QAAQ,0BAA0B,IAAI,UAAU,QAAQ;AAGlE,QAAO"}
@@ -1,6 +1,18 @@
1
- import { PLUGIN_NODE_TYPES } from "@intlayer/types/nodeType";
1
+ import { PLUGIN_NODE_TYPES, PREACT_NODE, REACT_NODE, SOLID_NODE } from "@intlayer/types/nodeType";
2
2
 
3
3
  //#region src/utils/getUsedNodeTypes.ts
4
+ /**
5
+ * Detect whether a plain object looks like a serialized React element.
6
+ * React serializes JSX as: { key, props, _owner, _store }.
7
+ * Preact serializes VNodes similarly with a `_store` field.
8
+ */
9
+ const isReactLikeElement = (obj) => typeof obj.props !== "undefined" && "key" in obj && typeof obj._store !== "undefined";
10
+ /**
11
+ * Detect whether a plain object looks like a serialized Solid element.
12
+ * Solid JSX is serialized as: { type, props } without the React-specific
13
+ * `_store` / `_owner` internal fields.
14
+ */
15
+ const isSolidLikeElement = (obj) => typeof obj.props !== "undefined" && typeof obj._store === "undefined" && typeof obj.nodeType === "undefined" && "type" in obj;
4
16
  /** Recursively collect every `nodeType` string found in a value. */
5
17
  const collectNodeTypes = (value, result) => {
6
18
  if (!value || typeof value !== "object") return;
@@ -10,6 +22,10 @@ const collectNodeTypes = (value, result) => {
10
22
  }
11
23
  const obj = value;
12
24
  if (typeof obj.nodeType === "string") result.add(obj.nodeType);
25
+ else if (isReactLikeElement(obj)) {
26
+ result.add(REACT_NODE);
27
+ result.add(PREACT_NODE);
28
+ } else if (isSolidLikeElement(obj)) result.add(SOLID_NODE);
13
29
  for (const key of Object.keys(obj)) collectNodeTypes(obj[key], result);
14
30
  };
15
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"getUsedNodeTypes.mjs","names":[],"sources":["../../../src/utils/getUsedNodeTypes.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport { PLUGIN_NODE_TYPES } from '@intlayer/types/nodeType';\n\nexport type PluginNodeType = (typeof PLUGIN_NODE_TYPES)[number];\n\n/** Recursively collect every `nodeType` string found in a value. */\nconst collectNodeTypes = (value: unknown, result: Set<string>): void => {\n if (!value || typeof value !== 'object') return;\n\n if (Array.isArray(value)) {\n for (const item of value) collectNodeTypes(item, result);\n return;\n }\n\n const obj = value as Record<string, unknown>;\n\n if (typeof obj.nodeType === 'string') {\n result.add(obj.nodeType);\n }\n\n for (const key of Object.keys(obj)) {\n collectNodeTypes(obj[key], result);\n }\n};\n\n/**\n * Returns the set of NodeType strings actually used across the given\n * built dictionaries.\n *\n * @example\n * const used = getUsedNodeTypes(getDictionaries(config));\n * // Set { 'translation', 'enumeration' }\n */\nexport const getUsedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const result = new Set<PluginNodeType>();\n const dicts = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n for (const dict of dicts) {\n collectNodeTypes(dict.content, result);\n }\n\n return [...result];\n};\n\nexport const getUnusedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const usedNodeTypes = getUsedNodeTypes(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n\nexport const getUsedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const dictionariesArray = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n const results = await Promise.all(\n dictionariesArray.map(async (dictionary) => {\n const result = new Set<PluginNodeType>();\n\n collectNodeTypes(dictionary.content, result as Set<string>);\n\n return result;\n })\n );\n\n const finalResult = new Set<PluginNodeType>();\n\n for (const res of results) {\n for (const val of res) {\n finalResult.add(val);\n }\n }\n\n return [...finalResult];\n};\n\nexport const getUnusedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const usedNodeTypes = await getUsedNodeTypesAsync(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n"],"mappings":";;;;AAMA,MAAM,oBAAoB,OAAgB,WAA8B;AACtE,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AAEzC,KAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,OAAK,MAAM,QAAQ,MAAO,kBAAiB,MAAM,OAAO;AACxD;;CAGF,MAAM,MAAM;AAEZ,KAAI,OAAO,IAAI,aAAa,SAC1B,QAAO,IAAI,IAAI,SAAS;AAG1B,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAChC,kBAAiB,IAAI,MAAM,OAAO;;;;;;;;;;AAYtC,MAAa,oBACX,iBACqB;CACrB,MAAM,yBAAS,IAAI,KAAqB;CACxC,MAAM,QAAQ,MAAM,QAAQ,aAAa,GACrC,eACA,OAAO,OAAO,aAAa;AAE/B,MAAK,MAAM,QAAQ,MACjB,kBAAiB,KAAK,SAAS,OAAO;AAGxC,QAAO,CAAC,GAAG,OAAO;;AAGpB,MAAa,sBACX,iBACqB;CACrB,MAAM,gBAAgB,iBAAiB,aAAa;AAEpD,QAAO,kBAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD;;AAGH,MAAa,wBAAwB,OACnC,iBAC8B;CAC9B,MAAM,oBAAoB,MAAM,QAAQ,aAAa,GACjD,eACA,OAAO,OAAO,aAAa;CAE/B,MAAM,UAAU,MAAM,QAAQ,IAC5B,kBAAkB,IAAI,OAAO,eAAe;EAC1C,MAAM,yBAAS,IAAI,KAAqB;AAExC,mBAAiB,WAAW,SAAS,OAAsB;AAE3D,SAAO;GACP,CACH;CAED,MAAM,8BAAc,IAAI,KAAqB;AAE7C,MAAK,MAAM,OAAO,QAChB,MAAK,MAAM,OAAO,IAChB,aAAY,IAAI,IAAI;AAIxB,QAAO,CAAC,GAAG,YAAY;;AAGzB,MAAa,0BAA0B,OACrC,iBAC8B;CAC9B,MAAM,gBAAgB,MAAM,sBAAsB,aAAa;AAE/D,QAAO,kBAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD"}
1
+ {"version":3,"file":"getUsedNodeTypes.mjs","names":[],"sources":["../../../src/utils/getUsedNodeTypes.ts"],"sourcesContent":["import type { Dictionary } from '@intlayer/types/dictionary';\nimport {\n PLUGIN_NODE_TYPES,\n PREACT_NODE,\n REACT_NODE,\n SOLID_NODE,\n} from '@intlayer/types/nodeType';\n\nexport type PluginNodeType = (typeof PLUGIN_NODE_TYPES)[number];\n\n/**\n * Detect whether a plain object looks like a serialized React element.\n * React serializes JSX as: { key, props, _owner, _store }.\n * Preact serializes VNodes similarly with a `_store` field.\n */\nconst isReactLikeElement = (obj: Record<string, unknown>): boolean =>\n typeof obj.props !== 'undefined' &&\n 'key' in obj &&\n typeof obj._store !== 'undefined';\n\n/**\n * Detect whether a plain object looks like a serialized Solid element.\n * Solid JSX is serialized as: { type, props } without the React-specific\n * `_store` / `_owner` internal fields.\n */\nconst isSolidLikeElement = (obj: Record<string, unknown>): boolean =>\n typeof obj.props !== 'undefined' &&\n typeof obj._store === 'undefined' &&\n typeof obj.nodeType === 'undefined' &&\n 'type' in obj;\n\n/** Recursively collect every `nodeType` string found in a value. */\nconst collectNodeTypes = (value: unknown, result: Set<string>): void => {\n if (!value || typeof value !== 'object') return;\n\n if (Array.isArray(value)) {\n for (const item of value) collectNodeTypes(item, result);\n return;\n }\n\n const obj = value as Record<string, unknown>;\n\n if (typeof obj.nodeType === 'string') {\n result.add(obj.nodeType);\n } else if (isReactLikeElement(obj)) {\n // Serialized React / Preact JSX element — both use { key, props, _store }\n result.add(REACT_NODE);\n result.add(PREACT_NODE);\n } else if (isSolidLikeElement(obj)) {\n result.add(SOLID_NODE);\n }\n\n for (const key of Object.keys(obj)) {\n collectNodeTypes(obj[key], result);\n }\n};\n\n/**\n * Returns the set of NodeType strings actually used across the given\n * built dictionaries.\n *\n * @example\n * const used = getUsedNodeTypes(getDictionaries(config));\n * // Set { 'translation', 'enumeration' }\n */\nexport const getUsedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const result = new Set<PluginNodeType>();\n const dicts = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n for (const dict of dicts) {\n collectNodeTypes(dict.content, result);\n }\n\n return [...result];\n};\n\nexport const getUnusedNodeTypes = (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): PluginNodeType[] => {\n const usedNodeTypes = getUsedNodeTypes(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n\nexport const getUsedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const dictionariesArray = Array.isArray(dictionaries)\n ? dictionaries\n : Object.values(dictionaries);\n\n const results = await Promise.all(\n dictionariesArray.map(async (dictionary) => {\n const result = new Set<PluginNodeType>();\n\n collectNodeTypes(dictionary.content, result as Set<string>);\n\n return result;\n })\n );\n\n const finalResult = new Set<PluginNodeType>();\n\n for (const res of results) {\n for (const val of res) {\n finalResult.add(val);\n }\n }\n\n return [...finalResult];\n};\n\nexport const getUnusedNodeTypesAsync = async (\n dictionaries: Record<string, Dictionary> | Dictionary[]\n): Promise<PluginNodeType[]> => {\n const usedNodeTypes = await getUsedNodeTypesAsync(dictionaries);\n\n return PLUGIN_NODE_TYPES.filter(\n (nodeType) => !usedNodeTypes.includes(nodeType)\n );\n};\n"],"mappings":";;;;;;;;AAeA,MAAM,sBAAsB,QAC1B,OAAO,IAAI,UAAU,eACrB,SAAS,OACT,OAAO,IAAI,WAAW;;;;;;AAOxB,MAAM,sBAAsB,QAC1B,OAAO,IAAI,UAAU,eACrB,OAAO,IAAI,WAAW,eACtB,OAAO,IAAI,aAAa,eACxB,UAAU;;AAGZ,MAAM,oBAAoB,OAAgB,WAA8B;AACtE,KAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AAEzC,KAAI,MAAM,QAAQ,MAAM,EAAE;AACxB,OAAK,MAAM,QAAQ,MAAO,kBAAiB,MAAM,OAAO;AACxD;;CAGF,MAAM,MAAM;AAEZ,KAAI,OAAO,IAAI,aAAa,SAC1B,QAAO,IAAI,IAAI,SAAS;UACf,mBAAmB,IAAI,EAAE;AAElC,SAAO,IAAI,WAAW;AACtB,SAAO,IAAI,YAAY;YACd,mBAAmB,IAAI,CAChC,QAAO,IAAI,WAAW;AAGxB,MAAK,MAAM,OAAO,OAAO,KAAK,IAAI,CAChC,kBAAiB,IAAI,MAAM,OAAO;;;;;;;;;;AAYtC,MAAa,oBACX,iBACqB;CACrB,MAAM,yBAAS,IAAI,KAAqB;CACxC,MAAM,QAAQ,MAAM,QAAQ,aAAa,GACrC,eACA,OAAO,OAAO,aAAa;AAE/B,MAAK,MAAM,QAAQ,MACjB,kBAAiB,KAAK,SAAS,OAAO;AAGxC,QAAO,CAAC,GAAG,OAAO;;AAGpB,MAAa,sBACX,iBACqB;CACrB,MAAM,gBAAgB,iBAAiB,aAAa;AAEpD,QAAO,kBAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD;;AAGH,MAAa,wBAAwB,OACnC,iBAC8B;CAC9B,MAAM,oBAAoB,MAAM,QAAQ,aAAa,GACjD,eACA,OAAO,OAAO,aAAa;CAE/B,MAAM,UAAU,MAAM,QAAQ,IAC5B,kBAAkB,IAAI,OAAO,eAAe;EAC1C,MAAM,yBAAS,IAAI,KAAqB;AAExC,mBAAiB,WAAW,SAAS,OAAsB;AAE3D,SAAO;GACP,CACH;CAED,MAAM,8BAAc,IAAI,KAAqB;AAE7C,MAAK,MAAM,OAAO,QAChB,MAAK,MAAM,OAAO,IAChB,aAAY,IAAI,IAAI;AAIxB,QAAO,CAAC,GAAG,YAAY;;AAGzB,MAAa,0BAA0B,OACrC,iBAC8B;CAC9B,MAAM,gBAAgB,MAAM,sBAAsB,aAAa;AAE/D,QAAO,kBAAkB,QACtB,aAAa,CAAC,cAAc,SAAS,SAAS,CAChD"}
@@ -9,8 +9,8 @@ import { IntlayerConfig } from "@intlayer/types/config";
9
9
  * formatNodeTypeToEnvVar(['enumeration'])
10
10
  * // { 'INTLAYER_NODE_TYPE_ENUMERATION': '"false"' }
11
11
  *
12
- * formatNodeTypeToEnvVar(['enumeration'], true)
13
- * // { 'process.env.INTLAYER_NODE_TYPE_ENUMERATION': '"false"' }
12
+ * formatNodeTypeToEnvVar(['reactNode'], (k) => `process.env.${k}`, (v) => `"${v}"`)
13
+ * // { 'process.env.INTLAYER_NODE_TYPE_REACT_NODE': '"false"' }
14
14
  */
15
15
  declare const formatNodeTypeToEnvVar: (nodeTypes: string[], wrapKey?: (key: string) => string, wrapValue?: (value: string) => string) => Record<string, string>;
16
16
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"envVars.d.ts","names":[],"sources":["../../../src/envVars/envVars.ts"],"mappings":";;;;;AAaA;;;;;;;;;cAAa,sBAAA,GACX,SAAA,YACA,OAAA,IAAW,GAAA,qBACX,SAAA,IAAa,KAAA,wBACZ,MAAA;;;AAsBH;;;;;;;;;;cAAa,gBAAA,GACX,MAAA,EAAQ,cAAA,EACR,OAAA,IAAW,GAAA,qBACX,SAAA,IAAa,KAAA,wBACZ,MAAA"}
1
+ {"version":3,"file":"envVars.d.ts","names":[],"sources":["../../../src/envVars/envVars.ts"],"mappings":";;;;;AA2BA;;;;;;;;;cAAa,sBAAA,GACX,SAAA,YACA,OAAA,IAAW,GAAA,qBACX,SAAA,IAAa,KAAA,wBACZ,MAAA;;;AAsBH;;;;;;;;;;cAAa,gBAAA,GACX,MAAA,EAAQ,cAAA,EACR,OAAA,IAAW,GAAA,qBACX,SAAA,IAAa,KAAA,wBACZ,MAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"getUsedNodeTypes.d.ts","names":[],"sources":["../../../src/utils/getUsedNodeTypes.ts"],"mappings":";;;;KAGY,cAAA,WAAyB,iBAAA;;AAArC;;;;;AA8BA;;cAAa,gBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,cAAA;AAAA,cAaU,kBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,cAAA;AAAA,cAQU,qBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,OAAA,CAAQ,cAAA;AAAA,cA0BE,uBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,OAAA,CAAQ,cAAA"}
1
+ {"version":3,"file":"getUsedNodeTypes.d.ts","names":[],"sources":["../../../src/utils/getUsedNodeTypes.ts"],"mappings":";;;;KAQY,cAAA,WAAyB,iBAAA;;AAArC;;;;;AAyDA;;cAAa,gBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,cAAA;AAAA,cAaU,kBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,cAAA;AAAA,cAQU,qBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,OAAA,CAAQ,cAAA;AAAA,cA0BE,uBAAA,GACX,YAAA,EAAc,MAAA,SAAe,UAAA,IAAc,UAAA,OAC1C,OAAA,CAAQ,cAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/config",
3
- "version": "8.7.12",
3
+ "version": "8.7.14",
4
4
  "private": false,
5
5
  "description": "Retrieve Intlayer configurations and manage environment variables for both server-side and client-side environments.",
6
6
  "keywords": [
@@ -160,12 +160,12 @@
160
160
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
161
161
  },
162
162
  "dependencies": {
163
- "@intlayer/types": "8.7.12",
163
+ "@intlayer/types": "8.7.14",
164
164
  "defu": "6.1.7",
165
165
  "dotenv": "17.4.2",
166
166
  "esbuild": "0.28.0",
167
167
  "json5": "2.2.3",
168
- "zod": "4.3.6"
168
+ "zod": "4.4.2"
169
169
  },
170
170
  "devDependencies": {
171
171
  "@types/node": "25.6.0",