@datocms/cma-client 5.1.25 → 5.1.27

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.
@@ -147,7 +147,7 @@ export class Client {
147
147
  ...this.config,
148
148
  ...options,
149
149
  logFn: this.config.logFn || console.log,
150
- userAgent: '@datocms/cma-client v5.1.25',
150
+ userAgent: '@datocms/cma-client v5.1.27',
151
151
  baseUrl: this.baseUrl,
152
152
  preCallStack: new Error().stack,
153
153
  extraHeaders: {
@@ -147,14 +147,12 @@ export default class Field extends BaseResource {
147
147
  }
148
148
 
149
149
  /**
150
- * List referenced fields
150
+ * List fields referencing a model/block
151
151
  *
152
152
  * Read more: https://www.datocms.com/docs/content-management-api/resources/field/referencing
153
153
  *
154
154
  * @throws {ApiError}
155
155
  * @throws {TimeoutError}
156
- *
157
- * @deprecated This API call is to be considered private and might change without notice
158
156
  */
159
157
  referencing(itemTypeId: string | ApiTypes.ItemTypeData) {
160
158
  return this.rawReferencing(Utils.toId(itemTypeId)).then((body) =>
@@ -165,14 +163,12 @@ export default class Field extends BaseResource {
165
163
  }
166
164
 
167
165
  /**
168
- * List referenced fields
166
+ * List fields referencing a model/block
169
167
  *
170
168
  * Read more: https://www.datocms.com/docs/content-management-api/resources/field/referencing
171
169
  *
172
170
  * @throws {ApiError}
173
171
  * @throws {TimeoutError}
174
- *
175
- * @deprecated This API call is to be considered private and might change without notice
176
172
  */
177
173
  rawReferencing(
178
174
  itemTypeId: string,
@@ -273,7 +273,7 @@ export default class ItemType extends BaseResource {
273
273
  }
274
274
 
275
275
  /**
276
- * List models referencing a model or block model
276
+ * List models referencing another model/block
277
277
  *
278
278
  * Read more: https://www.datocms.com/docs/content-management-api/resources/item-type/referencing
279
279
  *
@@ -289,7 +289,7 @@ export default class ItemType extends BaseResource {
289
289
  }
290
290
 
291
291
  /**
292
- * List models referencing a model or block model
292
+ * List models referencing another model/block
293
293
  *
294
294
  * Read more: https://www.datocms.com/docs/content-management-api/resources/item-type/referencing
295
295
  *
@@ -1,7 +1,10 @@
1
1
  import { deserializeResponseBody } from '@datocms/rest-client-utils';
2
2
  import type * as ApiTypes from '../generated/ApiTypes';
3
3
  import type * as RawApiTypes from '../generated/RawApiTypes';
4
- import { blockModelIdsReferencedInField } from './fieldsContainingReferences';
4
+ import {
5
+ blockModelIdsReferencedInField,
6
+ modelIdsReferencedInField,
7
+ } from './fieldsContainingReferences';
5
8
 
6
9
  interface GenericClient {
7
10
  itemTypes: {
@@ -265,9 +268,7 @@ export class SchemaRepository {
265
268
  async getItemTypeFields(
266
269
  itemType: ApiTypes.ItemType | RawApiTypes.ItemType,
267
270
  ): Promise<ApiTypes.Field[]> {
268
- const rawResult = await this.getRawItemTypeFields(
269
- itemType as RawApiTypes.ItemType,
270
- );
271
+ const rawResult = await this.getRawItemTypeFields(itemType);
271
272
  return deserializeResponseBody<ApiTypes.Field[]>({
272
273
  data: rawResult,
273
274
  });
@@ -280,7 +281,7 @@ export class SchemaRepository {
280
281
  * @returns Promise that resolves to an array of fields
281
282
  */
282
283
  async getRawItemTypeFields(
283
- itemType: RawApiTypes.ItemType,
284
+ itemType: ApiTypes.ItemType | RawApiTypes.ItemType,
284
285
  ): Promise<RawApiTypes.Field[]> {
285
286
  // Check if we already have the fields cached
286
287
  const cachedFields = this.fieldsByItemType.get(itemType.id);
@@ -304,9 +305,7 @@ export class SchemaRepository {
304
305
  async getItemTypeFieldsets(
305
306
  itemType: ApiTypes.ItemType | RawApiTypes.ItemType,
306
307
  ): Promise<ApiTypes.Fieldset[]> {
307
- const rawResult = await this.getRawItemTypeFieldsets(
308
- itemType as RawApiTypes.ItemType,
309
- );
308
+ const rawResult = await this.getRawItemTypeFieldsets(itemType);
310
309
  return deserializeResponseBody<ApiTypes.Fieldset[]>({
311
310
  data: rawResult,
312
311
  });
@@ -319,7 +318,7 @@ export class SchemaRepository {
319
318
  * @returns Promise that resolves to an array of fieldsets
320
319
  */
321
320
  async getRawItemTypeFieldsets(
322
- itemType: RawApiTypes.ItemType,
321
+ itemType: ApiTypes.ItemType | RawApiTypes.ItemType,
323
322
  ): Promise<RawApiTypes.Fieldset[]> {
324
323
  // Check if we already have the fieldsets cached
325
324
  const cachedFieldsets = this.fieldsetsByItemType.get(itemType.id);
@@ -589,4 +588,163 @@ export class SchemaRepository {
589
588
  data: rawResult,
590
589
  });
591
590
  }
591
+
592
+ /**
593
+ * Gets all block models that are directly or indirectly nested within the given item types.
594
+ * This method recursively traverses the schema to find all blocks that are nested
595
+ * within the provided item types, either directly through block fields or indirectly through
596
+ * other nested block models.
597
+ *
598
+ * @param itemTypes - Array of item types to find nested blocks for
599
+ * @returns Promise that resolves to array of all block models nested in these item types
600
+ */
601
+ async getRawNestedBlocks(
602
+ itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>,
603
+ ): Promise<Array<RawApiTypes.ItemType>> {
604
+ await this.prefetchAllModelsAndFields();
605
+
606
+ const allItemTypes = await this.getAllRawItemTypes();
607
+ const visited = new Set<string>();
608
+ const nestedBlocks: Array<RawApiTypes.ItemType> = [];
609
+
610
+ // Helper function to recursively find nested blocks
611
+ const findNestedBlocks = async (
612
+ itemType: ApiTypes.ItemType | RawApiTypes.ItemType,
613
+ alreadyExplored: Set<string> = new Set(),
614
+ ): Promise<void> => {
615
+ if (alreadyExplored.has(itemType.id)) {
616
+ return;
617
+ }
618
+
619
+ alreadyExplored.add(itemType.id);
620
+
621
+ const fields = await this.getRawItemTypeFields(itemType);
622
+
623
+ for (const field of fields) {
624
+ const referencedBlockIds = blockModelIdsReferencedInField(field);
625
+
626
+ for (const blockId of referencedBlockIds) {
627
+ if (!visited.has(blockId)) {
628
+ visited.add(blockId);
629
+ const nestedBlock = allItemTypes.find((it) => it.id === blockId);
630
+ if (nestedBlock) {
631
+ nestedBlocks.push(nestedBlock);
632
+ // Recursively find blocks nested in this block
633
+ await findNestedBlocks(nestedBlock, new Set(alreadyExplored));
634
+ }
635
+ }
636
+ }
637
+ }
638
+ };
639
+
640
+ // Find nested blocks for each provided item type
641
+ for (const itemType of itemTypes) {
642
+ await findNestedBlocks(itemType);
643
+ }
644
+
645
+ return nestedBlocks;
646
+ }
647
+
648
+ /**
649
+ * Gets all block models that are directly or indirectly nested within the given item types.
650
+ * This method recursively traverses the schema to find all blocks that are nested
651
+ * within the provided item types, either directly through block fields or indirectly through
652
+ * other nested block models.
653
+ *
654
+ * @param itemTypes - Array of item types to find nested blocks for
655
+ * @returns Promise that resolves to array of all block models nested in these item types
656
+ */
657
+ async getNestedBlocks(
658
+ itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>,
659
+ ): Promise<Array<ApiTypes.ItemType>> {
660
+ const rawResult = await this.getRawNestedBlocks(itemTypes);
661
+ return deserializeResponseBody<ApiTypes.ItemType[]>({
662
+ data: rawResult,
663
+ });
664
+ }
665
+
666
+ /**
667
+ * Gets all models that are directly or indirectly nested/referenced within the given item types.
668
+ * This method recursively traverses the schema to find all models that are referenced
669
+ * by the provided item types through link fields, either directly or indirectly through
670
+ * other referenced blocks.
671
+ *
672
+ * @param itemTypes - Array of item types to find nested models for
673
+ * @returns Promise that resolves to array of all models nested in these item types
674
+ */
675
+ async getRawNestedModels(
676
+ itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>,
677
+ ): Promise<Array<RawApiTypes.ItemType>> {
678
+ await this.prefetchAllModelsAndFields();
679
+
680
+ const allItemTypes = await this.getAllRawItemTypes();
681
+ const visited = new Set<string>();
682
+ const nestedModels: Array<RawApiTypes.ItemType> = [];
683
+
684
+ // Helper function to recursively find nested models
685
+ const findNestedModels = async (
686
+ itemType: ApiTypes.ItemType | RawApiTypes.ItemType,
687
+ alreadyExplored: Set<string> = new Set(),
688
+ ): Promise<void> => {
689
+ if (alreadyExplored.has(itemType.id)) {
690
+ return;
691
+ }
692
+
693
+ alreadyExplored.add(itemType.id);
694
+
695
+ const fields = await this.getRawItemTypeFields(itemType);
696
+
697
+ for (const field of fields) {
698
+ // Find models directly referenced via link fields
699
+ const referencedModelIds = modelIdsReferencedInField(field);
700
+
701
+ for (const modelId of referencedModelIds) {
702
+ if (!visited.has(modelId)) {
703
+ visited.add(modelId);
704
+ const nestedModel = allItemTypes.find((it) => it.id === modelId);
705
+ if (nestedModel) {
706
+ nestedModels.push(nestedModel);
707
+ // Do NOT recurse into models, only into blocks
708
+ }
709
+ }
710
+ }
711
+
712
+ // Find blocks referenced via block fields, then recursively find models in those blocks
713
+ const referencedBlockIds = blockModelIdsReferencedInField(field);
714
+
715
+ for (const blockId of referencedBlockIds) {
716
+ const nestedBlock = allItemTypes.find((it) => it.id === blockId);
717
+ if (nestedBlock) {
718
+ // Recursively find models nested in this block
719
+ await findNestedModels(nestedBlock, new Set(alreadyExplored));
720
+ }
721
+ }
722
+ }
723
+ };
724
+
725
+ // Find nested models for each provided item type
726
+ for (const itemType of itemTypes) {
727
+ await findNestedModels(itemType);
728
+ }
729
+
730
+ return nestedModels;
731
+ }
732
+
733
+ /**
734
+ * Gets all models that are directly or indirectly nested/referenced within the given item types.
735
+ * This method recursively traverses the schema to find all models that are referenced
736
+ * by the provided item types through link fields, either directly or indirectly through
737
+ * other referenced blocks.
738
+ *
739
+ * @param itemTypes - Array of item types to find nested models for
740
+ * @returns Promise that resolves to array of all models nested in these item types
741
+ */
742
+ async getNestedModels(
743
+ itemTypes: Array<ApiTypes.ItemType | RawApiTypes.ItemType>,
744
+ ): Promise<Array<ApiTypes.ItemType>> {
745
+ const rawResult = await this.getRawNestedModels(itemTypes);
746
+ return deserializeResponseBody<ApiTypes.ItemType[]>({
747
+ data: rawResult,
748
+ });
749
+ }
592
750
  }