@intlayer/sync-json-plugin 9.0.0-canary.16 → 9.0.0-canary.18

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.
@@ -1 +1 @@
1
- {"version":3,"file":"jsonCodec.cjs","names":[],"sources":["../../src/jsonCodec.ts"],"sourcesContent":["import { loadExternalFile } from '@intlayer/config/file';\nimport type { FormatCodec, SyncContent } from '@intlayer/engine/syncPluginKit';\n\n/**\n * JSON payload codec: standard JSON parsing, pretty-printed serialization\n * (2-space indentation, trailing newline).\n */\nexport const jsonCodec: FormatCodec = {\n parse: (raw) => JSON.parse(raw),\n serialize: (content) => `${JSON.stringify(content, null, 2)}\\n`,\n};\n\n/**\n * Read one JSON source through `loadExternalFile`, which also supports JSON5,\n * JSONC and transpiled JS/TS message files. Returns `undefined` for missing or\n * unreadable files so callers fall back to empty content.\n */\nexport const readJSONEntry = async (\n absoluteFilePath: string\n): Promise<SyncContent | undefined> =>\n await loadExternalFile(absoluteFilePath, { logError: false });\n"],"mappings":";;;;;;;;AAOA,MAAa,YAAyB;CACpC,QAAQ,QAAQ,KAAK,MAAM,IAAI;CAC/B,YAAY,YAAY,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;CAC7D;;;;;;AAOD,MAAa,gBAAgB,OAC3B,qBAEA,kDAAuB,kBAAkB,EAAE,UAAU,OAAO,CAAC"}
1
+ {"version":3,"file":"jsonCodec.cjs","names":[],"sources":["../../src/jsonCodec.ts"],"sourcesContent":["import { loadExternalFile } from '@intlayer/config/file';\nimport type { FormatCodec, SyncContent } from '@intlayer/engine/syncPluginKit';\n\n/**\n * JSON payload codec: standard JSON parsing, pretty-printed serialization\n * (2-space indentation, trailing newline).\n */\nexport const jsonCodec: FormatCodec = {\n parse: (raw) => JSON.parse(raw),\n serialize: (content) => `${JSON.stringify(content, null, 2)}\\n`,\n};\n\n/**\n * Read one JSON source through `loadExternalFile`, which also supports JSON5,\n * JSONC and transpiled JS/TS message files. Returns `undefined` for missing or\n * unreadable files so callers fall back to empty content.\n */\nexport const readJSONEntry = async (\n absoluteFilePath: string\n): Promise<SyncContent | undefined> =>\n await loadExternalFile(absoluteFilePath, { logError: false });\n"],"mappings":";;;;;;;;AAOA,MAAa,YAAyB;CACpC,QAAQ,QAAQ,KAAK,MAAM,GAAG;CAC9B,YAAY,YAAY,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE;AAC9D;;;;;;AAOA,MAAa,gBAAgB,OAC3B,qBAEA,kDAAuB,kBAAkB,EAAE,UAAU,MAAM,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadJSON.cjs","names":["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,iEACN;CACf,MAAM;CACN,+DAA2B;EACzB,QAAQ,QAAQ;EAChB,OAAOA;EACP,WAAWC;EACX,WAAW;EACZ,CAAC;CACF,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ,QAAQ;CAChB,WAAW,QAAQ;CACnB,gBAAgB,QAAQ;CACzB,CAAC"}
1
+ {"version":3,"file":"loadJSON.cjs","names":["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,iEACN;CACf,MAAM;CACN,+DAA2B;EACzB,QAAQ,QAAQ;EAChB,OAAOA;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":["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,uDAHpC,QAAQ,wEACoB,WAAW,aAAa,CACrD;AAGD,6DAAwB;EACtB,MAAM;EACN,+DAA2B;GACzB,QAAQ,QAAQ;GAChB,OAAOA;GACP,WAAWC;GACX,WAAW;GACZ,CAAC;EACF,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ,QAAQ;EAGhB,WAAW,QAAQ;EACpB,CAAC"}
1
+ {"version":3,"file":"syncJSON.cjs","names":["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,uDAHpC,QAAQ,wEACoB,WAAW,YAAY,CACrD;CAGA,4DAAwB;EACtB,MAAM;EACN,+DAA2B;GACzB,QAAQ,QAAQ;GAChB,OAAOA;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":"jsonCodec.mjs","names":[],"sources":["../../src/jsonCodec.ts"],"sourcesContent":["import { loadExternalFile } from '@intlayer/config/file';\nimport type { FormatCodec, SyncContent } from '@intlayer/engine/syncPluginKit';\n\n/**\n * JSON payload codec: standard JSON parsing, pretty-printed serialization\n * (2-space indentation, trailing newline).\n */\nexport const jsonCodec: FormatCodec = {\n parse: (raw) => JSON.parse(raw),\n serialize: (content) => `${JSON.stringify(content, null, 2)}\\n`,\n};\n\n/**\n * Read one JSON source through `loadExternalFile`, which also supports JSON5,\n * JSONC and transpiled JS/TS message files. Returns `undefined` for missing or\n * unreadable files so callers fall back to empty content.\n */\nexport const readJSONEntry = async (\n absoluteFilePath: string\n): Promise<SyncContent | undefined> =>\n await loadExternalFile(absoluteFilePath, { logError: false });\n"],"mappings":";;;;;;;AAOA,MAAa,YAAyB;CACpC,QAAQ,QAAQ,KAAK,MAAM,IAAI;CAC/B,YAAY,YAAY,GAAG,KAAK,UAAU,SAAS,MAAM,EAAE,CAAC;CAC7D;;;;;;AAOD,MAAa,gBAAgB,OAC3B,qBAEA,MAAM,iBAAiB,kBAAkB,EAAE,UAAU,OAAO,CAAC"}
1
+ {"version":3,"file":"jsonCodec.mjs","names":[],"sources":["../../src/jsonCodec.ts"],"sourcesContent":["import { loadExternalFile } from '@intlayer/config/file';\nimport type { FormatCodec, SyncContent } from '@intlayer/engine/syncPluginKit';\n\n/**\n * JSON payload codec: standard JSON parsing, pretty-printed serialization\n * (2-space indentation, trailing newline).\n */\nexport const jsonCodec: FormatCodec = {\n parse: (raw) => JSON.parse(raw),\n serialize: (content) => `${JSON.stringify(content, null, 2)}\\n`,\n};\n\n/**\n * Read one JSON source through `loadExternalFile`, which also supports JSON5,\n * JSONC and transpiled JS/TS message files. Returns `undefined` for missing or\n * unreadable files so callers fall back to empty content.\n */\nexport const readJSONEntry = async (\n absoluteFilePath: string\n): Promise<SyncContent | undefined> =>\n await loadExternalFile(absoluteFilePath, { logError: false });\n"],"mappings":";;;;;;;AAOA,MAAa,YAAyB;CACpC,QAAQ,QAAQ,KAAK,MAAM,GAAG;CAC9B,YAAY,YAAY,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE;AAC9D;;;;;;AAOA,MAAa,gBAAgB,OAC3B,qBAEA,MAAM,iBAAiB,kBAAkB,EAAE,UAAU,MAAM,CAAC"}
@@ -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;EACZ,CAAC;CACF,WAAW;CACX,UAAU,QAAQ,YAAY;CAC9B,UAAU,QAAQ,YAAY;CAC9B,QAAQ,QAAQ;CAChB,WAAW,QAAQ;CACnB,gBAAgB,QAAQ;CACzB,CAAC"}
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 +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,aAAa,CACrD;AAGD,QAAO,iBAAiB;EACtB,MAAM;EACN,SAAS,kBAAkB;GACzB,QAAQ,QAAQ;GAChB,OAAO;GACP,WAAW;GACX,WAAW;GACZ,CAAC;EACF,WAAW;EACX,UAAU,QAAQ,YAAY;EAC9B,UAAU,QAAQ,YAAY;EAC9B,QAAQ,QAAQ;EAGhB,WAAW,QAAQ;EACpB,CAAC"}
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,5 +1,4 @@
1
1
  import { FormatCodec, SyncContent } from "@intlayer/engine/syncPluginKit";
2
-
3
2
  //#region src/jsonCodec.d.ts
4
3
  /**
5
4
  * JSON payload codec: standard JSON parsing, pretty-printed serialization
@@ -1 +1 @@
1
- {"version":3,"file":"jsonCodec.d.ts","names":[],"sources":["../../src/jsonCodec.ts"],"mappings":";;;;;AAOA;;cAAa,SAAA,EAAW,WAAA;;;AAUxB;;;cAAa,aAAA,GACX,gBAAA,aACC,OAAA,CAAQ,WAAA"}
1
+ {"version":3,"file":"jsonCodec.d.ts","names":[],"sources":["../../src/jsonCodec.ts"],"mappings":";;;;;;cAOa,WAAW;;;;;;cAUX,gBAAa,6BAEvB,QAAQ"}
@@ -2,7 +2,6 @@ import { Locale } from "@intlayer/types/allLocales";
2
2
  import { DictionaryFormat } from "@intlayer/types/dictionary";
3
3
  import { FilePathPattern } from "@intlayer/types/filePathPattern";
4
4
  import { Plugin } from "@intlayer/types/plugin";
5
-
6
5
  //#region src/loadJSON.d.ts
7
6
  type LoadJSONPluginOptions = {
8
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"loadJSON.d.ts","names":[],"sources":["../../src/loadJSON.ts"],"mappings":";;;;;;KAUY,qBAAA;;AAAZ;;;;;;;;;;EAYE,MAAA,EAAQ,eAAA;EAeC;;;;;;;;AAmEX;;;;;EAnEE,MAAA,GAAS,MAAA;EAmE+C;;;;;;;;;;;;;;;;;;;;;;EA3CxD,QAAA;;;;;;;;;EAUA,QAAA;;;;;;;;;;;EAYA,MAAA,GAAS,gBAAA;;;;;;;;;;;;;EAcT,SAAA;AAAA;;;;;cAOW,QAAA,GAAY,OAAA,EAAS,qBAAA,KAAwB,MAAA"}
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"}
@@ -2,7 +2,6 @@ import { 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
-
6
5
  //#region src/syncJSON.d.ts
7
6
  type SyncJSONPluginOptions = {
8
7
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"syncJSON.d.ts","names":[],"sources":["../../src/syncJSON.ts"],"mappings":";;;;;;KAiBY,qBAAA;;AAAZ;;;;;;;;;EAWE,MAAA,EAAQ,eAAA;EAwBR;;;;;;;;AAmDF;;;;;;;;;;;;;;EAnDE,QAAA,GAAW,kBAAA;;;;;;;;;EAUX,QAAA;;;;;;;;EASA,MAAA,GAAS,gBAAA;;;;;;;;;;;;;;;;;;;;;;;;EAyBT,SAAA;AAAA;;;;;cAOW,QAAA,GACX,OAAA,EAAS,qBAAA,KACR,OAAA,CAAQ,MAAA"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/sync-json-plugin",
3
- "version": "9.0.0-canary.16",
3
+ "version": "9.0.0-canary.18",
4
4
  "private": false,
5
5
  "description": "A plugin for Intlayer that syncs JSON files to dictionaries.",
6
6
  "keywords": [
@@ -71,20 +71,20 @@
71
71
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
72
72
  },
73
73
  "dependencies": {
74
- "@intlayer/config": "9.0.0-canary.16",
75
- "@intlayer/core": "9.0.0-canary.16",
76
- "@intlayer/engine": "9.0.0-canary.16",
77
- "@intlayer/types": "9.0.0-canary.16",
74
+ "@intlayer/config": "9.0.0-canary.18",
75
+ "@intlayer/core": "9.0.0-canary.18",
76
+ "@intlayer/engine": "9.0.0-canary.18",
77
+ "@intlayer/types": "9.0.0-canary.18",
78
78
  "fast-glob": "3.3.3"
79
79
  },
80
80
  "devDependencies": {
81
- "@types/node": "25.9.4",
81
+ "@types/node": "26.1.1",
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.21.10",
87
- "typescript": "6.0.3",
86
+ "tsdown": "0.22.12",
87
+ "typescript": "7.0.2",
88
88
  "vitest": "4.1.10"
89
89
  },
90
90
  "engines": {