@datocms/cma-client 5.1.5 → 5.1.6
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/dist/cjs/fieldTypes/gallery.js +0 -2
- package/dist/cjs/fieldTypes/gallery.js.map +1 -1
- package/dist/cjs/fieldTypes/links.js +0 -2
- package/dist/cjs/fieldTypes/links.js.map +1 -1
- package/dist/cjs/fieldTypes/rich_text.js +0 -4
- package/dist/cjs/fieldTypes/rich_text.js.map +1 -1
- package/dist/cjs/generated/Client.js +1 -1
- package/dist/cjs/generated/resources/Item.js +2 -2
- package/dist/cjs/generated/resources/Item.js.map +1 -1
- package/dist/cjs/utilities/fieldValue.js +14 -9
- package/dist/cjs/utilities/fieldValue.js.map +1 -1
- package/dist/cjs/utilities/schemaRepository.js +64 -0
- package/dist/cjs/utilities/schemaRepository.js.map +1 -1
- package/dist/esm/fieldTypes/gallery.js +0 -2
- package/dist/esm/fieldTypes/gallery.js.map +1 -1
- package/dist/esm/fieldTypes/links.d.ts +1 -1
- package/dist/esm/fieldTypes/links.js +0 -2
- package/dist/esm/fieldTypes/links.js.map +1 -1
- package/dist/esm/fieldTypes/rich_text.js +0 -4
- package/dist/esm/fieldTypes/rich_text.js.map +1 -1
- package/dist/esm/generated/ApiTypes.d.ts +743 -5
- package/dist/esm/generated/Client.js +1 -1
- package/dist/esm/generated/RawApiTypes.d.ts +743 -5
- package/dist/esm/generated/resources/Item.js +2 -2
- package/dist/esm/generated/resources/Item.js.map +1 -1
- package/dist/esm/utilities/fieldValue.d.ts +18 -19
- package/dist/esm/utilities/fieldValue.js +14 -9
- package/dist/esm/utilities/fieldValue.js.map +1 -1
- package/dist/esm/utilities/itemDefinition.d.ts +27 -14
- package/dist/esm/utilities/schemaRepository.d.ts +64 -0
- package/dist/esm/utilities/schemaRepository.js +64 -0
- package/dist/esm/utilities/schemaRepository.js.map +1 -1
- package/dist/types/fieldTypes/links.d.ts +1 -1
- package/dist/types/generated/ApiTypes.d.ts +743 -5
- package/dist/types/generated/RawApiTypes.d.ts +743 -5
- package/dist/types/utilities/fieldValue.d.ts +18 -19
- package/dist/types/utilities/itemDefinition.d.ts +27 -14
- package/dist/types/utilities/schemaRepository.d.ts +64 -0
- package/package.json +4 -4
- package/src/fieldTypes/gallery.ts +0 -1
- package/src/fieldTypes/links.ts +1 -2
- package/src/fieldTypes/rich_text.ts +0 -4
- package/src/generated/ApiTypes.ts +743 -5
- package/src/generated/Client.ts +1 -1
- package/src/generated/RawApiTypes.ts +743 -5
- package/src/generated/resources/Item.ts +2 -2
- package/src/utilities/fieldValue.ts +96 -79
- package/src/utilities/itemDefinition.ts +99 -72
- package/src/utilities/schemaRepository.ts +64 -0
|
@@ -702,7 +702,7 @@ export default class Item extends BaseResource {
|
|
|
702
702
|
.request({
|
|
703
703
|
method: 'PUT',
|
|
704
704
|
url: `/items/${itemId}/publish`,
|
|
705
|
-
body: Utils.serializeRawRequestBodyWithItems(body),
|
|
705
|
+
body: body ? Utils.serializeRawRequestBodyWithItems(body) : undefined,
|
|
706
706
|
queryParams,
|
|
707
707
|
})
|
|
708
708
|
.then<
|
|
@@ -765,7 +765,7 @@ export default class Item extends BaseResource {
|
|
|
765
765
|
.request({
|
|
766
766
|
method: 'PUT',
|
|
767
767
|
url: `/items/${itemId}/unpublish`,
|
|
768
|
-
body: Utils.serializeRawRequestBodyWithItems(body),
|
|
768
|
+
body: body ? Utils.serializeRawRequestBodyWithItems(body) : undefined,
|
|
769
769
|
queryParams,
|
|
770
770
|
})
|
|
771
771
|
.then<
|
|
@@ -27,7 +27,10 @@ import type * as RawApiTypes from '../generated/RawApiTypes';
|
|
|
27
27
|
* for various locales structured as an object, such as
|
|
28
28
|
* `{ "en": "Hello", "it": "Ciao" }`
|
|
29
29
|
*/
|
|
30
|
-
export type LocalizedFieldValue<
|
|
30
|
+
export type LocalizedFieldValue<
|
|
31
|
+
T = unknown,
|
|
32
|
+
L extends string = string,
|
|
33
|
+
> = Record<L, T>;
|
|
31
34
|
|
|
32
35
|
/**
|
|
33
36
|
* Determines whether a DatoCMS field is localized or not.
|
|
@@ -52,13 +55,11 @@ export function isLocalized(
|
|
|
52
55
|
*
|
|
53
56
|
* This uniform structure allows the same processing logic to work with both field types.
|
|
54
57
|
*/
|
|
55
|
-
export type FieldValueEntry = {
|
|
56
|
-
locale:
|
|
57
|
-
value:
|
|
58
|
+
export type FieldValueEntry<T = unknown, L extends string = string> = {
|
|
59
|
+
locale: L | undefined;
|
|
60
|
+
value: T;
|
|
58
61
|
};
|
|
59
62
|
|
|
60
|
-
export type PossiblyLocalizedEntry = FieldValueEntry;
|
|
61
|
-
|
|
62
63
|
/**
|
|
63
64
|
* Converts a field value (localized or non-localized) into a uniform array of entries.
|
|
64
65
|
*
|
|
@@ -69,43 +70,48 @@ export type PossiblyLocalizedEntry = FieldValueEntry;
|
|
|
69
70
|
* @param value - The field value to convert (either a localized object or direct value)
|
|
70
71
|
* @returns Array of entries where each entry contains a locale (string for localized, undefined for non-localized) and the corresponding value
|
|
71
72
|
*/
|
|
72
|
-
export function fieldValueToEntries(
|
|
73
|
+
export function fieldValueToEntries<T = unknown, L extends string = string>(
|
|
73
74
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
74
|
-
value:
|
|
75
|
-
) {
|
|
75
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
76
|
+
): FieldValueEntry<T, L>[] {
|
|
76
77
|
if (isLocalized(field)) {
|
|
77
|
-
const localizedValue = value as LocalizedFieldValue
|
|
78
|
+
const localizedValue = value as LocalizedFieldValue<T, L>;
|
|
78
79
|
|
|
79
|
-
return Object.entries(localizedValue).map
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
return Object.entries(localizedValue).map(([locale, value]) => ({
|
|
81
|
+
locale: locale as L,
|
|
82
|
+
value: value as T,
|
|
83
|
+
}));
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
return [{ locale: undefined, value }];
|
|
86
|
+
return [{ locale: undefined, value: value as T }];
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
/**
|
|
88
90
|
* Converts an array of possibly localized entries back into the appropriate field value format.
|
|
89
91
|
*
|
|
90
|
-
* This function is the inverse of `
|
|
92
|
+
* This function is the inverse of `fieldValueToEntries`. It takes a uniform
|
|
91
93
|
* array of entries and converts them back to either a localized object or a direct value,
|
|
92
94
|
* depending on the field's localization setting.
|
|
93
95
|
*
|
|
94
96
|
* @param field - The DatoCMS field definition that determines the output format
|
|
95
|
-
* @param
|
|
97
|
+
* @param entries - Array of entries to convert back to field value format
|
|
96
98
|
* @returns Either a localized object (for localized fields) or the direct value (for non-localized fields)
|
|
97
99
|
*/
|
|
98
|
-
export function entriesToFieldValue(
|
|
100
|
+
export function entriesToFieldValue<T = unknown, L extends string = string>(
|
|
99
101
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
100
|
-
|
|
101
|
-
) {
|
|
102
|
+
entries: FieldValueEntry<T, L>[],
|
|
103
|
+
): T | LocalizedFieldValue<T, L> {
|
|
102
104
|
if (isLocalized(field)) {
|
|
103
105
|
return Object.fromEntries(
|
|
104
|
-
|
|
105
|
-
)
|
|
106
|
+
entries.map(({ locale, value }) => [locale, value]),
|
|
107
|
+
) as LocalizedFieldValue<T, L>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (entries.length === 0) {
|
|
111
|
+
throw new Error('There must be at least one entry!');
|
|
106
112
|
}
|
|
107
113
|
|
|
108
|
-
return
|
|
114
|
+
return entries[0]!.value;
|
|
109
115
|
}
|
|
110
116
|
|
|
111
117
|
/**
|
|
@@ -119,17 +125,21 @@ export function entriesToFieldValue(
|
|
|
119
125
|
* @param mapFn - The function to apply to each locale value or the direct value
|
|
120
126
|
* @returns The mapped value with the same structure as the input
|
|
121
127
|
*/
|
|
122
|
-
export function mapFieldValue<
|
|
128
|
+
export function mapFieldValue<
|
|
129
|
+
TInput = unknown,
|
|
130
|
+
TOutput = unknown,
|
|
131
|
+
L extends string = string,
|
|
132
|
+
>(
|
|
123
133
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
124
|
-
value:
|
|
125
|
-
mapFn: (locale:
|
|
126
|
-
) {
|
|
127
|
-
const entries = fieldValueToEntries(field, value);
|
|
134
|
+
value: TInput | LocalizedFieldValue<TInput, L>,
|
|
135
|
+
mapFn: (locale: L | undefined, localeValue: TInput) => TOutput,
|
|
136
|
+
): TOutput | LocalizedFieldValue<TOutput, L> {
|
|
137
|
+
const entries = fieldValueToEntries<TInput, L>(field, value);
|
|
128
138
|
const mappedEntries = entries.map(({ locale, value }) => ({
|
|
129
139
|
locale,
|
|
130
140
|
value: mapFn(locale, value),
|
|
131
141
|
}));
|
|
132
|
-
return entriesToFieldValue(field, mappedEntries);
|
|
142
|
+
return entriesToFieldValue<TOutput, L>(field, mappedEntries);
|
|
133
143
|
}
|
|
134
144
|
|
|
135
145
|
/**
|
|
@@ -143,19 +153,23 @@ export function mapFieldValue<T>(
|
|
|
143
153
|
* @param mapFn - The function to apply to each locale value or the direct value
|
|
144
154
|
* @returns The mapped value with the same structure as the input
|
|
145
155
|
*/
|
|
146
|
-
export async function mapFieldValueAsync<
|
|
156
|
+
export async function mapFieldValueAsync<
|
|
157
|
+
TInput = unknown,
|
|
158
|
+
TOutput = unknown,
|
|
159
|
+
L extends string = string,
|
|
160
|
+
>(
|
|
147
161
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
148
|
-
value:
|
|
149
|
-
mapFn: (locale:
|
|
150
|
-
) {
|
|
151
|
-
const entries = fieldValueToEntries(field, value);
|
|
162
|
+
value: TInput | LocalizedFieldValue<TInput, L>,
|
|
163
|
+
mapFn: (locale: L | undefined, localeValue: TInput) => Promise<TOutput>,
|
|
164
|
+
): Promise<TOutput | LocalizedFieldValue<TOutput, L>> {
|
|
165
|
+
const entries = fieldValueToEntries<TInput, L>(field, value);
|
|
152
166
|
const mappedEntries = await Promise.all(
|
|
153
167
|
entries.map(async ({ locale, value }) => ({
|
|
154
168
|
locale,
|
|
155
169
|
value: await mapFn(locale, value),
|
|
156
170
|
})),
|
|
157
171
|
);
|
|
158
|
-
return entriesToFieldValue(field, mappedEntries);
|
|
172
|
+
return entriesToFieldValue<TOutput, L>(field, mappedEntries);
|
|
159
173
|
}
|
|
160
174
|
|
|
161
175
|
/**
|
|
@@ -168,18 +182,18 @@ export async function mapFieldValueAsync<T>(
|
|
|
168
182
|
* @param filterFn - The function to test each locale value or the direct value
|
|
169
183
|
* @returns The filtered value with the same structure as the input
|
|
170
184
|
*/
|
|
171
|
-
export function filterFieldValue(
|
|
185
|
+
export function filterFieldValue<T = unknown, L extends string = string>(
|
|
172
186
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
173
|
-
value:
|
|
174
|
-
filterFn: (locale:
|
|
175
|
-
) {
|
|
176
|
-
const entries = fieldValueToEntries(field, value);
|
|
177
|
-
const filteredEntries = entries.filter((
|
|
178
|
-
filterFn(locale, value),
|
|
187
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
188
|
+
filterFn: (locale: L | undefined, localeValue: T) => boolean,
|
|
189
|
+
): T | LocalizedFieldValue<T, L> | undefined {
|
|
190
|
+
const entries = fieldValueToEntries<T, L>(field, value);
|
|
191
|
+
const filteredEntries = entries.filter((entry) =>
|
|
192
|
+
filterFn(entry.locale, entry.value),
|
|
179
193
|
);
|
|
180
194
|
|
|
181
195
|
if (isLocalized(field)) {
|
|
182
|
-
return entriesToFieldValue(field, filteredEntries);
|
|
196
|
+
return entriesToFieldValue<T, L>(field, filteredEntries);
|
|
183
197
|
}
|
|
184
198
|
|
|
185
199
|
return filteredEntries.length > 0 ? filteredEntries[0]?.value : undefined;
|
|
@@ -195,15 +209,15 @@ export function filterFieldValue(
|
|
|
195
209
|
* @param filterFn - The function to test each locale value or the direct value
|
|
196
210
|
* @returns The filtered value with the same structure as the input
|
|
197
211
|
*/
|
|
198
|
-
export async function filterFieldValueAsync
|
|
212
|
+
export async function filterFieldValueAsync<
|
|
213
|
+
T = unknown,
|
|
214
|
+
L extends string = string,
|
|
215
|
+
>(
|
|
199
216
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
200
|
-
value:
|
|
201
|
-
filterFn: (
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
) => Promise<boolean>,
|
|
205
|
-
) {
|
|
206
|
-
const entries = fieldValueToEntries(field, value);
|
|
217
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
218
|
+
filterFn: (locale: L | undefined, localeValue: T) => Promise<boolean>,
|
|
219
|
+
): Promise<T | LocalizedFieldValue<T, L> | undefined> {
|
|
220
|
+
const entries = fieldValueToEntries<T, L>(field, value);
|
|
207
221
|
const results = await Promise.all(
|
|
208
222
|
entries.map(async ({ locale, value }) => ({
|
|
209
223
|
locale,
|
|
@@ -217,7 +231,7 @@ export async function filterFieldValueAsync(
|
|
|
217
231
|
.map(({ locale, value }) => ({ locale, value }));
|
|
218
232
|
|
|
219
233
|
if (isLocalized(field)) {
|
|
220
|
-
return entriesToFieldValue(field, filteredEntries);
|
|
234
|
+
return entriesToFieldValue<T, L>(field, filteredEntries);
|
|
221
235
|
}
|
|
222
236
|
|
|
223
237
|
return filteredEntries.length > 0 ? filteredEntries[0]?.value : undefined;
|
|
@@ -233,12 +247,12 @@ export async function filterFieldValueAsync(
|
|
|
233
247
|
* @param testFn - The function to test each locale value or the direct value
|
|
234
248
|
* @returns true if at least one value passes the test, false otherwise
|
|
235
249
|
*/
|
|
236
|
-
export function someFieldValue(
|
|
250
|
+
export function someFieldValue<T = unknown, L extends string = string>(
|
|
237
251
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
238
|
-
value:
|
|
239
|
-
testFn: (locale:
|
|
252
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
253
|
+
testFn: (locale: L | undefined, localeValue: T) => boolean,
|
|
240
254
|
): boolean {
|
|
241
|
-
const entries = fieldValueToEntries(field, value);
|
|
255
|
+
const entries = fieldValueToEntries<T, L>(field, value);
|
|
242
256
|
return entries.some(({ locale, value }) => testFn(locale, value));
|
|
243
257
|
}
|
|
244
258
|
|
|
@@ -252,15 +266,15 @@ export function someFieldValue(
|
|
|
252
266
|
* @param testFn - The function to test each locale value or the direct value
|
|
253
267
|
* @returns true if at least one value passes the test, false otherwise
|
|
254
268
|
*/
|
|
255
|
-
export async function someFieldValueAsync
|
|
269
|
+
export async function someFieldValueAsync<
|
|
270
|
+
T = unknown,
|
|
271
|
+
L extends string = string,
|
|
272
|
+
>(
|
|
256
273
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
257
|
-
value:
|
|
258
|
-
testFn: (
|
|
259
|
-
locale: string | undefined,
|
|
260
|
-
localeValue: unknown,
|
|
261
|
-
) => Promise<boolean>,
|
|
274
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
275
|
+
testFn: (locale: L | undefined, localeValue: T) => Promise<boolean>,
|
|
262
276
|
): Promise<boolean> {
|
|
263
|
-
const entries = fieldValueToEntries(field, value);
|
|
277
|
+
const entries = fieldValueToEntries<T, L>(field, value);
|
|
264
278
|
const results = await Promise.all(
|
|
265
279
|
entries.map(({ locale, value }) => testFn(locale, value)),
|
|
266
280
|
);
|
|
@@ -277,10 +291,10 @@ export async function someFieldValueAsync(
|
|
|
277
291
|
* @param testFn - The function to test each locale value or the direct value
|
|
278
292
|
* @returns true if all values pass the test, false otherwise
|
|
279
293
|
*/
|
|
280
|
-
export function everyFieldValue(
|
|
294
|
+
export function everyFieldValue<T = unknown, L extends string = string>(
|
|
281
295
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
282
|
-
value:
|
|
283
|
-
testFn: (locale:
|
|
296
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
297
|
+
testFn: (locale: L | undefined, localeValue: T) => boolean,
|
|
284
298
|
): boolean {
|
|
285
299
|
return !someFieldValue(
|
|
286
300
|
field,
|
|
@@ -299,13 +313,13 @@ export function everyFieldValue(
|
|
|
299
313
|
* @param testFn - The function to test each locale value or the direct value
|
|
300
314
|
* @returns true if all values pass the test, false otherwise
|
|
301
315
|
*/
|
|
302
|
-
export async function everyFieldValueAsync
|
|
316
|
+
export async function everyFieldValueAsync<
|
|
317
|
+
T = unknown,
|
|
318
|
+
L extends string = string,
|
|
319
|
+
>(
|
|
303
320
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
304
|
-
value:
|
|
305
|
-
testFn: (
|
|
306
|
-
locale: string | undefined,
|
|
307
|
-
localeValue: unknown,
|
|
308
|
-
) => Promise<boolean>,
|
|
321
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
322
|
+
testFn: (locale: L | undefined, localeValue: T) => Promise<boolean>,
|
|
309
323
|
): Promise<boolean> {
|
|
310
324
|
return !(await someFieldValueAsync(
|
|
311
325
|
field,
|
|
@@ -323,12 +337,12 @@ export async function everyFieldValueAsync(
|
|
|
323
337
|
* @param value - The field value (either localized object or direct value)
|
|
324
338
|
* @param visitFn - The function to call for each locale value or the direct value
|
|
325
339
|
*/
|
|
326
|
-
export function visitFieldValue(
|
|
340
|
+
export function visitFieldValue<T = unknown, L extends string = string>(
|
|
327
341
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
328
|
-
value:
|
|
329
|
-
visitFn: (locale:
|
|
342
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
343
|
+
visitFn: (locale: L | undefined, localeValue: T) => void,
|
|
330
344
|
): void {
|
|
331
|
-
const entries = fieldValueToEntries(field, value);
|
|
345
|
+
const entries = fieldValueToEntries<T, L>(field, value);
|
|
332
346
|
for (const { locale, value } of entries) {
|
|
333
347
|
visitFn(locale, value);
|
|
334
348
|
}
|
|
@@ -343,11 +357,14 @@ export function visitFieldValue(
|
|
|
343
357
|
* @param value - The field value (either localized object or direct value)
|
|
344
358
|
* @param visitFn - The function to call for each locale value or the direct value
|
|
345
359
|
*/
|
|
346
|
-
export async function visitFieldValueAsync
|
|
360
|
+
export async function visitFieldValueAsync<
|
|
361
|
+
T = unknown,
|
|
362
|
+
L extends string = string,
|
|
363
|
+
>(
|
|
347
364
|
field: RawApiTypes.Field | ApiTypes.Field,
|
|
348
|
-
value:
|
|
349
|
-
visitFn: (locale:
|
|
365
|
+
value: T | LocalizedFieldValue<T, L>,
|
|
366
|
+
visitFn: (locale: L | undefined, localeValue: T) => Promise<void>,
|
|
350
367
|
): Promise<void> {
|
|
351
|
-
const entries = fieldValueToEntries(field, value);
|
|
368
|
+
const entries = fieldValueToEntries<T, L>(field, value);
|
|
352
369
|
await Promise.all(entries.map(({ locale, value }) => visitFn(locale, value)));
|
|
353
370
|
}
|
|
@@ -44,8 +44,8 @@ type StructuredTextFieldDefinition<
|
|
|
44
44
|
AllowedBlocks extends ItemTypeDefinition = ItemTypeDefinition,
|
|
45
45
|
AllowedInlineBlocks extends ItemTypeDefinition = ItemTypeDefinition,
|
|
46
46
|
> = BaseFieldDefinition<'structured_text'> & {
|
|
47
|
-
blocks
|
|
48
|
-
inline_blocks
|
|
47
|
+
blocks?: AllowedBlocks;
|
|
48
|
+
inline_blocks?: AllowedInlineBlocks;
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
/** Field definition union */
|
|
@@ -76,9 +76,11 @@ export type FieldDefinition =
|
|
|
76
76
|
|
|
77
77
|
/** Item type definition */
|
|
78
78
|
export type ItemTypeDefinition<
|
|
79
|
+
Settings extends { locales: string } = { locales: string },
|
|
79
80
|
ItemTypeId extends string = string,
|
|
80
81
|
FieldDefinitions extends Record<string, FieldDefinition> = {},
|
|
81
82
|
> = {
|
|
83
|
+
settings: Settings;
|
|
82
84
|
itemTypeId: ItemTypeId;
|
|
83
85
|
fields: FieldDefinitions;
|
|
84
86
|
};
|
|
@@ -118,109 +120,134 @@ type FieldTypeToValue = {
|
|
|
118
120
|
};
|
|
119
121
|
|
|
120
122
|
/** Localized wrapper */
|
|
121
|
-
type LocalizeIfNeeded<
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
type LocalizeIfNeeded<
|
|
124
|
+
T extends FieldDefinition,
|
|
125
|
+
Value,
|
|
126
|
+
Locales extends string,
|
|
127
|
+
> = T extends { localized: true } ? LocalizedFieldValue<Value, Locales> : Value;
|
|
126
128
|
|
|
127
129
|
/** Standard mapping */
|
|
128
|
-
type FieldDefinitionToFieldValue<
|
|
129
|
-
T,
|
|
130
|
-
|
|
131
|
-
>;
|
|
130
|
+
type FieldDefinitionToFieldValue<
|
|
131
|
+
T extends FieldDefinition,
|
|
132
|
+
Locales extends string,
|
|
133
|
+
> = LocalizeIfNeeded<T, FieldTypeToValue[T['type']], Locales>;
|
|
132
134
|
|
|
133
135
|
/** AsRequest mapping (block fields become generic over allowed blocks) */
|
|
134
|
-
type FieldDefinitionToFieldValueAsRequest<
|
|
135
|
-
T extends
|
|
136
|
+
type FieldDefinitionToFieldValueAsRequest<
|
|
137
|
+
T extends FieldDefinition,
|
|
138
|
+
Locales extends string,
|
|
139
|
+
> = T extends RichTextFieldDefinition<infer B>
|
|
140
|
+
? LocalizeIfNeeded<
|
|
141
|
+
T,
|
|
142
|
+
RichTextFieldValueAsRequest<
|
|
143
|
+
ItemTypeDefinitionToItemDefinitionAsRequest<B>
|
|
144
|
+
>,
|
|
145
|
+
Locales
|
|
146
|
+
>
|
|
147
|
+
: T extends SingleBlockFieldDefinition<infer B>
|
|
136
148
|
? LocalizeIfNeeded<
|
|
137
149
|
T,
|
|
138
|
-
|
|
150
|
+
SingleBlockFieldValueAsRequest<
|
|
139
151
|
ItemTypeDefinitionToItemDefinitionAsRequest<B>
|
|
140
|
-
|
|
152
|
+
>,
|
|
153
|
+
Locales
|
|
141
154
|
>
|
|
142
|
-
: T extends
|
|
155
|
+
: T extends StructuredTextFieldDefinition<infer B, infer I>
|
|
143
156
|
? LocalizeIfNeeded<
|
|
144
157
|
T,
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
158
|
+
StructuredTextFieldValueAsRequest<
|
|
159
|
+
T extends { blocks: any }
|
|
160
|
+
? ItemTypeDefinitionToItemDefinitionAsRequest<B>
|
|
161
|
+
: never,
|
|
162
|
+
T extends { inline_blocks: any }
|
|
163
|
+
? ItemTypeDefinitionToItemDefinitionAsRequest<I>
|
|
164
|
+
: never
|
|
165
|
+
>,
|
|
166
|
+
Locales
|
|
148
167
|
>
|
|
149
|
-
: T
|
|
150
|
-
? LocalizeIfNeeded<
|
|
151
|
-
T,
|
|
152
|
-
StructuredTextFieldValueAsRequest<
|
|
153
|
-
ItemTypeDefinitionToItemDefinitionAsRequest<B>,
|
|
154
|
-
ItemTypeDefinitionToItemDefinitionAsRequest<I>
|
|
155
|
-
>
|
|
156
|
-
>
|
|
157
|
-
: LocalizeIfNeeded<T, FieldTypeToValue[T['type']]>;
|
|
168
|
+
: LocalizeIfNeeded<T, FieldTypeToValue[T['type']], Locales>;
|
|
158
169
|
|
|
159
|
-
type FieldDefinitionToFieldValueWithNestedBlocks<
|
|
160
|
-
T extends
|
|
170
|
+
type FieldDefinitionToFieldValueWithNestedBlocks<
|
|
171
|
+
T extends FieldDefinition,
|
|
172
|
+
Locales extends string,
|
|
173
|
+
> = T extends RichTextFieldDefinition<infer B>
|
|
174
|
+
? LocalizeIfNeeded<
|
|
175
|
+
T,
|
|
176
|
+
RichTextFieldValueWithNestedBlocks<
|
|
177
|
+
ItemTypeDefinitionToItemDefinitionWithNestedBlocks<B>
|
|
178
|
+
>,
|
|
179
|
+
Locales
|
|
180
|
+
>
|
|
181
|
+
: T extends SingleBlockFieldDefinition<infer B>
|
|
161
182
|
? LocalizeIfNeeded<
|
|
162
183
|
T,
|
|
163
|
-
|
|
184
|
+
SingleBlockFieldValueWithNestedBlocks<
|
|
164
185
|
ItemTypeDefinitionToItemDefinitionWithNestedBlocks<B>
|
|
165
|
-
|
|
186
|
+
>,
|
|
187
|
+
Locales
|
|
166
188
|
>
|
|
167
|
-
: T extends
|
|
189
|
+
: T extends StructuredTextFieldDefinition<infer B, infer I>
|
|
168
190
|
? LocalizeIfNeeded<
|
|
169
191
|
T,
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
192
|
+
StructuredTextFieldValueWithNestedBlocks<
|
|
193
|
+
T extends { blocks: any }
|
|
194
|
+
? ItemTypeDefinitionToItemDefinitionWithNestedBlocks<B>
|
|
195
|
+
: never,
|
|
196
|
+
T extends { inline_blocks: any }
|
|
197
|
+
? ItemTypeDefinitionToItemDefinitionWithNestedBlocks<I>
|
|
198
|
+
: never
|
|
199
|
+
>,
|
|
200
|
+
Locales
|
|
173
201
|
>
|
|
174
|
-
: T
|
|
175
|
-
? LocalizeIfNeeded<
|
|
176
|
-
T,
|
|
177
|
-
StructuredTextFieldValueWithNestedBlocks<
|
|
178
|
-
ItemTypeDefinitionToItemDefinitionWithNestedBlocks<B>,
|
|
179
|
-
ItemTypeDefinitionToItemDefinitionWithNestedBlocks<I>
|
|
180
|
-
>
|
|
181
|
-
>
|
|
182
|
-
: LocalizeIfNeeded<T, FieldTypeToValue[T['type']]>;
|
|
202
|
+
: LocalizeIfNeeded<T, FieldTypeToValue[T['type']], Locales>;
|
|
183
203
|
|
|
184
204
|
/** Transformers */
|
|
185
|
-
export type ItemTypeDefinitionToItemDefinition<
|
|
186
|
-
T extends ItemTypeDefinition
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
205
|
+
export type ItemTypeDefinitionToItemDefinition<
|
|
206
|
+
T extends ItemTypeDefinition<any, any, any>,
|
|
207
|
+
> = T extends ItemTypeDefinition<infer Settings, infer ItemTypeId, infer Fields>
|
|
208
|
+
? keyof Fields extends never
|
|
209
|
+
? ItemDefinition<ItemTypeId>
|
|
210
|
+
: ItemDefinition<
|
|
211
|
+
ItemTypeId,
|
|
212
|
+
{
|
|
213
|
+
[K in keyof Fields]: Fields[K] extends FieldDefinition
|
|
214
|
+
? FieldDefinitionToFieldValue<Fields[K], Settings['locales']>
|
|
215
|
+
: never;
|
|
216
|
+
}
|
|
217
|
+
>
|
|
218
|
+
: never;
|
|
198
219
|
|
|
199
220
|
export type ItemTypeDefinitionToItemDefinitionAsRequest<
|
|
200
|
-
T extends ItemTypeDefinition,
|
|
201
|
-
> = T extends ItemTypeDefinition
|
|
202
|
-
? keyof
|
|
203
|
-
? ItemDefinition<
|
|
221
|
+
T extends ItemTypeDefinition<any, any, any>,
|
|
222
|
+
> = T extends ItemTypeDefinition<infer Settings, infer ItemTypeId, infer Fields>
|
|
223
|
+
? keyof Fields extends never
|
|
224
|
+
? ItemDefinition<ItemTypeId>
|
|
204
225
|
: ItemDefinition<
|
|
205
|
-
|
|
226
|
+
ItemTypeId,
|
|
206
227
|
Partial<{
|
|
207
|
-
[K in keyof
|
|
208
|
-
? FieldDefinitionToFieldValueAsRequest<
|
|
228
|
+
[K in keyof Fields]: Fields[K] extends FieldDefinition
|
|
229
|
+
? FieldDefinitionToFieldValueAsRequest<
|
|
230
|
+
Fields[K],
|
|
231
|
+
Settings['locales']
|
|
232
|
+
>
|
|
209
233
|
: never;
|
|
210
234
|
}>
|
|
211
235
|
>
|
|
212
236
|
: never;
|
|
213
237
|
|
|
214
238
|
export type ItemTypeDefinitionToItemDefinitionWithNestedBlocks<
|
|
215
|
-
T extends ItemTypeDefinition,
|
|
216
|
-
> = T extends ItemTypeDefinition
|
|
217
|
-
? keyof
|
|
218
|
-
? ItemDefinition<
|
|
239
|
+
T extends ItemTypeDefinition<any, any, any>,
|
|
240
|
+
> = T extends ItemTypeDefinition<infer Settings, infer ItemTypeId, infer Fields>
|
|
241
|
+
? keyof Fields extends never
|
|
242
|
+
? ItemDefinition<ItemTypeId>
|
|
219
243
|
: ItemDefinition<
|
|
220
|
-
|
|
244
|
+
ItemTypeId,
|
|
221
245
|
{
|
|
222
|
-
[K in keyof
|
|
223
|
-
? FieldDefinitionToFieldValueWithNestedBlocks<
|
|
246
|
+
[K in keyof Fields]: Fields[K] extends FieldDefinition
|
|
247
|
+
? FieldDefinitionToFieldValueWithNestedBlocks<
|
|
248
|
+
Fields[K],
|
|
249
|
+
Settings['locales']
|
|
250
|
+
>
|
|
224
251
|
: never;
|
|
225
252
|
}
|
|
226
253
|
>
|
|
@@ -21,6 +21,70 @@ interface GenericClient {
|
|
|
21
21
|
/**
|
|
22
22
|
* Repository for DatoCMS schema entities including item types, fields, and plugins.
|
|
23
23
|
* Provides caching and efficient lookup functionality for schema-related operations.
|
|
24
|
+
*
|
|
25
|
+
* ## Purpose
|
|
26
|
+
*
|
|
27
|
+
* SchemaRepository is designed to solve the performance problem of repeatedly fetching
|
|
28
|
+
* the same schema information during complex operations that traverse nested blocks,
|
|
29
|
+
* structured text, or modular content. It acts as an in-memory cache/memoization layer
|
|
30
|
+
* for schema entities to avoid redundant API calls.
|
|
31
|
+
*
|
|
32
|
+
* ## What it's for:
|
|
33
|
+
*
|
|
34
|
+
* - **Caching schema entities**: Automatically caches item types, fields, fieldsets,
|
|
35
|
+
* and plugins after the first API request, returning cached results on subsequent calls
|
|
36
|
+
* - **Complex traversal operations**: Essential when using utilities like
|
|
37
|
+
* `mapBlocksInFieldValues()` that need to repeatedly lookup block models and fields
|
|
38
|
+
* while traversing nested content structures
|
|
39
|
+
* - **Bulk operations**: Ideal for scripts that process multiple records of different
|
|
40
|
+
* types and need efficient access to schema information
|
|
41
|
+
* - **Read-heavy workflows**: Perfect for scenarios where you need to repeatedly access
|
|
42
|
+
* the same schema information without making redundant API calls
|
|
43
|
+
*
|
|
44
|
+
* ## What it's NOT for:
|
|
45
|
+
*
|
|
46
|
+
* - **Schema modification**: Do NOT use SchemaRepository if your script modifies models,
|
|
47
|
+
* fields, fieldsets, or plugins, as the cache will become stale
|
|
48
|
+
* - **Record/content operations**: This is only for schema entities, not for records,
|
|
49
|
+
* uploads, or other content
|
|
50
|
+
* - **Long-running applications**: The cache has no expiration or invalidation mechanism,
|
|
51
|
+
* so it's not suitable for applications that need fresh schema data over time
|
|
52
|
+
* - **Concurrent schema changes**: No protection against cache inconsistency if other
|
|
53
|
+
* processes modify the schema while your script runs
|
|
54
|
+
*
|
|
55
|
+
* ## Usage Pattern
|
|
56
|
+
*
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const schemaRepository = new SchemaRepository(client);
|
|
59
|
+
*
|
|
60
|
+
* // These calls will hit the API and cache the results
|
|
61
|
+
* const models = await schemaRepository.getAllModels();
|
|
62
|
+
* const blogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
|
|
63
|
+
*
|
|
64
|
+
* // These subsequent calls will return cached results (no API calls)
|
|
65
|
+
* const sameModels = await schemaRepository.getAllModels();
|
|
66
|
+
* const sameBlogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
|
|
67
|
+
*
|
|
68
|
+
* // Pass the repository to utilities that need schema information
|
|
69
|
+
* await mapBlocksInFieldValues(schemaRepository, record, (block) => {
|
|
70
|
+
* // The utility will use the cached schema data internally
|
|
71
|
+
* });
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* ## Performance Benefits
|
|
75
|
+
*
|
|
76
|
+
* Without SchemaRepository, a script processing structured text with nested blocks
|
|
77
|
+
* might make the same `client.itemTypes.list()` or `client.fields.list()` calls
|
|
78
|
+
* dozens of times. SchemaRepository ensures each unique schema request is made only once.
|
|
79
|
+
*
|
|
80
|
+
* ## Best Practices
|
|
81
|
+
*
|
|
82
|
+
* - Use SchemaRepository consistently throughout your script — if you need it for one
|
|
83
|
+
* utility call, use it for all schema operations to maximize cache efficiency
|
|
84
|
+
* - Create one instance per script execution, not per operation
|
|
85
|
+
* - Only use when you have read-only access to schema entities
|
|
86
|
+
* - Consider using optimistic locking for any record updates to handle potential
|
|
87
|
+
* version conflicts when working with cached schema information
|
|
24
88
|
*/
|
|
25
89
|
export class SchemaRepository {
|
|
26
90
|
private client: GenericClient;
|