@intlayer/sync-json-plugin 9.4.3 → 9.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -69,8 +69,6 @@ With **per-locale content files**, **TypeScript autocompletion**, **tree-shakabl
69
69
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/interoperability.png?raw=true" alt="Feature" width="700"> | **Interoperability**<br><br>Allow interoperability with react-i18next, next-i18next, next-intl, react-intl, vue-i18n. <br><br> - [Intlayer and react-intl](https://intlayer.org/blog/intlayer-with-react-intl) <br> - [Intlayer and next-intl](https://intlayer.org/blog/intlayer-with-next-intl) <br> - [Intlayer and next-i18next](https://intlayer.org/blog/intlayer-with-next-i18next) <br> - [Intlayer and vue-i18n](https://intlayer.org/blog/intlayer-with-vue-i18n) <br> - [Intlayer compat adapters](https://intlayer.org/doc/compatibility) |
70
70
  | <img src="https://github.com/aymericzip/intlayer/blob/main/docs/assets/benchmark.png?raw=true" alt="Feature" width="700"> | **Performances & Benchmark**<br><br>Uses advanced tree-shaking and dynamic loading to boost performances and keep the solution as light as possible. <br><br> - [Performances & Benchmark](https://intlayer.org/doc/benchmark) |
71
71
 
72
- ---
73
-
74
72
  ## 📦 Installation
75
73
 
76
74
  Start your journey with Intlayer today and experience a smoother, more powerful approach to internationalization.
@@ -1 +1 @@
1
- {"version":3,"file":"loadJSON.cjs","names":["createSyncPlugin","createFileAdapter","jsonCodec","readJSONEntry"],"sources":["../../src/loadJSON.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { DictionaryFormat } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\nexport type LoadJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadJSON({\n * source: ({ key }) => `./resources/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * loadJSON({\n * source: ({ key }) => `./messages/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionary content.\n *\n * @example\n * ```ts\n * loadJSON({\n * format: 'icu',\n * })\n * ```\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys.\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment, and kept as a single dictionary otherwise.\n */\n splitKeys?: boolean;\n};\n\n/**\n * Read-only JSON ingestion plugin: loads JSON message files as dictionaries\n * without ever writing back to them.\n */\nexport const loadJSON = (options: LoadJSONPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: options.format,\n splitKeys: options.splitKeys,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;;AAwGA,MAAa,YAAY,gBACvBA,iDAAiB;CACf,MAAM;CACN,aAASC,kDAAkB;EACzB,QAAQ,QAAQ;EAChB,OAAOC;EACP,WAAWC;EACX,WAAW;CACb,CAAC;CACD,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ,QAAQ;CAChB,WAAW,QAAQ;CACnB,gBAAgB,QAAQ;AAC1B,CAAC"}
1
+ {"version":3,"file":"loadJSON.cjs","names":["createSyncPlugin","createFileAdapter","jsonCodec","readJSONEntry"],"sources":["../../src/loadJSON.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n type SplitKeysMode,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { DictionaryFormat } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\nexport type LoadJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadJSON({\n * source: ({ key }) => `./resources/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * loadJSON({\n * source: ({ key }) => `./messages/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionary content.\n *\n * @example\n * ```ts\n * loadJSON({\n * format: 'icu',\n * })\n * ```\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys.\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment, and kept as a single dictionary otherwise.\n */\n splitKeys?: SplitKeysMode;\n};\n\n/**\n * Read-only JSON ingestion plugin: loads JSON message files as dictionaries\n * without ever writing back to them.\n */\nexport const loadJSON = (options: LoadJSONPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: options.format,\n splitKeys: options.splitKeys,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;;AAyGA,MAAa,YAAY,gBACvBA,iDAAiB;CACf,MAAM;CACN,aAASC,kDAAkB;EACzB,QAAQ,QAAQ;EAChB,OAAOC;EACP,WAAWC;EACX,WAAW;CACb,CAAC;CACD,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ,QAAQ;CAChB,WAAW,QAAQ;CACnB,gBAAgB,QAAQ;AAC1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"syncJSON.cjs","names":["parseFilePathPattern","buildFilePathPatternContext","createSyncPlugin","createFileAdapter","jsonCodec","readJSONEntry"],"sources":["../../src/syncJSON.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type {\n DictionaryFormat,\n DictionaryLocation,\n} from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\n// Re-exported for backward compatibility: this helper used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\n\nexport type SyncJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncJSON({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionaries created by the plugin.\n *\n * Default: 'intlayer'\n *\n * The format of the dictionaries created by the plugin.\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys and each namespace is addressed\n * independently (e.g. `useTranslations('Hero')` → dictionary `Hero`).\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment (i.e. one file holds every namespace),\n * and kept as a single dictionary otherwise (one file per key).\n *\n * @example\n * ```ts\n * // messages/en.json → dictionaries: Hero, Nav, About, …\n * syncJSON({\n * source: ({ locale }) => `./messages/${locale}.json`,\n * splitKeys: true,\n * })\n * ```\n */\n splitKeys?: boolean;\n};\n\n/**\n * Two-way JSON synchronization plugin: ingests JSON message files as\n * dictionaries and writes the merged build output back to the same files.\n */\nexport const syncJSON = async (\n options: SyncJSONPluginOptions\n): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n // This ensures that if you have multiple plugins, they don't share the same 'plugin' ID.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-json::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: options.format,\n // Auto-detected by the file adapter when omitted: split when the source\n // pattern has no `{{key}}` segment (one file holds every namespace).\n splitKeys: options.splitKeys,\n });\n};\n"],"mappings":";;;;;;;;;;AAuGA,MAAa,WAAW,OACtB,YACoB;CAOpB,MAAM,kBAAkB,cAAc,UAJVA,6CAC1B,QAAQ,YACRC,4DAA4B,WAAW,YAAY,CACrD;CAGA,WAAOC,iDAAiB;EACtB,MAAM;EACN,aAASC,kDAAkB;GACzB,QAAQ,QAAQ;GAChB,OAAOC;GACP,WAAWC;GACX,WAAW;EACb,CAAC;EACD,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ,QAAQ;EAGhB,WAAW,QAAQ;CACrB,CAAC;AACH"}
1
+ {"version":3,"file":"syncJSON.cjs","names":["parseFilePathPattern","buildFilePathPatternContext","createSyncPlugin","createFileAdapter","jsonCodec","readJSONEntry"],"sources":["../../src/syncJSON.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n type SplitKeysMode,\n} from '@intlayer/engine/syncPluginKit';\nimport type {\n DictionaryFormat,\n DictionaryLocation,\n} from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\n// Re-exported for backward compatibility: this helper used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\n\nexport type SyncJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncJSON({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionaries created by the plugin.\n *\n * Default: 'intlayer'\n *\n * The format of the dictionaries created by the plugin.\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys and each namespace is addressed\n * independently (e.g. `useTranslations('Hero')` → dictionary `Hero`).\n *\n * Pass `'key-prefix'` for *flat* catalogs whose keys are dotted ids rather\n * than nested objects — the single-catalog model of `lingui` and of\n * i18next's default `translation` namespace. Each id's first dot-segment\n * becomes a dictionary and the remainder becomes the key inside it, so\n * `'footer.github'` is addressed as dictionary `footer`, key `github`.\n * Write-back restores the flat dotted ids, leaving the source file in the\n * shape its library expects.\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment (i.e. one file holds every namespace),\n * and kept as a single dictionary otherwise (one file per key).\n *\n * @example\n * ```ts\n * // messages/en.json → dictionaries: Hero, Nav, About, …\n * syncJSON({\n * source: ({ locale }) => `./messages/${locale}.json`,\n * splitKeys: true,\n * })\n *\n * // locales/en/messages.json → { 'footer.github': …, 'hero.title': … }\n * // → dictionaries: footer, hero, …\n * syncJSON({\n * source: ({ locale }) => `./locales/${locale}/messages.json`,\n * splitKeys: 'key-prefix',\n * })\n * ```\n */\n splitKeys?: SplitKeysMode;\n};\n\n/**\n * Two-way JSON synchronization plugin: ingests JSON message files as\n * dictionaries and writes the merged build output back to the same files.\n */\nexport const syncJSON = async (\n options: SyncJSONPluginOptions\n): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n // This ensures that if you have multiple plugins, they don't share the same 'plugin' ID.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-json::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: options.format,\n // Auto-detected by the file adapter when omitted: split when the source\n // pattern has no `{{key}}` segment (one file holds every namespace).\n splitKeys: options.splitKeys,\n });\n};\n"],"mappings":";;;;;;;;;;AAuHA,MAAa,WAAW,OACtB,YACoB;CAOpB,MAAM,kBAAkB,cAAc,UAJVA,6CAC1B,QAAQ,YACRC,4DAA4B,WAAW,YAAY,CACrD;CAGA,WAAOC,iDAAiB;EACtB,MAAM;EACN,aAASC,kDAAkB;GACzB,QAAQ,QAAQ;GAChB,OAAOC;GACP,WAAWC;GACX,WAAW;EACb,CAAC;EACD,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ,QAAQ;EAGhB,WAAW,QAAQ;CACrB,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadJSON.mjs","names":[],"sources":["../../src/loadJSON.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { DictionaryFormat } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\nexport type LoadJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadJSON({\n * source: ({ key }) => `./resources/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * loadJSON({\n * source: ({ key }) => `./messages/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionary content.\n *\n * @example\n * ```ts\n * loadJSON({\n * format: 'icu',\n * })\n * ```\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys.\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment, and kept as a single dictionary otherwise.\n */\n splitKeys?: boolean;\n};\n\n/**\n * Read-only JSON ingestion plugin: loads JSON message files as dictionaries\n * without ever writing back to them.\n */\nexport const loadJSON = (options: LoadJSONPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: options.format,\n splitKeys: options.splitKeys,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;AAwGA,MAAa,YAAY,YACvB,iBAAiB;CACf,MAAM;CACN,SAAS,kBAAkB;EACzB,QAAQ,QAAQ;EAChB,OAAO;EACP,WAAW;EACX,WAAW;CACb,CAAC;CACD,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ,QAAQ;CAChB,WAAW,QAAQ;CACnB,gBAAgB,QAAQ;AAC1B,CAAC"}
1
+ {"version":3,"file":"loadJSON.mjs","names":[],"sources":["../../src/loadJSON.ts"],"sourcesContent":["import {\n createFileAdapter,\n createSyncPlugin,\n type SplitKeysMode,\n} from '@intlayer/engine/syncPluginKit';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { DictionaryFormat } from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\nexport type LoadJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Locale\n *\n * If not provided, the plugin will consider the default locale.\n *\n * @example\n * ```ts\n * loadJSON({\n * source: ({ key }) => `blog/${'**'}/${key}.i18n.json`,\n * locale: Locales.ENGLISH,\n * })\n * ```\n */\n locale?: Locale;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * @example\n * ```ts\n * const config = {\n * plugins: [\n * loadJSON({\n * source: ({ key }) => `./resources/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * loadJSON({\n * source: ({ key }) => `./messages/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: string;\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionary content.\n *\n * @example\n * ```ts\n * loadJSON({\n * format: 'icu',\n * })\n * ```\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys.\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment, and kept as a single dictionary otherwise.\n */\n splitKeys?: SplitKeysMode;\n};\n\n/**\n * Read-only JSON ingestion plugin: loads JSON message files as dictionaries\n * without ever writing back to them.\n */\nexport const loadJSON = (options: LoadJSONPluginOptions): Plugin =>\n createSyncPlugin({\n name: 'load-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'inclusive',\n }),\n direction: 'pull',\n location: options.location ?? 'plugin',\n priority: options.priority ?? 0,\n format: options.format,\n splitKeys: options.splitKeys,\n localeOverride: options.locale,\n });\n"],"mappings":";;;;;;;;AAyGA,MAAa,YAAY,YACvB,iBAAiB;CACf,MAAM;CACN,SAAS,kBAAkB;EACzB,QAAQ,QAAQ;EAChB,OAAO;EACP,WAAW;EACX,WAAW;CACb,CAAC;CACD,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ,QAAQ;CAChB,WAAW,QAAQ;CACnB,gBAAgB,QAAQ;AAC1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"syncJSON.mjs","names":[],"sources":["../../src/syncJSON.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n} from '@intlayer/engine/syncPluginKit';\nimport type {\n DictionaryFormat,\n DictionaryLocation,\n} from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\n// Re-exported for backward compatibility: this helper used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\n\nexport type SyncJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncJSON({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionaries created by the plugin.\n *\n * Default: 'intlayer'\n *\n * The format of the dictionaries created by the plugin.\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys and each namespace is addressed\n * independently (e.g. `useTranslations('Hero')` → dictionary `Hero`).\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment (i.e. one file holds every namespace),\n * and kept as a single dictionary otherwise (one file per key).\n *\n * @example\n * ```ts\n * // messages/en.json → dictionaries: Hero, Nav, About, …\n * syncJSON({\n * source: ({ locale }) => `./messages/${locale}.json`,\n * splitKeys: true,\n * })\n * ```\n */\n splitKeys?: boolean;\n};\n\n/**\n * Two-way JSON synchronization plugin: ingests JSON message files as\n * dictionaries and writes the merged build output back to the same files.\n */\nexport const syncJSON = async (\n options: SyncJSONPluginOptions\n): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n // This ensures that if you have multiple plugins, they don't share the same 'plugin' ID.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-json::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: options.format,\n // Auto-detected by the file adapter when omitted: split when the source\n // pattern has no `{{key}}` segment (one file holds every namespace).\n splitKeys: options.splitKeys,\n });\n};\n"],"mappings":";;;;;;;;;AAuGA,MAAa,WAAW,OACtB,YACoB;CAOpB,MAAM,kBAAkB,cAAc,MAJV,qBAC1B,QAAQ,QACR,4BAA4B,WAAW,YAAY,CACrD;CAGA,OAAO,iBAAiB;EACtB,MAAM;EACN,SAAS,kBAAkB;GACzB,QAAQ,QAAQ;GAChB,OAAO;GACP,WAAW;GACX,WAAW;EACb,CAAC;EACD,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ,QAAQ;EAGhB,WAAW,QAAQ;CACrB,CAAC;AACH"}
1
+ {"version":3,"file":"syncJSON.mjs","names":[],"sources":["../../src/syncJSON.ts"],"sourcesContent":["import { parseFilePathPattern } from '@intlayer/config/utils';\nimport {\n buildFilePathPatternContext,\n createFileAdapter,\n createSyncPlugin,\n type SplitKeysMode,\n} from '@intlayer/engine/syncPluginKit';\nimport type {\n DictionaryFormat,\n DictionaryLocation,\n} from '@intlayer/types/dictionary';\nimport type { FilePathPattern } from '@intlayer/types/filePathPattern';\nimport type { Plugin } from '@intlayer/types/plugin';\nimport { jsonCodec, readJSONEntry } from './jsonCodec';\n\n// Re-exported for backward compatibility: this helper used to live here.\nexport { extractKeyAndLocaleFromPath } from '@intlayer/engine/syncPluginKit';\n\nexport type SyncJSONPluginOptions = {\n /**\n * The source of the plugin.\n * Is a function to build the source from the key and locale.\n *\n * ```ts\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`\n * })\n * ```\n */\n source: FilePathPattern;\n\n /**\n * Because Intlayer transform the JSON files into Dictionary, we need to identify the plugin in the dictionary.\n * Used to identify the plugin in the dictionary.\n *\n * In the case you have multiple plugins, you can use this to identify the plugin in the dictionary.\n *\n * ```ts\n * // Example usage:\n * const config = {\n * plugins: [\n * syncJSON({\n * source: ({ key, locale }) => `./resources/${locale}/${key}.json`,\n * location: 'plugin-i18next',\n * }),\n * syncJSON({\n * source: ({ key, locale }) => `./messages/${locale}/${key}.json`,\n * location: 'plugin-next-intl',\n * }),\n * ]\n * }\n * ```\n */\n location?: DictionaryLocation | (string & {});\n\n /**\n * The priority of the dictionaries created by the plugin.\n *\n * In the case of conflicts with remote dictionaries, or .content files, the dictionary with the highest priority will override the other dictionaries.\n *\n * Default is -1. (.content file priority is 0)\n *\n */\n priority?: number;\n\n /**\n * The format of the dictionaries created by the plugin.\n *\n * Default: 'intlayer'\n *\n * The format of the dictionaries created by the plugin.\n */\n format?: DictionaryFormat;\n\n /**\n * Whether each top-level key of the JSON file should become its own\n * dictionary (keyed by that top-level key) instead of a single dictionary\n * holding the whole file.\n *\n * This matches the namespace model of libraries such as `next-intl` /\n * `react-intl`, where a single `messages/{locale}.json` file groups several\n * namespaces by its first-level keys and each namespace is addressed\n * independently (e.g. `useTranslations('Hero')` → dictionary `Hero`).\n *\n * Pass `'key-prefix'` for *flat* catalogs whose keys are dotted ids rather\n * than nested objects — the single-catalog model of `lingui` and of\n * i18next's default `translation` namespace. Each id's first dot-segment\n * becomes a dictionary and the remainder becomes the key inside it, so\n * `'footer.github'` is addressed as dictionary `footer`, key `github`.\n * Write-back restores the flat dotted ids, leaving the source file in the\n * shape its library expects.\n *\n * When omitted, it is auto-detected: the file is split when the `source`\n * pattern has no `{{key}}` segment (i.e. one file holds every namespace),\n * and kept as a single dictionary otherwise (one file per key).\n *\n * @example\n * ```ts\n * // messages/en.json → dictionaries: Hero, Nav, About, …\n * syncJSON({\n * source: ({ locale }) => `./messages/${locale}.json`,\n * splitKeys: true,\n * })\n *\n * // locales/en/messages.json → { 'footer.github': …, 'hero.title': … }\n * // → dictionaries: footer, hero, …\n * syncJSON({\n * source: ({ locale }) => `./locales/${locale}/messages.json`,\n * splitKeys: 'key-prefix',\n * })\n * ```\n */\n splitKeys?: SplitKeysMode;\n};\n\n/**\n * Two-way JSON synchronization plugin: ingests JSON message files as\n * dictionaries and writes the merged build output back to the same files.\n */\nexport const syncJSON = async (\n options: SyncJSONPluginOptions\n): Promise<Plugin> => {\n // Generate a unique default location based on the source pattern.\n // This ensures that if you have multiple plugins, they don't share the same 'plugin' ID.\n const patternMarker = await parseFilePathPattern(\n options.source,\n buildFilePathPatternContext('{{key}}', '{{locale}}')\n );\n const defaultLocation = `sync-json::${patternMarker}`;\n\n return createSyncPlugin({\n name: 'sync-json',\n adapter: createFileAdapter({\n source: options.source,\n codec: jsonCodec,\n readEntry: readJSONEntry,\n discovery: 'strict',\n }),\n direction: 'both',\n location: options.location ?? defaultLocation,\n priority: options.priority ?? 0,\n format: options.format,\n // Auto-detected by the file adapter when omitted: split when the source\n // pattern has no `{{key}}` segment (one file holds every namespace).\n splitKeys: options.splitKeys,\n });\n};\n"],"mappings":";;;;;;;;;AAuHA,MAAa,WAAW,OACtB,YACoB;CAOpB,MAAM,kBAAkB,cAAc,MAJV,qBAC1B,QAAQ,QACR,4BAA4B,WAAW,YAAY,CACrD;CAGA,OAAO,iBAAiB;EACtB,MAAM;EACN,SAAS,kBAAkB;GACzB,QAAQ,QAAQ;GAChB,OAAO;GACP,WAAW;GACX,WAAW;EACb,CAAC;EACD,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ,QAAQ;EAGhB,WAAW,QAAQ;CACrB,CAAC;AACH"}
@@ -4,13 +4,12 @@ import { FormatCodec, SyncContent } from "@intlayer/engine/syncPluginKit";
4
4
  * JSON payload codec: standard JSON parsing, pretty-printed serialization
5
5
  * (2-space indentation, trailing newline).
6
6
  */
7
- declare const jsonCodec: FormatCodec;
7
+ export declare const jsonCodec: FormatCodec;
8
8
  /**
9
9
  * Read one JSON source through `loadExternalFile`, which also supports JSON5,
10
10
  * JSONC and transpiled JS/TS message files. Returns `undefined` for missing or
11
11
  * unreadable files so callers fall back to empty content.
12
12
  */
13
- declare const readJSONEntry: (absoluteFilePath: string) => Promise<SyncContent | undefined>;
13
+ export declare const readJSONEntry: (absoluteFilePath: string) => Promise<SyncContent | undefined>;
14
14
  //#endregion
15
- export { jsonCodec, readJSONEntry };
16
15
  //# sourceMappingURL=jsonCodec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jsonCodec.d.ts","names":[],"sources":["../../src/jsonCodec.ts"],"mappings":";;;;;;cAOa,WAAW;;;;;;cAUX,gBAAa,6BAEvB,QAAQ"}
1
+ {"version":3,"file":"jsonCodec.d.ts","names":[],"sources":["../../src/jsonCodec.ts"],"mappings":";;;;;;qBAOa,WAAW;;;;;;qBAUX,gBAAa,6BAEvB,QAAQ"}
@@ -1,9 +1,10 @@
1
+ import { SplitKeysMode } from "@intlayer/engine/syncPluginKit";
1
2
  import { Locale } from "@intlayer/types/allLocales";
2
3
  import { DictionaryFormat } from "@intlayer/types/dictionary";
3
4
  import { FilePathPattern } from "@intlayer/types/filePathPattern";
4
5
  import { Plugin } from "@intlayer/types/plugin";
5
6
  //#region src/loadJSON.d.ts
6
- type LoadJSONPluginOptions = {
7
+ export type LoadJSONPluginOptions = {
7
8
  /**
8
9
  * The source of the plugin.
9
10
  * Is a function to build the source from the key and locale.
@@ -85,13 +86,12 @@ type LoadJSONPluginOptions = {
85
86
  * When omitted, it is auto-detected: the file is split when the `source`
86
87
  * pattern has no `{{key}}` segment, and kept as a single dictionary otherwise.
87
88
  */
88
- splitKeys?: boolean;
89
+ splitKeys?: SplitKeysMode;
89
90
  };
90
91
  /**
91
92
  * Read-only JSON ingestion plugin: loads JSON message files as dictionaries
92
93
  * without ever writing back to them.
93
94
  */
94
- declare const loadJSON: (options: LoadJSONPluginOptions) => Plugin;
95
+ export declare const loadJSON: (options: LoadJSONPluginOptions) => Plugin;
95
96
  //#endregion
96
- export { LoadJSONPluginOptions, loadJSON };
97
97
  //# sourceMappingURL=loadJSON.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"loadJSON.d.ts","names":[],"sources":["../../src/loadJSON.ts"],"mappings":";;;;;KAUY;;;;;;;;;;;;EAYV,QAAQ;;;;;;;;;;;;;;EAeR,SAAS;;;;;;;;;;;;;;;;;;;;;;;EAwBT;;;;;;;;;EAUA;;;;;;;;;;;EAYA,SAAS;;;;;;;;;;;;;EAcT;;;;;;cAOW,WAAQ,SAAa,0BAAwB"}
1
+ {"version":3,"file":"loadJSON.d.ts","names":[],"sources":["../../src/loadJSON.ts"],"mappings":";;;;;;YAWY;;;;;;;;;;;;EAYV,QAAQ;;;;;;;;;;;;;;EAeR,SAAS;;;;;;;;;;;;;;;;;;;;;;;EAwBT;;;;;;;;;EAUA;;;;;;;;;;;EAYA,SAAS;;;;;;;;;;;;;EAcT,YAAY;;;;;;qBAOD,WAAQ,SAAa,0BAAwB"}
@@ -1,9 +1,9 @@
1
- import { extractKeyAndLocaleFromPath } from "@intlayer/engine/syncPluginKit";
1
+ import { SplitKeysMode, extractKeyAndLocaleFromPath } from "@intlayer/engine/syncPluginKit";
2
2
  import { DictionaryFormat, DictionaryLocation } from "@intlayer/types/dictionary";
3
3
  import { FilePathPattern } from "@intlayer/types/filePathPattern";
4
4
  import { Plugin } from "@intlayer/types/plugin";
5
5
  //#region src/syncJSON.d.ts
6
- type SyncJSONPluginOptions = {
6
+ export type SyncJSONPluginOptions = {
7
7
  /**
8
8
  * The source of the plugin.
9
9
  * Is a function to build the source from the key and locale.
@@ -65,6 +65,14 @@ type SyncJSONPluginOptions = {
65
65
  * namespaces by its first-level keys and each namespace is addressed
66
66
  * independently (e.g. `useTranslations('Hero')` → dictionary `Hero`).
67
67
  *
68
+ * Pass `'key-prefix'` for *flat* catalogs whose keys are dotted ids rather
69
+ * than nested objects — the single-catalog model of `lingui` and of
70
+ * i18next's default `translation` namespace. Each id's first dot-segment
71
+ * becomes a dictionary and the remainder becomes the key inside it, so
72
+ * `'footer.github'` is addressed as dictionary `footer`, key `github`.
73
+ * Write-back restores the flat dotted ids, leaving the source file in the
74
+ * shape its library expects.
75
+ *
68
76
  * When omitted, it is auto-detected: the file is split when the `source`
69
77
  * pattern has no `{{key}}` segment (i.e. one file holds every namespace),
70
78
  * and kept as a single dictionary otherwise (one file per key).
@@ -76,15 +84,22 @@ type SyncJSONPluginOptions = {
76
84
  * source: ({ locale }) => `./messages/${locale}.json`,
77
85
  * splitKeys: true,
78
86
  * })
87
+ *
88
+ * // locales/en/messages.json → { 'footer.github': …, 'hero.title': … }
89
+ * // → dictionaries: footer, hero, …
90
+ * syncJSON({
91
+ * source: ({ locale }) => `./locales/${locale}/messages.json`,
92
+ * splitKeys: 'key-prefix',
93
+ * })
79
94
  * ```
80
95
  */
81
- splitKeys?: boolean;
96
+ splitKeys?: SplitKeysMode;
82
97
  };
83
98
  /**
84
99
  * Two-way JSON synchronization plugin: ingests JSON message files as
85
100
  * dictionaries and writes the merged build output back to the same files.
86
101
  */
87
- declare const syncJSON: (options: SyncJSONPluginOptions) => Promise<Plugin>;
102
+ export declare const syncJSON: (options: SyncJSONPluginOptions) => Promise<Plugin>;
88
103
  //#endregion
89
- export { SyncJSONPluginOptions, extractKeyAndLocaleFromPath, syncJSON };
104
+ export { extractKeyAndLocaleFromPath };
90
105
  //# sourceMappingURL=syncJSON.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncJSON.d.ts","names":[],"sources":["../../src/syncJSON.ts"],"mappings":";;;;;KAiBY;;;;;;;;;;;EAWV,QAAQ;;;;;;;;;;;;;;;;;;;;;;;EAwBR,WAAW;;;;;;;;;EAUX;;;;;;;;EASA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;EAyBT;;;;;;cAOW,WAAQ,SACV,0BACR,QAAQ"}
1
+ {"version":3,"file":"syncJSON.d.ts","names":[],"sources":["../../src/syncJSON.ts"],"mappings":";;;;;YAkBY;;;;;;;;;;;EAWV,QAAQ;;;;;;;;;;;;;;;;;;;;;;;EAwBR,WAAW;;;;;;;;;EAUX;;;;;;;;EASA,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwCT,YAAY;;;;;;qBAOD,WAAQ,SACV,0BACR,QAAQ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/sync-json-plugin",
3
- "version": "9.4.3",
3
+ "version": "9.5.0",
4
4
  "private": false,
5
5
  "description": "A plugin for Intlayer that syncs JSON files to dictionaries.",
6
6
  "keywords": [
@@ -71,21 +71,21 @@
71
71
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
72
72
  },
73
73
  "dependencies": {
74
- "@intlayer/config": "9.4.3",
75
- "@intlayer/core": "9.4.3",
76
- "@intlayer/engine": "9.4.3",
77
- "@intlayer/types": "9.4.3",
74
+ "@intlayer/config": "9.5.0",
75
+ "@intlayer/core": "9.5.0",
76
+ "@intlayer/engine": "9.5.0",
77
+ "@intlayer/types": "9.5.0",
78
78
  "fast-glob": "3.3.3"
79
79
  },
80
80
  "devDependencies": {
81
- "@types/node": "26.4.1",
81
+ "@types/node": "26.5.0",
82
82
  "@utils/ts-config": "1.0.4",
83
83
  "@utils/ts-config-types": "1.0.4",
84
84
  "@utils/tsdown-config": "1.0.4",
85
85
  "rimraf": "6.1.3",
86
- "tsdown": "0.22.14",
86
+ "tsdown": "0.23.0",
87
87
  "typescript": "7.0.2",
88
- "vitest": "4.1.11"
88
+ "vitest": "5.0.0"
89
89
  },
90
90
  "engines": {
91
91
  "node": ">=14.18"