@intlayer/types 9.0.0-canary.17 → 9.0.0-canary.19

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,7 +1,6 @@
1
1
  import { DeclaredLocales, LocalesValues, Schema, SchemaKeys } from "./module_augmentation.js";
2
2
  import { FilePathPattern } from "./filePathPattern.js";
3
3
  import { NodeType } from "./nodeType.js";
4
-
5
4
  //#region src/dictionary.d.ts
6
5
  type BaseNode = number | string | boolean | null | undefined;
7
6
  type TypedNodeBase = {
@@ -9,144 +8,145 @@ type TypedNodeBase = {
9
8
  };
10
9
  interface TypedNode<_NodeType = undefined> extends TypedNodeBase {}
11
10
  type FetchableContentNode<NodeType> = (args?: any) => ContentNode<NodeType> | Promise<ContentNode<NodeType>>;
12
- type ContentNode<T = undefined, FetchableNode = false, NodeType = (T extends undefined ? BaseNode : T)> = NodeType | TypedNode<NodeType> | ((args?: any) => ContentNode<NodeType>) | (FetchableNode extends true ? FetchableContentNode<NodeType> : undefined);
11
+ type ContentNode<T = undefined, FetchableNode = false, NodeType = T extends undefined ? BaseNode : T> = NodeType | TypedNode<NodeType> | ((args?: any) => ContentNode<NodeType>) | (FetchableNode extends true ? FetchableContentNode<NodeType> : undefined);
13
12
  type IsArray<T> = T extends any[] ? true : false;
14
13
  type ReplaceContentValueArray<T, FetchableNode> = T extends (infer U)[] ? ContentNode<T, FetchableNode> | ReplaceContentValue<U, FetchableNode>[] : never;
15
- type ReplaceContentValueObject<T, FetchableNode> = { [K in keyof T]: ReplaceContentValue<T[K], FetchableNode> };
14
+ type ReplaceContentValueObject<T, FetchableNode> = { [K in keyof T]: ReplaceContentValue<T[K], FetchableNode>; };
16
15
  type ReplaceContentValue<NodeType, FetchableNode = true> = NodeType extends object ? IsArray<NodeType> extends true ? ReplaceContentValueArray<NodeType, FetchableNode> : ContentNode<NodeType, FetchableNode> | ReplaceContentValueObject<NodeType, FetchableNode> : ContentNode<NodeType, FetchableNode>;
17
16
  /**
18
- * Indicate how the dictionary should be filled using AI.
19
- *
20
- * Default: `true`
21
- *
22
- * - If `true`, will consider the `compiler.output` field.
23
- * - If `false`, will skip the fill process.
24
- *
25
- * - `./` paths are resolved relative to the component directory.
26
- * - `/` paths are resolved relative to the project root (`baseDir`).
27
- *
28
- * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.
29
- *
30
- * Example:
31
- * ```ts
32
- * {
33
- * // Create Multilingual .content.ts files close to the component
34
- * fill: ({ fileName, extension }) => `./${fileName}${extension}`,
35
- *
36
- * // fill: './{{fileName}}{{extension}}', // Equivalent using template string
37
- * }
38
- * ```
39
- *
40
- * ```ts
41
- * {
42
- * // Create centralize per-locale JSON at the root of the project
43
- * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,
44
- *
45
- * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string
46
- * }
47
- * ```
48
- *
49
- * ```ts
50
- * {
51
- * // Create custom output based on the locale
52
- * fill: {
53
- * en: ({ key }) => `/locales/en/${key}.content.json`,
54
- * fr: '/locales/fr/{{key}}.content.json',
55
- * es: false,
56
- * de: true,
57
- * },
58
- * }
59
- * ```
60
- *
61
- *
62
- * Variable list:
63
- * - `fileName`: The name of the file.
64
- * - `key`: The key of the content.
65
- * - `locale`: The locale of the content.
66
- * - `extension`: The extension of the file.
67
- * - `componentFileName`: The name of the component file.
68
- * - `componentExtension`: The extension of the component file.
69
- * - `format`: The format of the dictionary.
70
- * - `componentFormat`: The format of the component dictionary.
71
- * - `componentDirPath`: The directory path of the component.
72
- */
17
+ * Indicate how the dictionary should be filled using AI.
18
+ *
19
+ * Default: `true`
20
+ *
21
+ * - If `true`, will consider the `compiler.output` field.
22
+ * - If `false`, will skip the fill process.
23
+ *
24
+ * - `./` paths are resolved relative to the component directory.
25
+ * - `/` paths are resolved relative to the project root (`baseDir`).
26
+ *
27
+ * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.
28
+ *
29
+ * Example:
30
+ * ```ts
31
+ * {
32
+ * // Create Multilingual .content.ts files close to the component
33
+ * fill: ({ fileName, extension }) => `./${fileName}${extension}`,
34
+ *
35
+ * // fill: './{{fileName}}{{extension}}', // Equivalent using template string
36
+ * }
37
+ * ```
38
+ *
39
+ * ```ts
40
+ * {
41
+ * // Create centralize per-locale JSON at the root of the project
42
+ * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,
43
+ *
44
+ * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string
45
+ * }
46
+ * ```
47
+ *
48
+ * ```ts
49
+ * {
50
+ * // Create custom output based on the locale
51
+ * fill: {
52
+ * en: ({ key }) => `/locales/en/${key}.content.json`,
53
+ * fr: '/locales/fr/{{key}}.content.json',
54
+ * es: false,
55
+ * de: true,
56
+ * },
57
+ * }
58
+ * ```
59
+ *
60
+ *
61
+ * Variable list:
62
+ * - `fileName`: The name of the file.
63
+ * - `key`: The key of the content.
64
+ * - `locale`: The locale of the content.
65
+ * - `extension`: The extension of the file.
66
+ * - `componentFileName`: The name of the component file.
67
+ * - `componentExtension`: The extension of the component file.
68
+ * - `format`: The format of the dictionary.
69
+ * - `componentFormat`: The format of the component dictionary.
70
+ * - `componentDirPath`: The directory path of the component.
71
+ */
73
72
  type Fill = boolean | FilePathPattern | Partial<Record<DeclaredLocales, boolean | FilePathPattern>>;
74
73
  type DictionaryId = string;
75
74
  type DictionaryKey = string;
76
75
  /**
77
- * A dimension used to discriminate sibling dictionaries sharing the same key.
78
- *
79
- * - 'variant': named or structured alternative content (A/B testing, seasonal
80
- * banners, CMS records, user-specific copy…). The variant value is a string
81
- * (named) or an object (structured discriminator).
82
- * - 'item': ordered collection items (blog posts, FAQs…)
83
- *
84
- * A key may declare BOTH dimensions at once (e.g. a collection whose items also
85
- * have variants). They are always ordered canonically as `variant → item`,
86
- * with `item` as the innermost / collection axis.
87
- */
76
+ * A dimension used to discriminate sibling dictionaries sharing the same key.
77
+ *
78
+ * - 'variant': named or structured alternative content (A/B testing, seasonal
79
+ * banners, CMS records, user-specific copy…). The variant value is a string
80
+ * (named) or an object (structured discriminator).
81
+ * - 'item': ordered collection items (blog posts, FAQs…)
82
+ *
83
+ * A key may declare BOTH dimensions at once (e.g. a collection whose items also
84
+ * have variants). They are always ordered canonically as `variant → item`,
85
+ * with `item` as the innermost / collection axis.
86
+ */
88
87
  type DictionaryQualifierType = "variant" | "item";
89
88
  /**
90
- * A single variant value declared on a dictionary:
91
- *
92
- * - a **string** — a named alternative (`'black-friday'`)
93
- * - an **object** — a structured discriminator whose canonical serialization
94
- * (sorted `key=value` pairs joined by `&`) is the variant identity
95
- *
96
- * The `variant` field of a dictionary accepts one value or an **array** of
97
- * values — an array registers the same content under every listed variant id.
98
- */
89
+ * A single variant value declared on a dictionary:
90
+ *
91
+ * - a **string** — a named alternative (`'black-friday'`)
92
+ * - an **object** — a structured discriminator whose canonical serialization
93
+ * (sorted `key=value` pairs joined by `&`) is the variant identity
94
+ *
95
+ * The `variant` field of a dictionary accepts one value or an **array** of
96
+ * values — an array registers the same content under every listed variant id.
97
+ */
99
98
  type DictionaryVariantValue = string | Record<string, string | number>;
100
99
  /**
101
- * Output of the merge step for a key whose dictionaries declare one or more
102
- * qualifier dimensions (`variant`, `item`).
103
- *
104
- * Sibling dictionaries sharing the same qualifier coordinates are merged
105
- * together (locale completion / priority overrides preserved). Sibling
106
- * dictionaries without any qualifier act as shared base content merged into
107
- * every entry as fallback.
108
- *
109
- * `content` is keyed by the composite id — the per-dimension ids joined in
110
- * canonical order with `/` (e.g. `"promo/2"` for a variant × item key). For an
111
- * object variant the variant segment is the canonical serialization of the
112
- * object (e.g. `"id=abc&userId=123"`). Each value is the resolved content node
113
- * directly: the qualifier coordinates are decoded from the composite id, not
114
- * duplicated on a per-entry wrapper.
115
- *
116
- * Example (`.intlayer/dictionaries/faq.json`):
117
- * ```json
118
- * {
119
- * "key": "faq",
120
- * "qualifierTypes": ["item"],
121
- * "content": {
122
- * "1": { "nodeType": "translation", "translation": { ... } },
123
- * "2": { "nodeType": "translation", "translation": { ... } }
124
- * }
125
- * }
126
- * ```
127
- */
100
+ * Output of the merge step for a key whose dictionaries declare one or more
101
+ * qualifier dimensions (`variant`, `item`).
102
+ *
103
+ * Sibling dictionaries sharing the same qualifier coordinates are merged
104
+ * together (locale completion / priority overrides preserved). Sibling
105
+ * dictionaries without any qualifier act as shared base content merged into
106
+ * every entry as fallback.
107
+ *
108
+ * `content` is keyed by the composite id — the per-dimension ids joined in
109
+ * canonical order with `/` (e.g. `"promo/2"` for a variant × item key). For an
110
+ * object variant the variant segment is the canonical serialization of the
111
+ * object (e.g. `"id=abc&userId=123"`). Each value is the resolved content node
112
+ * directly: the qualifier coordinates are decoded from the composite id, not
113
+ * duplicated on a per-entry wrapper.
114
+ *
115
+ * Example (`.intlayer/dictionaries/faq.json`):
116
+ * ```json
117
+ * {
118
+ * "key": "faq",
119
+ * "qualifierTypes": ["item"],
120
+ * "content": {
121
+ * "1": { "nodeType": "translation", "translation": { ... } },
122
+ * "2": { "nodeType": "translation", "translation": { ... } }
123
+ * }
124
+ * }
125
+ * ```
126
+ */
128
127
  type QualifiedDictionaryGroup = {
129
128
  $schema?: "https://intlayer.org/schema.json";
130
129
  key: DictionaryKey;
131
130
  qualifierTypes: DictionaryQualifierType[];
132
131
  /**
133
- * Maps each composite id to its resolved content node. Replaces the former
134
- * per-entry `Dictionary` wrapper — coordinates live in the key, not the value.
135
- */
136
- content: Record<string, unknown>; /** Import mode shared by the group (collected from its qualified entries). */
132
+ * Maps each composite id to its resolved content node. Replaces the former
133
+ * per-entry `Dictionary` wrapper — coordinates live in the key, not the value.
134
+ */
135
+ content: Record<string, unknown>;
136
+ /** Import mode shared by the group (collected from its qualified entries). */
137
137
  importMode?: ImportMode;
138
138
  localIds?: LocalDictionaryId[];
139
139
  };
140
140
  /**
141
- * Selector accepted as second argument of `useIntlayer` / `getIntlayer` (and
142
- * forwarded by the build-time transform to `useDictionary` / `getDictionary`).
143
- *
144
- * - `{ item: 2 }` selects a collection item (1-based index)
145
- * - `{ variant: 'black-friday' }` selects a named variant
146
- * - `{ variant: { id: 'prod_abc', userId: '123' } }` selects a structured
147
- * variant; the object must equal the variant declared on the dictionary
148
- * - `locale` composes with any of the above and overrides the context locale
149
- */
141
+ * Selector accepted as second argument of `useIntlayer` / `getIntlayer` (and
142
+ * forwarded by the build-time transform to `useDictionary` / `getDictionary`).
143
+ *
144
+ * - `{ item: 2 }` selects a collection item (1-based index)
145
+ * - `{ variant: 'black-friday' }` selects a named variant
146
+ * - `{ variant: { id: 'prod_abc', userId: '123' } }` selects a structured
147
+ * variant; the object must equal the variant declared on the dictionary
148
+ * - `locale` composes with any of the above and overrides the context locale
149
+ */
150
150
  type DictionarySelector = {
151
151
  locale?: LocalesValues;
152
152
  item?: number;
@@ -158,17 +158,17 @@ type QualifiedEntryContent<Entry> = Entry extends {
158
158
  /** Splits a composite id literal (`"a/b/c"`) into its ordered segments. */
159
159
  type SplitCompositeId<Id extends string> = Id extends `${infer Head}/${infer Tail}` ? [Head, ...SplitCompositeId<Tail>] : [Id];
160
160
  /**
161
- * Zips the declared qualifier dimensions with the segments decoded from a
162
- * composite id into a coordinate record (e.g. `['variant', 'item']` +
163
- * `['promo', '2']` → `{ variant: 'promo'; item: '2' }`).
164
- */
165
- type ZipQualifierCoordinates<QualifierTypes extends readonly DictionaryQualifierType[], Segments extends readonly string[]> = { [Index in keyof QualifierTypes as QualifierTypes[Index] extends DictionaryQualifierType ? QualifierTypes[Index] : never]: Index extends keyof Segments ? Segments[Index] : never };
161
+ * Zips the declared qualifier dimensions with the segments decoded from a
162
+ * composite id into a coordinate record (e.g. `['variant', 'item']` +
163
+ * `['promo', '2']` → `{ variant: 'promo'; item: '2' }`).
164
+ */
165
+ type ZipQualifierCoordinates<QualifierTypes extends readonly DictionaryQualifierType[], Segments extends readonly string[]> = { [Index in keyof QualifierTypes as QualifierTypes[Index] extends DictionaryQualifierType ? QualifierTypes[Index] : never]: Index extends keyof Segments ? Segments[Index] : never; };
166
166
  /**
167
- * Rebuilds the per-entry shape (`{ variant; item; content }`) from the
168
- * `content` map keyed by composite id, so the coordinate-comparison helpers can
169
- * be reused unchanged. Coordinates are decoded from each key.
170
- */
171
- type ReconstructedEntries<ContentMap, QualifierTypes extends readonly DictionaryQualifierType[]> = { [Key in keyof ContentMap & string]: ZipQualifierCoordinates<QualifierTypes, SplitCompositeId<Key>> extends infer Coordinates ? {
167
+ * Rebuilds the per-entry shape (`{ variant; item; content }`) from the
168
+ * `content` map keyed by composite id, so the coordinate-comparison helpers can
169
+ * be reused unchanged. Coordinates are decoded from each key.
170
+ */
171
+ type ReconstructedEntries<ContentMap, QualifierTypes extends readonly DictionaryQualifierType[]> = { [Key in keyof ContentMap & string]: ZipQualifierCoordinates<QualifierTypes, SplitCompositeId<Key>> extends (infer Coordinates) ? {
172
172
  content: ContentMap[Key];
173
173
  } & (Coordinates extends {
174
174
  variant: infer V;
@@ -178,17 +178,17 @@ type ReconstructedEntries<ContentMap, QualifierTypes extends readonly Dictionary
178
178
  item: infer Item;
179
179
  } ? {
180
180
  item: Item;
181
- } : unknown) : never };
181
+ } : unknown) : never; };
182
182
  /** Stringifies a literal coordinate for comparison. */
183
183
  type StringifyCoordinate<Value> = Value extends string | number ? `${Value}` : never;
184
184
  /** Literal equality between two coordinate values. */
185
185
  type CoordinateEquals<Left, Right> = [StringifyCoordinate<Left>] extends [StringifyCoordinate<Right>] ? true : false;
186
186
  /**
187
- * The variant coordinate a selector pins. A string variant is matched
188
- * precisely; an object variant broadens to `string` (it matches any declared
189
- * variant entry, since the object identity is not reconstructable at the type
190
- * level). An absent selector defaults to the `'default'` variant.
191
- */
187
+ * The variant coordinate a selector pins. A string variant is matched
188
+ * precisely; an object variant broadens to `string` (it matches any declared
189
+ * variant entry, since the object identity is not reconstructable at the type
190
+ * level). An absent selector defaults to the `'default'` variant.
191
+ */
192
192
  type SelectorVariant<Selector> = Selector extends {
193
193
  variant: infer Variant;
194
194
  } ? Variant extends string ? Variant : string : "default";
@@ -196,35 +196,35 @@ type SelectorItem<Selector> = Selector extends {
196
196
  item: infer Item;
197
197
  } ? Item : undefined;
198
198
  /**
199
- * Whether a single group entry matches the selector across every declared
200
- * dimension. The `item` dimension matches any value when the selector leaves it
201
- * open (collection axis).
202
- */
199
+ * Whether a single group entry matches the selector across every declared
200
+ * dimension. The `item` dimension matches any value when the selector leaves it
201
+ * open (collection axis).
202
+ */
203
203
  type EntryMatchesSelector<Entry, QualifierTypes extends readonly DictionaryQualifierType[], Selector> = ("variant" extends QualifierTypes[number] ? Entry extends {
204
204
  variant: infer Variant;
205
205
  } ? CoordinateEquals<Variant, SelectorVariant<Selector>> : false : true) extends true ? "item" extends QualifierTypes[number] ? [SelectorItem<Selector>] extends [undefined] ? true : Entry extends {
206
206
  item: infer Item;
207
207
  } ? CoordinateEquals<Item, SelectorItem<Selector>> : false : true : false;
208
208
  /** Entries that match the selector. */
209
- type MatchingEntries<Entries, QualifierTypes extends readonly DictionaryQualifierType[], Selector> = { [Key in keyof Entries as EntryMatchesSelector<Entries[Key], QualifierTypes, Selector> extends true ? Key : never]: Entries[Key] };
209
+ type MatchingEntries<Entries, QualifierTypes extends readonly DictionaryQualifierType[], Selector> = { [Key in keyof Entries as EntryMatchesSelector<Entries[Key], QualifierTypes, Selector> extends true ? Key : never]: Entries[Key]; };
210
210
  /** Whether the collection (`item`) axis is left open (→ array result). */
211
211
  type IsItemAxisOpen<QualifierTypes extends readonly DictionaryQualifierType[], Selector> = "item" extends QualifierTypes[number] ? [SelectorItem<Selector>] extends [undefined] ? true : false : false;
212
212
  /**
213
- * Computes the content type returned by `getIntlayer` / `getDictionary` for a
214
- * dictionary (or qualified dictionary group) `T` given the selector argument
215
- * `Selector`.
216
- *
217
- * The result is resolved against the **specific** entries the selector targets
218
- * (matched across variant / item coordinates), never the union of every
219
- * entry:
220
- * - `item` left open → array of the matching entries' content
221
- * - all dimensions pinned → that single entry's content (or `null` if none match)
222
- * - plain dictionary → its `content` (selector ignored)
223
- */
213
+ * Computes the content type returned by `getIntlayer` / `getDictionary` for a
214
+ * dictionary (or qualified dictionary group) `T` given the selector argument
215
+ * `Selector`.
216
+ *
217
+ * The result is resolved against the **specific** entries the selector targets
218
+ * (matched across variant / item coordinates), never the union of every
219
+ * entry:
220
+ * - `item` left open → array of the matching entries' content
221
+ * - all dimensions pinned → that single entry's content (or `null` if none match)
222
+ * - plain dictionary → its `content` (selector ignored)
223
+ */
224
224
  type ResolveQualifiedDictionaryContent<T, Selector = undefined> = T extends {
225
225
  qualifierTypes: infer QualifierTypes extends readonly DictionaryQualifierType[];
226
226
  content: infer ContentMap extends Record<string, any>;
227
- } ? ReconstructedEntries<ContentMap, QualifierTypes> extends infer Entries ? IsItemAxisOpen<QualifierTypes, Selector> extends true ? QualifiedEntryContent<MatchingEntries<Entries, QualifierTypes, Selector>[keyof MatchingEntries<Entries, QualifierTypes, Selector>]>[] : [keyof MatchingEntries<Entries, QualifierTypes, Selector>] extends [never] ? null : QualifiedEntryContent<MatchingEntries<Entries, QualifierTypes, Selector>[keyof MatchingEntries<Entries, QualifierTypes, Selector>]> : never : T extends {
227
+ } ? ReconstructedEntries<ContentMap, QualifierTypes> extends (infer Entries) ? IsItemAxisOpen<QualifierTypes, Selector> extends true ? QualifiedEntryContent<MatchingEntries<Entries, QualifierTypes, Selector>[keyof MatchingEntries<Entries, QualifierTypes, Selector>]>[] : [keyof MatchingEntries<Entries, QualifierTypes, Selector>] extends [never] ? null : QualifiedEntryContent<MatchingEntries<Entries, QualifierTypes, Selector>[keyof MatchingEntries<Entries, QualifierTypes, Selector>]> : never : T extends {
228
228
  content: infer Content;
229
229
  } ? Content : never;
230
230
  /** Distributes over the union of a group's entries. */
@@ -239,12 +239,12 @@ type EntryItem<Entry> = Entry extends {
239
239
  item: infer Item;
240
240
  } ? Item : never;
241
241
  /**
242
- * The selector accepted for a specific qualified dictionary group `T`: each
243
- * dimension is constrained to the coordinates that actually exist, so an unknown
244
- * `item` is a compile-time error. Named (string) variants are suggested for
245
- * autocomplete; object variants are accepted via the loose `Record` form. Plain
246
- * dictionaries (no `entries`) fall back to the loose {@link DictionarySelector}.
247
- */
242
+ * The selector accepted for a specific qualified dictionary group `T`: each
243
+ * dimension is constrained to the coordinates that actually exist, so an unknown
244
+ * `item` is a compile-time error. Named (string) variants are suggested for
245
+ * autocomplete; object variants are accepted via the loose `Record` form. Plain
246
+ * dictionaries (no `entries`) fall back to the loose {@link DictionarySelector}.
247
+ */
248
248
  type DictionarySelectorForGroup<T> = [GroupEntryUnion<T>] extends [never] ? DictionarySelector : {
249
249
  locale?: LocalesValues;
250
250
  } & ([EntryVariant<GroupEntryUnion<T>>] extends [never] ? unknown : {
@@ -256,360 +256,360 @@ type DictionaryLocation = "remote" | "local" | "hybrid" | "plugin" | (string & {
256
256
  type LocalDictionaryId = `${DictionaryKey}::${Dictionary["location"]}::${Dictionary["filePath"] | DictionaryId}`;
257
257
  type DictionaryFormat = "intlayer" | "icu" | "i18next" | "vue-i18n" | "po";
258
258
  /**
259
- * Indicates the mode of import to use for the dictionary.
260
- *
261
- * Available modes:
262
- * - "static": The dictionaries are imported statically.
263
- * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.
264
- * - "dynamic": The dictionaries are imported dynamically in a synchronous component using the suspense API.
265
- * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
266
- * - "live": The dictionaries are imported dynamically using the live sync API.
267
- * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
268
- * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as "dynamic" mode.
269
- *
270
- * Default: "static"
271
- */
259
+ * Indicates the mode of import to use for the dictionary.
260
+ *
261
+ * Available modes:
262
+ * - "static": The dictionaries are imported statically.
263
+ * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.
264
+ * - "dynamic": The dictionaries are imported dynamically in a synchronous component using the suspense API.
265
+ * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
266
+ * - "live": The dictionaries are imported dynamically using the live sync API.
267
+ * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
268
+ * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as "dynamic" mode.
269
+ *
270
+ * Default: "static"
271
+ */
272
272
  type ImportMode = "static" | "dynamic" | "fetch";
273
273
  type ContentAutoTransformation = boolean | {
274
274
  /**
275
- * Indicates if the content should be automatically transformed to a markdown node.
276
- * Default: true
277
- */
275
+ * Indicates if the content should be automatically transformed to a markdown node.
276
+ * Default: true
277
+ */
278
278
  markdown?: boolean;
279
279
  /**
280
- * Indicates if the content should be automatically transformed to an HTML node.
281
- * Default: true
282
- */
280
+ * Indicates if the content should be automatically transformed to an HTML node.
281
+ * Default: true
282
+ */
283
283
  html?: boolean;
284
284
  /**
285
- * Indicates if the content should be automatically transformed to an insertion node.
286
- * Default: true
287
- */
285
+ * Indicates if the content should be automatically transformed to an insertion node.
286
+ * Default: true
287
+ */
288
288
  insertion?: boolean;
289
289
  };
290
290
  /**
291
- * Common properties shared by all Dictionary variants.
292
- */
291
+ * Common properties shared by all Dictionary variants.
292
+ */
293
293
  type DictionaryBase = {
294
294
  /**
295
- * _Auto generated by the intlayer, do not modify it_
296
- *
297
- * The schema of the dictionary, used for JSON validation
298
- */
295
+ * _Auto generated by the intlayer, do not modify it_
296
+ *
297
+ * The schema of the dictionary, used for JSON validation
298
+ */
299
299
  $schema?: "https://intlayer.org/schema.json";
300
300
  /**
301
- * _Auto generated by the intlayer, do not modify it_
302
- *
303
- * For remote dictionaries, the id is the id of the dictionary in the remote server
304
- */
301
+ * _Auto generated by the intlayer, do not modify it_
302
+ *
303
+ * For remote dictionaries, the id is the id of the dictionary in the remote server
304
+ */
305
305
  id?: DictionaryId;
306
306
  /**
307
- * _Auto generated by the intlayer, do not modify it_
308
- *
309
- * For remote dictionaries, the projectIds is the ids of the projects that can use this dictionary
310
- * A remote dictionary can be shared between multiple projects
311
- */
307
+ * _Auto generated by the intlayer, do not modify it_
308
+ *
309
+ * For remote dictionaries, the projectIds is the ids of the projects that can use this dictionary
310
+ * A remote dictionary can be shared between multiple projects
311
+ */
312
312
  projectIds?: string[];
313
313
  /**
314
- * _Auto generated by the intlayer, do not modify it_
315
- *
316
- * Unique Identifier for the dictionaries. Auto generated by the intlayer, it helps to identify the dictionary and know if it is a local or remote dictionary, and his location.
317
- */
314
+ * _Auto generated by the intlayer, do not modify it_
315
+ *
316
+ * Unique Identifier for the dictionaries. Auto generated by the intlayer, it helps to identify the dictionary and know if it is a local or remote dictionary, and his location.
317
+ */
318
318
  localId?: LocalDictionaryId;
319
319
  /**
320
- * _Auto generated by the intlayer, do not modify it_
321
- *
322
- * For merged dictionaries, the localIds is the ids of the dictionaries that are merged
323
- */
320
+ * _Auto generated by the intlayer, do not modify it_
321
+ *
322
+ * For merged dictionaries, the localIds is the ids of the dictionaries that are merged
323
+ */
324
324
  localIds?: LocalDictionaryId[];
325
325
  /**
326
- * The formatter to use for the dictionary.
327
- *
328
- * Default: 'intlayer'
329
- *
330
- * The formatter to use for the dictionary content.
331
- */
326
+ * The formatter to use for the dictionary.
327
+ *
328
+ * Default: 'intlayer'
329
+ *
330
+ * The formatter to use for the dictionary content.
331
+ */
332
332
  format?: DictionaryFormat;
333
333
  /**
334
- * The key of the dictionary. If multiple dictionaries have the same key, intlayer will merge them.
335
- *
336
- * As convention, use '-' to separate the words in the key.
337
- *
338
- * Example:
339
- * ```json
340
- * {
341
- * "key": "about-page-meta",
342
- * "content": { ... }
343
- * }
344
- * ```
345
- */
334
+ * The key of the dictionary. If multiple dictionaries have the same key, intlayer will merge them.
335
+ *
336
+ * As convention, use '-' to separate the words in the key.
337
+ *
338
+ * Example:
339
+ * ```json
340
+ * {
341
+ * "key": "about-page-meta",
342
+ * "content": { ... }
343
+ * }
344
+ * ```
345
+ */
346
346
  key: DictionaryKey;
347
347
  /**
348
- * The title of the dictionary. Helps to identify the dictionary in the editor, and the CMS.
349
- *
350
- * Example:
351
- * ```json
352
- * {
353
- * "key": "about-page-meta",
354
- * "title": "About Page",
355
- * "content": { ... }
356
- * }
357
- * ```
358
- */
348
+ * The title of the dictionary. Helps to identify the dictionary in the editor, and the CMS.
349
+ *
350
+ * Example:
351
+ * ```json
352
+ * {
353
+ * "key": "about-page-meta",
354
+ * "title": "About Page",
355
+ * "content": { ... }
356
+ * }
357
+ * ```
358
+ */
359
359
  title?: string;
360
360
  /**
361
- * The description of the dictionary. Helps to understand the purpose of the dictionary in the editor, and the CMS.
362
- * The description is also used as context for translations generation.
363
- *
364
- * Example:
365
- * ```ts
366
- * {
367
- * "key": "about-page-meta",
368
- * "description":[
369
- * "This dictionary is manage the metadata of the About Page",
370
- * "Consider good practices for SEO:",
371
- * "- The title should be between 50 and 60 characters",
372
- * "- The description should be between 150 and 160 characters",
373
- * ].join('\n'),
374
- * "content": { ... }
375
- * }
376
- * ```
377
- */
361
+ * The description of the dictionary. Helps to understand the purpose of the dictionary in the editor, and the CMS.
362
+ * The description is also used as context for translations generation.
363
+ *
364
+ * Example:
365
+ * ```ts
366
+ * {
367
+ * "key": "about-page-meta",
368
+ * "description":[
369
+ * "This dictionary is manage the metadata of the About Page",
370
+ * "Consider good practices for SEO:",
371
+ * "- The title should be between 50 and 60 characters",
372
+ * "- The description should be between 150 and 160 characters",
373
+ * ].join('\n'),
374
+ * "content": { ... }
375
+ * }
376
+ * ```
377
+ */
378
378
  description?: string;
379
379
  /**
380
- * _Auto generated by the intlayer, do not modify it_
381
- *
382
- * The available versions of the remote dictionary. Helps to know the versions of the dictionary that are available.
383
- */
380
+ * _Auto generated by the intlayer, do not modify it_
381
+ *
382
+ * The available versions of the remote dictionary. Helps to know the versions of the dictionary that are available.
383
+ */
384
384
  versions?: string[];
385
385
  /**
386
- * _Managable on the CMS, do not modify it locally_
387
- *
388
- * The version of the remote dictionary. Helps to know the version of the dictionary that is currently used.
389
- */
386
+ * _Managable on the CMS, do not modify it locally_
387
+ *
388
+ * The version of the remote dictionary. Helps to know the version of the dictionary that is currently used.
389
+ */
390
390
  version?: string;
391
391
  /**
392
- * _Auto generated by the intlayer, do not modify it_
393
- *
394
- * The file path of the local dictionary. Helps to know from what .content file the dictionary has been generated.
395
- */
392
+ * _Auto generated by the intlayer, do not modify it_
393
+ *
394
+ * The file path of the local dictionary. Helps to know from what .content file the dictionary has been generated.
395
+ */
396
396
  filePath?: string;
397
397
  /**
398
- * Helps to categorize the dictionaries. The tags can provide more context and instructions for the dictionary.
399
- *
400
- * Example:
401
- * ```json
402
- * {
403
- * "key": "about-page-meta",
404
- * "tags": ["metadata","about-page"]
405
- * }
406
- * ```
407
- */
398
+ * Helps to categorize the dictionaries. The tags can provide more context and instructions for the dictionary.
399
+ *
400
+ * Example:
401
+ * ```json
402
+ * {
403
+ * "key": "about-page-meta",
404
+ * "tags": ["metadata","about-page"]
405
+ * }
406
+ * ```
407
+ */
408
408
  tags?: string[];
409
409
  /**
410
- * Collection item index (1-based) of this dictionary inside the collection
411
- * identified by `key`.
412
- *
413
- * Sibling dictionaries sharing the same key but different `item` values form
414
- * an ordered collection:
415
- *
416
- * ```ts
417
- * // faq.1.content.ts → { key: 'faq', item: 1, content: { ... } }
418
- * // faq.2.content.ts → { key: 'faq', item: 2, content: { ... } }
419
- *
420
- * const allFaqs = useIntlayer('faq'); // → every item, ordered
421
- * const faq2 = useIntlayer('faq', { item: 2 }); // → single item
422
- * ```
423
- *
424
- * A sibling dictionary without any qualifier acts as shared base content
425
- * merged into every item as fallback.
426
- */
410
+ * Collection item index (1-based) of this dictionary inside the collection
411
+ * identified by `key`.
412
+ *
413
+ * Sibling dictionaries sharing the same key but different `item` values form
414
+ * an ordered collection:
415
+ *
416
+ * ```ts
417
+ * // faq.1.content.ts → { key: 'faq', item: 1, content: { ... } }
418
+ * // faq.2.content.ts → { key: 'faq', item: 2, content: { ... } }
419
+ *
420
+ * const allFaqs = useIntlayer('faq'); // → every item, ordered
421
+ * const faq2 = useIntlayer('faq', { item: 2 }); // → single item
422
+ * ```
423
+ *
424
+ * A sibling dictionary without any qualifier acts as shared base content
425
+ * merged into every item as fallback.
426
+ */
427
427
  item?: number;
428
428
  /**
429
- * Variant of this dictionary inside the variant set identified by `key`.
430
- *
431
- * A variant can be declared in two equivalent forms:
432
- *
433
- * - **A string** — a single named alternative (A/B testing, seasonal banners,
434
- * feature flags…). Omitting `variant` (or using `'default'`) marks the
435
- * fallback variant.
436
- *
437
- * ```ts
438
- * // hero.content.ts → { key: 'hero-banner', variant: 'default', content: { ... } }
439
- * // hero.bf.content.ts → { key: 'hero-banner', variant: 'black-friday', content: { ... } }
440
- *
441
- * const hero = useIntlayer('hero-banner'); // → 'default' variant
442
- * const heroBf = useIntlayer('hero-banner', { variant: 'black-friday' }); // → named variant
443
- * ```
444
- *
445
- * - **An object** — a structured discriminator (CMS records, user-specific
446
- * copy, any content keyed by a set of fields). The whole object is the
447
- * identity: the selector must provide an equal object to resolve the entry.
448
- *
449
- * ```ts
450
- * // product.abc.content.ts → { key: 'product', variant: { id: 'abc', userId: '123' }, content: { ... } }
451
- *
452
- * const product = useIntlayer('product', { variant: { id: 'abc', userId: '123' } });
453
- * ```
454
- *
455
- * - **An array** of the above — registers the same content under every
456
- * listed variant id (the declaration fans out into one entry per id).
457
- * Selecting any of the ids resolves this content:
458
- *
459
- * ```ts
460
- * // hero.sales.content.ts → { key: 'hero-banner', variant: ['black-friday', 'cyber-monday'], content: { ... } }
461
- *
462
- * const heroBf = useIntlayer('hero-banner', { variant: 'black-friday' }); // → this content
463
- * const heroCm = useIntlayer('hero-banner', { variant: 'cyber-monday' }); // → same content
464
- * ```
465
- *
466
- * Sibling dictionaries sharing the same key but different `variant` values
467
- * form the variant set. A sibling without any qualifier acts as shared base
468
- * content merged into every variant as fallback.
469
- */
429
+ * Variant of this dictionary inside the variant set identified by `key`.
430
+ *
431
+ * A variant can be declared in two equivalent forms:
432
+ *
433
+ * - **A string** — a single named alternative (A/B testing, seasonal banners,
434
+ * feature flags…). Omitting `variant` (or using `'default'`) marks the
435
+ * fallback variant.
436
+ *
437
+ * ```ts
438
+ * // hero.content.ts → { key: 'hero-banner', variant: 'default', content: { ... } }
439
+ * // hero.bf.content.ts → { key: 'hero-banner', variant: 'black-friday', content: { ... } }
440
+ *
441
+ * const hero = useIntlayer('hero-banner'); // → 'default' variant
442
+ * const heroBf = useIntlayer('hero-banner', { variant: 'black-friday' }); // → named variant
443
+ * ```
444
+ *
445
+ * - **An object** — a structured discriminator (CMS records, user-specific
446
+ * copy, any content keyed by a set of fields). The whole object is the
447
+ * identity: the selector must provide an equal object to resolve the entry.
448
+ *
449
+ * ```ts
450
+ * // product.abc.content.ts → { key: 'product', variant: { id: 'abc', userId: '123' }, content: { ... } }
451
+ *
452
+ * const product = useIntlayer('product', { variant: { id: 'abc', userId: '123' } });
453
+ * ```
454
+ *
455
+ * - **An array** of the above — registers the same content under every
456
+ * listed variant id (the declaration fans out into one entry per id).
457
+ * Selecting any of the ids resolves this content:
458
+ *
459
+ * ```ts
460
+ * // hero.sales.content.ts → { key: 'hero-banner', variant: ['black-friday', 'cyber-monday'], content: { ... } }
461
+ *
462
+ * const heroBf = useIntlayer('hero-banner', { variant: 'black-friday' }); // → this content
463
+ * const heroCm = useIntlayer('hero-banner', { variant: 'cyber-monday' }); // → same content
464
+ * ```
465
+ *
466
+ * Sibling dictionaries sharing the same key but different `variant` values
467
+ * form the variant set. A sibling without any qualifier acts as shared base
468
+ * content merged into every variant as fallback.
469
+ */
470
470
  variant?: DictionaryVariantValue | DictionaryVariantValue[];
471
471
  /**
472
- * Transform the dictionary in a per-locale dictionary.
473
- * Each field declared in a per-locale dictionary will be transformed in a translation node.
474
- * If missing, the dictionary will be treated as a multilingual dictionary.
475
- * If declared, do not use translation nodes in the content.
476
- *
477
- * Example:
478
- * ```json
479
- * {
480
- * "key": "about-page",
481
- * "locale": "en",
482
- * "content": {
483
- * "multilingualContent": "English content"
484
- * }
485
- * }
486
- * ```
487
- */
472
+ * Transform the dictionary in a per-locale dictionary.
473
+ * Each field declared in a per-locale dictionary will be transformed in a translation node.
474
+ * If missing, the dictionary will be treated as a multilingual dictionary.
475
+ * If declared, do not use translation nodes in the content.
476
+ *
477
+ * Example:
478
+ * ```json
479
+ * {
480
+ * "key": "about-page",
481
+ * "locale": "en",
482
+ * "content": {
483
+ * "multilingualContent": "English content"
484
+ * }
485
+ * }
486
+ * ```
487
+ */
488
488
  locale?: LocalesValues;
489
489
  /**
490
- * Indicators if the content of the dictionary should be automatically transformed.
491
- * If true, the content will be transformed to the corresponding node type.
492
- * - Markdown: `### Title` -> `md('### Title')`
493
- * - HTML: `<div>Title</div>` -> `html('<div>Title</div>')`
494
- * - Insertion: `Hello {{name}}` -> `insert('Hello {{name}}')`
495
- *
496
- * If an object is provided, you can specify which transformations should be enabled.
497
- *
498
- * Default: false
499
- */
490
+ * Indicators if the content of the dictionary should be automatically transformed.
491
+ * If true, the content will be transformed to the corresponding node type.
492
+ * - Markdown: `### Title` -> `md('### Title')`
493
+ * - HTML: `<div>Title</div>` -> `html('<div>Title</div>')`
494
+ * - Insertion: `Hello {{name}}` -> `insert('Hello {{name}}')`
495
+ *
496
+ * If an object is provided, you can specify which transformations should be enabled.
497
+ *
498
+ * Default: false
499
+ */
500
500
  contentAutoTransformation?: ContentAutoTransformation;
501
501
  /**
502
- * Indicate how the dictionary should be filled using AI.
503
- *
504
- * Default: `true`
505
- *
506
- * - If `true`, will consider the `compiler.output` field.
507
- * - If `false`, will skip the fill process.
508
- *
509
- * - `./` paths are resolved relative to the component directory.
510
- * - `/` paths are resolved relative to the project root (`baseDir`).
511
- *
512
- * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.
513
- *
514
- * Example:
515
- * ```ts
516
- * {
517
- * // Create Multilingual .content.ts files close to the component
518
- * fill: ({ fileName, extension }) => `./${fileName}${extension}`,
519
- *
520
- * // fill: './{{fileName}}{{extension}}', // Equivalent using template string
521
- * }
522
- * ```
523
- *
524
- * ```ts
525
- * {
526
- * // Create centralize per-locale JSON at the root of the project
527
- * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,
528
- *
529
- * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string
530
- * }
531
- * ```
532
- *
533
- * ```ts
534
- * {
535
- * // Create custom output based on the locale
536
- * fill: {
537
- * en: ({ key }) => `/locales/en/${key}.content.json`,
538
- * fr: '/locales/fr/{{key}}.content.json',
539
- * es: false,
540
- * de: true,
541
- * },
542
- * }
543
- * ```
544
- *
545
- *
546
- * Variable list:
547
- * - `fileName`: The name of the file.
548
- * - `key`: The key of the content.
549
- * - `locale`: The locale of the content.
550
- * - `extension`: The extension of the file.
551
- * - `componentFileName`: The name of the component file.
552
- * - `componentExtension`: The extension of the component file.
553
- * - `format`: The format of the dictionary.
554
- * - `componentFormat`: The format of the component dictionary.
555
- * - `componentDirPath`: The directory path of the component.
556
- */
502
+ * Indicate how the dictionary should be filled using AI.
503
+ *
504
+ * Default: `true`
505
+ *
506
+ * - If `true`, will consider the `compiler.output` field.
507
+ * - If `false`, will skip the fill process.
508
+ *
509
+ * - `./` paths are resolved relative to the component directory.
510
+ * - `/` paths are resolved relative to the project root (`baseDir`).
511
+ *
512
+ * - If includes `{{locale}}` variable in the path, will trigger the generation of separate dictionaries per locale.
513
+ *
514
+ * Example:
515
+ * ```ts
516
+ * {
517
+ * // Create Multilingual .content.ts files close to the component
518
+ * fill: ({ fileName, extension }) => `./${fileName}${extension}`,
519
+ *
520
+ * // fill: './{{fileName}}{{extension}}', // Equivalent using template string
521
+ * }
522
+ * ```
523
+ *
524
+ * ```ts
525
+ * {
526
+ * // Create centralize per-locale JSON at the root of the project
527
+ * fill: ({ key, locale }) => `/locales/${locale}/${key}.content.json`,
528
+ *
529
+ * // fill: '/locales/{{locale}}/{{key}}.content.json', // Equivalent using template string
530
+ * }
531
+ * ```
532
+ *
533
+ * ```ts
534
+ * {
535
+ * // Create custom output based on the locale
536
+ * fill: {
537
+ * en: ({ key }) => `/locales/en/${key}.content.json`,
538
+ * fr: '/locales/fr/{{key}}.content.json',
539
+ * es: false,
540
+ * de: true,
541
+ * },
542
+ * }
543
+ * ```
544
+ *
545
+ *
546
+ * Variable list:
547
+ * - `fileName`: The name of the file.
548
+ * - `key`: The key of the content.
549
+ * - `locale`: The locale of the content.
550
+ * - `extension`: The extension of the file.
551
+ * - `componentFileName`: The name of the component file.
552
+ * - `componentExtension`: The extension of the component file.
553
+ * - `format`: The format of the dictionary.
554
+ * - `componentFormat`: The format of the component dictionary.
555
+ * - `componentDirPath`: The directory path of the component.
556
+ */
557
557
  fill?: Fill;
558
558
  /**
559
- * _Auto generated by the intlayer, do not modify it_
560
- *
561
- * Indicates if the dictionary has been auto filled.
562
- * In the case of conflicts, base dictionaryed will override auto filled dictionary.
563
- */
559
+ * _Auto generated by the intlayer, do not modify it_
560
+ *
561
+ * Indicates if the dictionary has been auto filled.
562
+ * In the case of conflicts, base dictionaryed will override auto filled dictionary.
563
+ */
564
564
  filled?: true;
565
565
  /**
566
- * Indicates the priority of the dictionary.
567
- * In the case of conflicts, the dictionary with the highest priority will override the other dictionaries.
568
- */
566
+ * Indicates the priority of the dictionary.
567
+ * In the case of conflicts, the dictionary with the highest priority will override the other dictionaries.
568
+ */
569
569
  priority?: number;
570
570
  /**
571
- * Indicates the mode of import to use for the dictionary.
572
- *
573
- * Available modes:
574
- * - "static": The dictionaries are imported statically.
575
- * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.
576
- * - "dynamic": The dictionaries are imported dynamically in a synchronous component using the suspense API.
577
- * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
578
- * - "live": The dictionaries are imported dynamically using the live sync API.
579
- * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
580
- * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as "dynamic" mode.
581
- *
582
- * Default: "static"
583
- */
571
+ * Indicates the mode of import to use for the dictionary.
572
+ *
573
+ * Available modes:
574
+ * - "static": The dictionaries are imported statically.
575
+ * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionary`.
576
+ * - "dynamic": The dictionaries are imported dynamically in a synchronous component using the suspense API.
577
+ * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
578
+ * - "live": The dictionaries are imported dynamically using the live sync API.
579
+ * In that case, Intlayer will replace all calls to `useIntlayer` with `useDictionaryDynamic`.
580
+ * Live mode will use the live sync API to fetch the dictionaries. If the API call fails, the dictionaries will be imported dynamically as "dynamic" mode.
581
+ *
582
+ * Default: "static"
583
+ */
584
584
  importMode?: ImportMode;
585
585
  /**
586
- * Indicates the location of the dictionary and controls how it synchronizes with the CMS.
587
- *
588
- * - 'hybrid': The dictionary is managed locally and remotely. Once pushed on the CMS, it will be synchronized from the local one. The local dictionary will be pulled from the CMS.
589
- * - 'remote': The dictionary is managed remotely only. Once pushed on the CMS, it will be detached from the local one. At content load time, the remote dictionary will be pulled from the CMS. A '.content' file with remote location will be ignored.
590
- * - 'local': The dictionary is managed locally. It will not be pushed to the remote CMS.
591
- * - 'plugin' (or any custom string): The dictionary is managed by a plugin, or a custom source. When you will try to push it, the system will ask an action to the user.
592
- */
586
+ * Indicates the location of the dictionary and controls how it synchronizes with the CMS.
587
+ *
588
+ * - 'hybrid': The dictionary is managed locally and remotely. Once pushed on the CMS, it will be synchronized from the local one. The local dictionary will be pulled from the CMS.
589
+ * - 'remote': The dictionary is managed remotely only. Once pushed on the CMS, it will be detached from the local one. At content load time, the remote dictionary will be pulled from the CMS. A '.content' file with remote location will be ignored.
590
+ * - 'local': The dictionary is managed locally. It will not be pushed to the remote CMS.
591
+ * - 'plugin' (or any custom string): The dictionary is managed by a plugin, or a custom source. When you will try to push it, the system will ask an action to the user.
592
+ */
593
593
  location?: DictionaryLocation;
594
594
  };
595
595
  /**
596
- * Strict Schema Branch:
597
- * If a schema is provided, it MUST be one of the SchemaKeys.
598
- */
596
+ * Strict Schema Branch:
597
+ * If a schema is provided, it MUST be one of the SchemaKeys.
598
+ */
599
599
  type DictionaryWithSchema<ContentType, FetchableNode, K extends SchemaKeys = SchemaKeys> = K extends any ? {
600
600
  schema: K;
601
601
  content: ContentType extends undefined ? ReplaceContentValue<Schema<K>, FetchableNode> | Schema<K> : ReplaceContentValue<ContentType & Schema<K>, FetchableNode> | (ContentType & Schema<K>);
602
602
  } : never;
603
603
  /**
604
- * Strict Discrimination Branch
605
- */
604
+ * Strict Discrimination Branch
605
+ */
606
606
  type DictionaryWithoutSchema<ContentType, FetchableNode> = {
607
607
  schema?: never;
608
608
  content: ContentType extends undefined ? any : ReplaceContentValue<ContentType, FetchableNode> | ContentType;
609
609
  };
610
610
  /**
611
- * The Final Dictionary Type
612
- */
611
+ * The Final Dictionary Type
612
+ */
613
613
  type Dictionary<ContentType = undefined, SchemaKey extends SchemaKeys | undefined = undefined, FetchableNode = false> = DictionaryBase & (SchemaKey extends SchemaKeys ? DictionaryWithSchema<ContentType, FetchableNode, SchemaKey> : undefined extends SchemaKey ? DictionaryWithoutSchema<ContentType, FetchableNode> | DictionaryWithSchema<ContentType, FetchableNode> : never);
614
614
  type GetSubPath<T, P> = P extends `${infer K}.${infer Rest}` ? K extends keyof T ? GetSubPath<T[K], Rest> : never : P extends keyof T ? T[P] : T;
615
615
  //#endregion