@datocms/cma-client 5.1.12 → 5.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +284 -143
- package/dist/cjs/generated/Client.js +1 -1
- package/dist/cjs/utilities/buildBlockRecord.js.map +1 -1
- package/dist/cjs/utilities/duplicateBlockRecord.js +2 -1
- package/dist/cjs/utilities/duplicateBlockRecord.js.map +1 -1
- package/dist/esm/fieldTypes/schema.d.ts +1 -1
- package/dist/esm/fieldTypes/single_block.d.ts +1 -1
- package/dist/esm/generated/ApiTypes.d.ts +4 -0
- package/dist/esm/generated/Client.js +1 -1
- package/dist/esm/generated/RawApiTypes.d.ts +4 -0
- package/dist/esm/generated/resources/Field.d.ts +100 -100
- package/dist/esm/utilities/buildBlockRecord.d.ts +10 -2
- package/dist/esm/utilities/buildBlockRecord.js.map +1 -1
- package/dist/esm/utilities/duplicateBlockRecord.js +2 -1
- package/dist/esm/utilities/duplicateBlockRecord.js.map +1 -1
- package/dist/types/fieldTypes/schema.d.ts +1 -1
- package/dist/types/fieldTypes/single_block.d.ts +1 -1
- package/dist/types/generated/ApiTypes.d.ts +4 -0
- package/dist/types/generated/RawApiTypes.d.ts +4 -0
- package/dist/types/generated/resources/Field.d.ts +100 -100
- package/dist/types/utilities/buildBlockRecord.d.ts +10 -2
- package/package.json +4 -4
- package/src/fieldTypes/schema.ts +1 -1
- package/src/fieldTypes/single_block.ts +1 -1
- package/src/generated/ApiTypes.ts +4 -0
- package/src/generated/Client.ts +1 -1
- package/src/generated/RawApiTypes.ts +4 -0
- package/src/utilities/buildBlockRecord.ts +18 -2
- package/src/utilities/duplicateBlockRecord.ts +2 -1
package/README.md
CHANGED
|
@@ -1,20 +1,195 @@
|
|
|
1
|
-
|
|
1
|
+
# DatoCMS Content Management API Utilities
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Take a look at the full [API documentation](https://www.datocms.com/docs/content-management-api) for examples!
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Field Types
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
<a href="https://www.datocms.com/">
|
|
9
|
-
<img src="https://www.datocms.com/images/full_logo.svg" height="60">
|
|
10
|
-
</a>
|
|
11
|
-
<br /><br />
|
|
7
|
+
This library provides comprehensive TypeScript type definitions and utilities for all DatoCMS field types. Each field type includes type guards, validation functions, localization support, and editor appearance configurations.
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
### What's available
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
Every field type follows a consistent pattern providing:
|
|
16
12
|
|
|
17
|
-
|
|
13
|
+
- **Field value types**: TypeScript definitions for the field's data structure
|
|
14
|
+
- **Type guards**: Functions to validate field values at runtime
|
|
15
|
+
- **Localization support**: Utilities for handling localized field variants
|
|
16
|
+
- **Validation types**: Supported validators for the field type
|
|
17
|
+
- **Appearance configuration**: Editor types and their configuration options
|
|
18
|
+
|
|
19
|
+
**Example: `lat_lon` Field Type**
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { LatLonFieldValue, isLatLonFieldValue, isLocalizedLatLonFieldValue } from '@datocms/cma-client';
|
|
23
|
+
import type { LatLonFieldValidators, LatLonFieldAppearance } from '@datocms/cma-client';
|
|
24
|
+
|
|
25
|
+
// Field value type - can be boolean or null
|
|
26
|
+
const value: LatLonFieldValue = true;
|
|
27
|
+
|
|
28
|
+
// Type guard functions for validation
|
|
29
|
+
if (isLatLonFieldValue(someValue)) {
|
|
30
|
+
// someValue is guaranteed to be boolean | null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (isLocalizedLatLonFieldValue(localizedValue)) {
|
|
34
|
+
// localizedValue is a localized boolean field
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Validator and appearance types available for type-safe configuration
|
|
38
|
+
type Validators = LatLonFieldValidators;
|
|
39
|
+
type Appearance = LatLonFieldAppearance;
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Context-Dependent field types
|
|
43
|
+
|
|
44
|
+
Some field types have different value formats depending on the API context (request vs response) or query parameters:
|
|
45
|
+
|
|
46
|
+
#### Request vs Response variations
|
|
47
|
+
|
|
48
|
+
**File and Gallery fields** have different type requirements for API requests versus responses:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import {
|
|
52
|
+
FileFieldValue,
|
|
53
|
+
FileFieldValueInRequest,
|
|
54
|
+
GalleryFieldValue,
|
|
55
|
+
GalleryFieldValueInRequest,
|
|
56
|
+
// Type guards for runtime validation
|
|
57
|
+
isFileFieldValue,
|
|
58
|
+
isFileFieldValueInRequest,
|
|
59
|
+
isGalleryFieldValue,
|
|
60
|
+
isGalleryFieldValueInRequest
|
|
61
|
+
} from '@datocms/cma-client';
|
|
62
|
+
|
|
63
|
+
// API Response format - all metadata fields present with defaults
|
|
64
|
+
const fileResponse: FileFieldValue = {
|
|
65
|
+
upload_id: "12345",
|
|
66
|
+
alt: null, // Always present (default: null)
|
|
67
|
+
title: null, // Always present (default: null)
|
|
68
|
+
custom_data: {}, // Always present (default: {})
|
|
69
|
+
focal_point: null // Always present (default: null)
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
// API Request format - metadata fields are optional
|
|
73
|
+
const fileRequest: FileFieldValueInRequest = {
|
|
74
|
+
upload_id: "12345"
|
|
75
|
+
// alt, title, custom_data, focal_point are optional
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// Runtime validation for different contexts
|
|
79
|
+
if (isFileFieldValueInRequest(someFileValue)) {
|
|
80
|
+
// someFileValue has optional metadata fields
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (isGalleryFieldValue(someGalleryValue)) {
|
|
84
|
+
// someGalleryValue is array of files with all metadata present
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### "Nested Mode" Response variations
|
|
89
|
+
|
|
90
|
+
**Block-containing fields** (`structured_text`, `single_block`, `rich_text`) support different block representations for regular responses, for ["Nested Mode" responses](https://www.datocms.com/docs/content-management-api/resources/item#api-response-modes-regular-vs-nested), and for requests:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
import {
|
|
94
|
+
StructuredTextFieldValue,
|
|
95
|
+
StructuredTextFieldValueInRequest,
|
|
96
|
+
StructuredTextFieldValueInNestedResponse,
|
|
97
|
+
// Type guards for all variations (also available for single_block and rich_text)
|
|
98
|
+
isStructuredTextFieldValue,
|
|
99
|
+
isStructuredTextFieldValueInRequest,
|
|
100
|
+
isStructuredTextFieldValueInNestedResponse
|
|
101
|
+
} from '@datocms/cma-client';
|
|
102
|
+
|
|
103
|
+
// Regular response - blocks as string IDs
|
|
104
|
+
const standard: StructuredTextFieldValue = {
|
|
105
|
+
document: {
|
|
106
|
+
type: "root",
|
|
107
|
+
children: [
|
|
108
|
+
{
|
|
109
|
+
type: "block",
|
|
110
|
+
// String ID reference
|
|
111
|
+
item: "IdMLV2GJTXyQ0Bfns7R4IQ"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Nested Mode response (?nested=true) - blocks as full objects
|
|
118
|
+
const nested: StructuredTextFieldValueInNestedResponse = {
|
|
119
|
+
document: {
|
|
120
|
+
type: "root",
|
|
121
|
+
children: [
|
|
122
|
+
{
|
|
123
|
+
type: "block",
|
|
124
|
+
// Always full block object
|
|
125
|
+
item: {
|
|
126
|
+
id: "IdMLV2GJTXyQ0Bfns7R4IQ",
|
|
127
|
+
type: "item",
|
|
128
|
+
attributes: { /* ... */ },
|
|
129
|
+
relationships: { /* ... */ }
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Request format - flexible block representation
|
|
137
|
+
const request: StructuredTextFieldValueInRequest = {
|
|
138
|
+
document: {
|
|
139
|
+
type: "root",
|
|
140
|
+
children: [
|
|
141
|
+
{
|
|
142
|
+
type: "block",
|
|
143
|
+
// Can be string ID, to keep block unchanged...
|
|
144
|
+
item: "FicV5CxCSQ6yOrgfwRoiKA"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
type: "block",
|
|
148
|
+
// ...or full block object (to create new blocks or update existing ones)
|
|
149
|
+
item: {
|
|
150
|
+
type: "item",
|
|
151
|
+
attributes: { /* ... */ },
|
|
152
|
+
relationships: { /* ... */ }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Runtime validation for different contexts
|
|
160
|
+
if (isStructuredTextFieldValueInNestedResponse(someStructuredText)) {
|
|
161
|
+
// someStructuredText has blocks as full objects
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (isStructuredTextFieldValueInRequest(requestData)) {
|
|
165
|
+
// requestData allows flexible block representations
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
These variants ensure type safety across different API contexts while maintaining the same conceptual data structure. All localized variants also have corresponding type guards (e.g., `isLocalizedStructuredTextFieldValueInRequest`, `isLocalizedStructuredTextFieldValueInNestedResponse`, etc.).
|
|
170
|
+
|
|
171
|
+
**TypeScript Generics Support:** For maximum type safety, all field value types and type guards for block-containing fields accept [`ItemTypeDefinition` generics](https://www.datocms.com/docs/content-management-api/resources/item#type-safe-development-with-typescript) to provide precise typing for your specific schema:
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
import type { MyArticle, MyArticleSection } from './schema';
|
|
175
|
+
|
|
176
|
+
// Fully typed structured text with specific block types
|
|
177
|
+
const content: StructuredTextFieldValueInRequest<MyArticleSection> = {
|
|
178
|
+
document: {
|
|
179
|
+
type: "root",
|
|
180
|
+
children: [/* ... */]
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Type guard with generic for precise validation
|
|
185
|
+
if (isStructuredTextFieldValueInNestedResponse<MyArticleSection>(value)) {
|
|
186
|
+
// value is now typed with your specific block schema
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Block Processing Utilities
|
|
191
|
+
|
|
192
|
+
### Inspecting Records and Blocks
|
|
18
193
|
|
|
19
194
|
The `inspectItem()` function provides a visual, tree-structured representation of DatoCMS records in the console, making it easier to debug and understand complex content structures.
|
|
20
195
|
|
|
@@ -59,13 +234,49 @@ console.log(inspectItem(record));
|
|
|
59
234
|
```
|
|
60
235
|
</details>
|
|
61
236
|
|
|
62
|
-
###
|
|
237
|
+
### Creating and Duplicating Blocks
|
|
238
|
+
|
|
239
|
+
<details>
|
|
240
|
+
<summary><strong>buildBlockRecord()</strong> - Create block records from data</summary>
|
|
241
|
+
|
|
242
|
+
Converts a block data object into the proper format for API requests.
|
|
243
|
+
|
|
244
|
+
**TypeScript Signature:**
|
|
245
|
+
```typescript
|
|
246
|
+
function buildBlockRecord<D extends ItemTypeDefinition>(
|
|
247
|
+
body: ItemUpdateSchema<ToItemDefinitionInRequest<D>>
|
|
248
|
+
): NewBlockInRequest<ToItemDefinitionInRequest<D>>
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**Parameters:**
|
|
252
|
+
- `body`: Block data in update schema format
|
|
253
|
+
|
|
254
|
+
**Returns:** Formatted block record ready for API requests
|
|
255
|
+
</details>
|
|
256
|
+
|
|
257
|
+
<details>
|
|
258
|
+
<summary><strong>duplicateBlockRecord()</strong> - Deep clone blocks with nested content</summary>
|
|
259
|
+
|
|
260
|
+
Creates a deep copy of a block record, including all nested blocks, removing IDs to create new instances.
|
|
261
|
+
|
|
262
|
+
**TypeScript Signature:**
|
|
263
|
+
```typescript
|
|
264
|
+
async function duplicateBlockRecord<D extends ItemTypeDefinition>(
|
|
265
|
+
existingBlock: ItemWithOptionalIdAndMeta<ToItemDefinitionInNestedResponse<D>>,
|
|
266
|
+
schemaRepository: SchemaRepository
|
|
267
|
+
): Promise<NewBlockInRequest<ToItemDefinitionInRequest<D>>>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Parameters:**
|
|
271
|
+
- `existingBlock`: The block to duplicate
|
|
272
|
+
- `schemaRepository`: Repository for schema lookups
|
|
63
273
|
|
|
64
|
-
|
|
274
|
+
**Returns:** New block record without IDs, ready to be created
|
|
275
|
+
</details>
|
|
65
276
|
|
|
66
|
-
|
|
277
|
+
### Recursive Block Operations
|
|
67
278
|
|
|
68
|
-
These functions traverse blocks recursively, processing nested blocks within blocks. They require a `SchemaRepository` instance to look up field definitions for nested blocks.
|
|
279
|
+
DatoCMS supports three field types that can contain blocks: Modular Content (arrays of blocks), Single Block fields, and Structured Text (rich-text with embedded blocks). These functions abstract away the differences between field types and can traverse blocks recursively, processing nested blocks within blocks. They require a `SchemaRepository` instance to look up field definitions for nested blocks.
|
|
69
280
|
|
|
70
281
|
<details>
|
|
71
282
|
<summary><strong>visitBlocksInNonLocalizedFieldValue()</strong> - Recursively visit all blocks</summary>
|
|
@@ -79,17 +290,14 @@ async function visitBlocksInNonLocalizedFieldValue(
|
|
|
79
290
|
fieldType: string,
|
|
80
291
|
schemaRepository: SchemaRepository,
|
|
81
292
|
visitor: (item: BlockInRequest, path: TreePath) => void | Promise<void>,
|
|
82
|
-
path?: TreePath
|
|
83
293
|
): Promise<void>
|
|
84
294
|
```
|
|
85
295
|
|
|
86
296
|
**Parameters:**
|
|
87
297
|
- `nonLocalizedFieldValue`: The non-localized field value
|
|
88
|
-
- `fieldType`: The
|
|
298
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
89
299
|
- `schemaRepository`: Repository for caching schema lookups
|
|
90
300
|
- `visitor`: Function called for each block (including nested)
|
|
91
|
-
- `path`: Optional base path for tracking location
|
|
92
|
-
```
|
|
93
301
|
</details>
|
|
94
302
|
|
|
95
303
|
<details>
|
|
@@ -104,13 +312,12 @@ async function mapBlocksInNonLocalizedFieldValue(
|
|
|
104
312
|
fieldType: string,
|
|
105
313
|
schemaRepository: SchemaRepository,
|
|
106
314
|
mapper: (item: BlockInRequest, path: TreePath) => BlockInRequest | Promise<BlockInRequest>,
|
|
107
|
-
path?: TreePath
|
|
108
315
|
): Promise<unknown>
|
|
109
316
|
```
|
|
110
317
|
|
|
111
318
|
**Parameters:**
|
|
112
319
|
- `nonLocalizedFieldValue`: The non-localized field value
|
|
113
|
-
- `fieldType`: The
|
|
320
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
114
321
|
- `schemaRepository`: Repository for caching schema lookups
|
|
115
322
|
- `mapper`: Function that transforms each block
|
|
116
323
|
|
|
@@ -129,13 +336,12 @@ async function filterBlocksInNonLocalizedFieldValue(
|
|
|
129
336
|
fieldType: string,
|
|
130
337
|
schemaRepository: SchemaRepository,
|
|
131
338
|
predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
|
|
132
|
-
path?: TreePath
|
|
133
339
|
): Promise<unknown>
|
|
134
340
|
```
|
|
135
341
|
|
|
136
342
|
**Parameters:**
|
|
137
343
|
- `nonLocalizedFieldValue`: The non-localized field value to filter
|
|
138
|
-
- `fieldType`: The
|
|
344
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
139
345
|
- `schemaRepository`: Repository for caching schema lookups
|
|
140
346
|
- `predicate`: Function that tests each block
|
|
141
347
|
|
|
@@ -165,13 +371,12 @@ async function findAllBlocksInNonLocalizedFieldValue(
|
|
|
165
371
|
fieldType: string,
|
|
166
372
|
schemaRepository: SchemaRepository,
|
|
167
373
|
predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
|
|
168
|
-
path?: TreePath
|
|
169
374
|
): Promise<Array<{ item: BlockInRequest; path: TreePath }>>
|
|
170
375
|
```
|
|
171
376
|
|
|
172
377
|
**Parameters:**
|
|
173
378
|
- `nonLocalizedFieldValue`: The non-localized field value to search
|
|
174
|
-
- `fieldType`: The
|
|
379
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
175
380
|
- `schemaRepository`: Repository for caching schema lookups
|
|
176
381
|
- `predicate`: Function that tests each block
|
|
177
382
|
|
|
@@ -191,19 +396,17 @@ async function reduceBlocksInNonLocalizedFieldValue<R>(
|
|
|
191
396
|
schemaRepository: SchemaRepository,
|
|
192
397
|
reducer: (accumulator: R, item: BlockInRequest, path: TreePath) => R | Promise<R>,
|
|
193
398
|
initialValue: R,
|
|
194
|
-
path?: TreePath
|
|
195
399
|
): Promise<R>
|
|
196
400
|
```
|
|
197
401
|
|
|
198
402
|
**Parameters:**
|
|
199
403
|
- `nonLocalizedFieldValue`: The non-localized field value to reduce
|
|
200
|
-
- `fieldType`: The
|
|
404
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
201
405
|
- `schemaRepository`: Repository for caching schema lookups
|
|
202
406
|
- `reducer`: Function that processes each block
|
|
203
407
|
- `initialValue`: Initial accumulator value
|
|
204
408
|
|
|
205
409
|
**Returns:** The final accumulated value
|
|
206
|
-
```
|
|
207
410
|
</details>
|
|
208
411
|
|
|
209
412
|
<details>
|
|
@@ -218,18 +421,16 @@ async function someBlocksInNonLocalizedFieldValue(
|
|
|
218
421
|
fieldType: string,
|
|
219
422
|
schemaRepository: SchemaRepository,
|
|
220
423
|
predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
|
|
221
|
-
path?: TreePath
|
|
222
424
|
): Promise<boolean>
|
|
223
425
|
```
|
|
224
426
|
|
|
225
427
|
**Parameters:**
|
|
226
428
|
- `nonLocalizedFieldValue`: The non-localized field value to test
|
|
227
|
-
- `fieldType`: The
|
|
429
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
228
430
|
- `schemaRepository`: Repository for caching schema lookups
|
|
229
431
|
- `predicate`: Function that tests each block
|
|
230
432
|
|
|
231
433
|
**Returns:** True if any block matches
|
|
232
|
-
```
|
|
233
434
|
</details>
|
|
234
435
|
|
|
235
436
|
<details>
|
|
@@ -244,79 +445,22 @@ async function everyBlockInNonLocalizedFieldValue(
|
|
|
244
445
|
fieldType: string,
|
|
245
446
|
schemaRepository: SchemaRepository,
|
|
246
447
|
predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
|
|
247
|
-
path?: TreePath
|
|
248
448
|
): Promise<boolean>
|
|
249
449
|
```
|
|
250
450
|
|
|
251
451
|
**Parameters:**
|
|
252
452
|
- `nonLocalizedFieldValue`: The non-localized field value to test
|
|
253
|
-
- `fieldType`: The
|
|
453
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
254
454
|
- `schemaRepository`: Repository for caching schema lookups
|
|
255
455
|
- `predicate`: Function that tests each block
|
|
256
456
|
|
|
257
457
|
**Returns:** True if all blocks match
|
|
258
458
|
</details>
|
|
259
459
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
<details>
|
|
263
|
-
<summary><strong>buildBlockRecord()</strong> - Create block records from data</summary>
|
|
264
|
-
|
|
265
|
-
Converts a block data object into the proper format for API requests.
|
|
266
|
-
|
|
267
|
-
**TypeScript Signature:**
|
|
268
|
-
```typescript
|
|
269
|
-
function buildBlockRecord<D extends ItemTypeDefinition>(
|
|
270
|
-
body: ItemUpdateSchema<ToItemDefinitionInRequest<D>>
|
|
271
|
-
): NewBlockInRequest<ToItemDefinitionInRequest<D>>
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
**Parameters:**
|
|
275
|
-
- `body`: Block data in update schema format
|
|
276
|
-
|
|
277
|
-
**Returns:** Formatted block record ready for API requests
|
|
278
|
-
</details>
|
|
279
|
-
|
|
280
|
-
<details>
|
|
281
|
-
<summary><strong>duplicateBlockRecord()</strong> - Deep clone blocks with nested content</summary>
|
|
282
|
-
|
|
283
|
-
Creates a deep copy of a block record, including all nested blocks, removing IDs to create new instances.
|
|
284
|
-
|
|
285
|
-
**TypeScript Signature:**
|
|
286
|
-
```typescript
|
|
287
|
-
async function duplicateBlockRecord<D extends ItemTypeDefinition>(
|
|
288
|
-
existingBlock: ItemWithOptionalIdAndMeta<ToItemDefinitionInNestedResponse<D>>,
|
|
289
|
-
schemaRepository: SchemaRepository
|
|
290
|
-
): Promise<NewBlockInRequest<ToItemDefinitionInRequest<D>>>
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
**Parameters:**
|
|
294
|
-
- `existingBlock`: The block to duplicate
|
|
295
|
-
- `schemaRepository`: Repository for schema lookups
|
|
296
|
-
|
|
297
|
-
**Returns:** New block record without IDs, ready to be created
|
|
298
|
-
</details>
|
|
299
|
-
|
|
300
|
-
### 3. Localization-Aware Field Utilities
|
|
460
|
+
## Unified Field Processing (Localized & Non-Localized)
|
|
301
461
|
|
|
302
462
|
These utilities provide a unified interface for working with DatoCMS field values that may or may not be localized. They eliminate the need for conditional logic when processing fields that could be either localized or non-localized.
|
|
303
463
|
|
|
304
|
-
<details>
|
|
305
|
-
<summary><strong>isLocalized()</strong> - Check if a field is localized</summary>
|
|
306
|
-
|
|
307
|
-
Determines whether a DatoCMS field is configured for localization.
|
|
308
|
-
|
|
309
|
-
**TypeScript Signature:**
|
|
310
|
-
```typescript
|
|
311
|
-
function isLocalized(field: Field): boolean
|
|
312
|
-
```
|
|
313
|
-
|
|
314
|
-
**Parameters:**
|
|
315
|
-
- `fieldType`: The typeo of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
316
|
-
|
|
317
|
-
**Returns:** True if the field is localized, false otherwise
|
|
318
|
-
</details>
|
|
319
|
-
|
|
320
464
|
<details>
|
|
321
465
|
<summary><strong>mapNormalizedFieldValues() / mapNormalizedFieldValuesAsync()</strong> - Transform field values</summary>
|
|
322
466
|
|
|
@@ -338,7 +482,7 @@ async function mapNormalizedFieldValuesAsync<TInput, TOutput>(
|
|
|
338
482
|
```
|
|
339
483
|
|
|
340
484
|
**Parameters:**
|
|
341
|
-
- `fieldType`: The
|
|
485
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
342
486
|
- `nonLocalizedFieldValue`: The non-localized field value (localized or non-localized)
|
|
343
487
|
- `mapFn`: Function to transform each value (receives locale for localized fields, undefined for non-localized)
|
|
344
488
|
|
|
@@ -366,7 +510,7 @@ async function filterNormalizedFieldValuesAsync<T>(
|
|
|
366
510
|
```
|
|
367
511
|
|
|
368
512
|
**Parameters:**
|
|
369
|
-
- `fieldType`: The
|
|
513
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
370
514
|
- `nonLocalizedFieldValue`: The non-localized field value to filter
|
|
371
515
|
- `filterFn`: Predicate function for filtering
|
|
372
516
|
|
|
@@ -394,7 +538,7 @@ async function visitNormalizedFieldValuesAsync<T>(
|
|
|
394
538
|
```
|
|
395
539
|
|
|
396
540
|
**Parameters:**
|
|
397
|
-
- `fieldType`: The
|
|
541
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
398
542
|
- `nonLocalizedFieldValue`: The non-localized field value to visit
|
|
399
543
|
- `visitFn`: Function called for each value
|
|
400
544
|
</details>
|
|
@@ -420,7 +564,7 @@ async function someNormalizedFieldValuesAsync<T>(
|
|
|
420
564
|
```
|
|
421
565
|
|
|
422
566
|
**Parameters:**
|
|
423
|
-
- `fieldType`: The
|
|
567
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
424
568
|
- `nonLocalizedFieldValue`: The non-localized field value to test
|
|
425
569
|
- `testFn`: Predicate function
|
|
426
570
|
|
|
@@ -448,7 +592,7 @@ async function everyNormalizedFieldValueAsync<T>(
|
|
|
448
592
|
```
|
|
449
593
|
|
|
450
594
|
**Parameters:**
|
|
451
|
-
- `fieldType`: The
|
|
595
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
452
596
|
- `nonLocalizedFieldValue`: The non-localized field value to test
|
|
453
597
|
- `testFn`: Predicate function
|
|
454
598
|
|
|
@@ -479,7 +623,7 @@ type NormalizedFieldValueEntry<T> = {
|
|
|
479
623
|
```
|
|
480
624
|
|
|
481
625
|
**Parameters:**
|
|
482
|
-
- `fieldType`: The
|
|
626
|
+
- `fieldType`: The type of DatoCMS field (ie. `string`, `rich_text`, etc.)
|
|
483
627
|
- `nonLocalizedFieldValue`/`entries non-localized`: Value to convert from/to
|
|
484
628
|
|
|
485
629
|
**Returns:** Normalized entries array or reconstructed field value
|
|
@@ -497,25 +641,57 @@ const processed = entries.map(({ locale, value }) => ({
|
|
|
497
641
|
|
|
498
642
|
// Convert back to field value format
|
|
499
643
|
const result = fromNormalizedFieldValueEntries(field, processed);
|
|
500
|
-
```
|
|
501
644
|
</details>
|
|
502
645
|
|
|
503
|
-
### 4.
|
|
646
|
+
### 4. SchemaRepository
|
|
504
647
|
|
|
505
|
-
The `SchemaRepository` class provides
|
|
648
|
+
The `SchemaRepository` class provides a lightweight, in-memory cache for DatoCMS schema entities (item types, fields, fieldsets, and plugins). It helps avoid redundant API calls when working across multiple functions or utilities that require schema lookups.
|
|
506
649
|
|
|
507
|
-
|
|
508
|
-
|
|
650
|
+
**Why use it?**
|
|
651
|
+
|
|
652
|
+
- **Cache once, reuse everywhere**: The first API call stores results in memory; all subsequent lookups are instant.
|
|
653
|
+
- **Efficient schema access**: Retrieve entities by ID, API key, or package name without re-fetching.
|
|
654
|
+
- **Optimized for block processing**: Essential for utilities like `mapBlocksInNonLocalizedFieldValue`.
|
|
655
|
+
- **Fewer API calls**: Dramatically speeds up bulk operations and complex traversals.
|
|
656
|
+
|
|
657
|
+
**Usage Example:**
|
|
658
|
+
```typescript
|
|
659
|
+
const schemaRepository = new SchemaRepository(client);
|
|
660
|
+
|
|
661
|
+
// First call: fetches from API and caches result
|
|
662
|
+
const blogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
|
|
663
|
+
const fields = await schemaRepository.getItemTypeFields(blogPost);
|
|
664
|
+
|
|
665
|
+
// Next calls: resolved instantly from cache (no API calls)
|
|
666
|
+
const sameBlogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
|
|
667
|
+
const sameFields = await schemaRepository.getItemTypeFields(blogPost);
|
|
668
|
+
|
|
669
|
+
// Works seamlessly with block-processing utilities
|
|
670
|
+
await mapBlocksInNonLocalizedFieldValue(
|
|
671
|
+
fieldValue,
|
|
672
|
+
field,
|
|
673
|
+
schemaRepository, // share cached lookups
|
|
674
|
+
async (block) => {
|
|
675
|
+
// transform block here
|
|
676
|
+
}
|
|
677
|
+
);
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**When to Use**
|
|
681
|
+
|
|
682
|
+
* Traversing relationships that repeatedly query schema
|
|
683
|
+
* Bulk record processing scripts
|
|
684
|
+
* Block-processing utilities that need frequent lookups
|
|
685
|
+
* Any script where reducing API calls matters
|
|
509
686
|
|
|
510
|
-
|
|
687
|
+
**When Not to Use**
|
|
511
688
|
|
|
512
|
-
|
|
513
|
-
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
689
|
+
* Scripts that modify schema (models, fields, etc.)
|
|
690
|
+
* Long-running applications (cache never expires)
|
|
691
|
+
* Situations where the schema might change during execution
|
|
692
|
+
|
|
693
|
+
<details><summary><strong>Class signature</strong></summary>
|
|
517
694
|
|
|
518
|
-
**TypeScript Class:**
|
|
519
695
|
```typescript
|
|
520
696
|
class SchemaRepository {
|
|
521
697
|
constructor(client: GenericClient)
|
|
@@ -542,41 +718,6 @@ class SchemaRepository {
|
|
|
542
718
|
// ... and more raw variants
|
|
543
719
|
}
|
|
544
720
|
```
|
|
545
|
-
|
|
546
|
-
**When to Use:**
|
|
547
|
-
- Complex traversal operations that repeatedly lookup schema
|
|
548
|
-
- Bulk operations processing multiple records
|
|
549
|
-
- Scripts that need efficient access to schema information
|
|
550
|
-
- Working with recursive block utilities
|
|
551
|
-
|
|
552
|
-
**When NOT to Use:**
|
|
553
|
-
- Scripts that modify schema (models, fields, etc.)
|
|
554
|
-
- Long-running applications (no cache expiration)
|
|
555
|
-
- When schema might change during execution
|
|
556
|
-
|
|
557
|
-
**Usage Example:**
|
|
558
|
-
```typescript
|
|
559
|
-
const schemaRepository = new SchemaRepository(client);
|
|
560
|
-
|
|
561
|
-
// First call fetches from API and caches
|
|
562
|
-
const blogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
|
|
563
|
-
const fields = await schemaRepository.getItemTypeFields(blogPost);
|
|
564
|
-
|
|
565
|
-
// Subsequent calls use cached data (no API calls)
|
|
566
|
-
const sameBlogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
|
|
567
|
-
const sameFields = await schemaRepository.getItemTypeFields(blogPost);
|
|
568
|
-
|
|
569
|
-
// Use with recursive utilities for optimal performance
|
|
570
|
-
await mapBlocksInNonLocalizedFieldValue(
|
|
571
|
-
schemaRepository, // Pass repository for efficient lookups
|
|
572
|
-
field,
|
|
573
|
-
fieldValue,
|
|
574
|
-
async (block) => { /* transform */ }
|
|
575
|
-
);
|
|
576
|
-
```
|
|
577
|
-
|
|
578
|
-
**Performance Impact:**
|
|
579
|
-
Without SchemaRepository, a script processing structured text with nested blocks might make the same API calls dozens of times. SchemaRepository ensures each unique schema request is made only once, dramatically improving performance for complex operations.
|
|
580
721
|
</details>
|
|
581
722
|
|
|
582
723
|
## Contributing
|
|
@@ -88,7 +88,7 @@ class Client {
|
|
|
88
88
|
return this.config.baseUrl || Client.defaultBaseUrl;
|
|
89
89
|
}
|
|
90
90
|
request(options) {
|
|
91
|
-
return (0, rest_client_utils_1.request)(Object.assign(Object.assign(Object.assign({}, this.config), options), { logFn: this.config.logFn || console.log, userAgent: '@datocms/cma-client v5.1.
|
|
91
|
+
return (0, rest_client_utils_1.request)(Object.assign(Object.assign(Object.assign({}, this.config), options), { logFn: this.config.logFn || console.log, userAgent: '@datocms/cma-client v5.1.13', baseUrl: this.baseUrl, preCallStack: new Error().stack, extraHeaders: Object.assign(Object.assign(Object.assign({}, (this.config.extraHeaders || {})), (this.config.environment
|
|
92
92
|
? { 'X-Environment': this.config.environment }
|
|
93
93
|
: {})), { 'X-API-Version': '3' }), fetchJobResult: (jobId) => {
|
|
94
94
|
return this.jobResultsFetcher
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildBlockRecord.js","sourceRoot":"","sources":["../../../src/utilities/buildBlockRecord.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kEAAoD;AAGpD,sDAA8C;
|
|
1
|
+
{"version":3,"file":"buildBlockRecord.js","sourceRoot":"","sources":["../../../src/utilities/buildBlockRecord.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kEAAoD;AAGpD,sDAA8C;AAmB9C,SAAgB,gBAAgB,CAG9B,IAAiD;IAEjD,OAAO,KAAK,CAAC,oBAAoB,CAE9B,IAAI,EAAE;QACP,IAAI,EAAE,gBAAI,CAAC,IAAI;QACf,UAAU,EAAE,GAAG;QACf,aAAa,EAAE,CAAC,WAAW,CAAC;KAC7B,CAAC,CAAC,IAAI,CAAC;AACV,CAAC;AAZD,4CAYC"}
|
|
@@ -24,9 +24,10 @@ exports.duplicateBlockRecord = void 0;
|
|
|
24
24
|
const recursiveBlocks_1 = require("./recursiveBlocks");
|
|
25
25
|
function duplicateBlockRecord(existingBlock, schemaRepository) {
|
|
26
26
|
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
-
const { type, attributes, relationships } = existingBlock;
|
|
27
|
+
const { __itemTypeId, type, attributes, relationships } = existingBlock;
|
|
28
28
|
const itemType = yield schemaRepository.getRawItemTypeById(existingBlock.relationships.item_type.data.id);
|
|
29
29
|
const newBlock = {
|
|
30
|
+
__itemTypeId,
|
|
30
31
|
type,
|
|
31
32
|
relationships,
|
|
32
33
|
attributes,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duplicateBlockRecord.js","sourceRoot":"","sources":["../../../src/utilities/duplicateBlockRecord.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAKA,uDAAsE;AAKtE,SAAsB,oBAAoB,CAGxC,aAAoD,EACpD,gBAAkC;;QAElC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"duplicateBlockRecord.js","sourceRoot":"","sources":["../../../src/utilities/duplicateBlockRecord.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAKA,uDAAsE;AAKtE,SAAsB,oBAAoB,CAGxC,aAAoD,EACpD,gBAAkC;;QAElC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,aAAa,CAAC;QAExE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,kBAAkB,CACxD,aAAa,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC9C,CAAC;QAEF,MAAM,QAAQ,GAAG;YACf,YAAY;YACZ,IAAI;YACJ,aAAa;YACb,UAAU;SACU,CAAC;QAEvB,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAErE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC3C,MAAM,IAAA,mDAAiC,EACrC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,EAC7C,KAAK,CAAC,UAAU,CAAC,UAAU,EAC3B,gBAAgB,EAChB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;oBACd,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;wBAC7B,MAAM,IAAI,KAAK,CACb,6DAA6D,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,6BAA6B,KAAK,2BAA2B,CACzI,CAAC;qBACH;oBAED,MAAM,EAAE,EAAE,EAAE,IAAI,KAA+B,KAAK,EAA/B,qBAAqB,UAAK,KAAK,EAA9C,cAAsC,CAAQ,CAAC;oBAErD,OAAO,qBAA0C,CAAC;gBACpD,CAAC,CACF,CAAC;SACL;QAED,OAAO,QAAyC,CAAC;IACnD,CAAC;CAAA;AA1CD,oDA0CC"}
|
|
@@ -20,7 +20,7 @@ type NonLocalizedFieldAttributesForFieldType<SourceType, FieldType extends Field
|
|
|
20
20
|
type LocalizedFieldAttributesForFieldType<SourceType, FieldType extends FieldAttributesStableShell['field_type'], FieldValue, FieldValidators, FieldAppearance> = Omit<SourceType, 'field_type' | 'default_value' | 'validators' | 'appearance' | 'localized'> & {
|
|
21
21
|
field_type: FieldType;
|
|
22
22
|
localized: true;
|
|
23
|
-
default_value:
|
|
23
|
+
default_value: Record<string, FieldValue>;
|
|
24
24
|
validators: FieldValidators;
|
|
25
25
|
appearance: FieldAppearanceConfig<FieldAppearance>;
|
|
26
26
|
};
|
|
@@ -52,7 +52,7 @@ export type UpdatedBlockInRequest<D extends ItemTypeDefinition = ItemTypeDefinit
|
|
|
52
52
|
__itemTypeId?: D['itemTypeId'];
|
|
53
53
|
type: RawApiTypes.ItemType1;
|
|
54
54
|
id: RawApiTypes.ItemIdentity;
|
|
55
|
-
relationships
|
|
55
|
+
relationships: RawApiTypes.ItemRelationships<D>;
|
|
56
56
|
meta?: RawApiTypes.ItemMeta;
|
|
57
57
|
attributes: ToItemAttributesInRequest<D>;
|
|
58
58
|
};
|