@uniformdev/transformer 1.1.20 → 1.1.22

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/index.d.ts CHANGED
@@ -130,7 +130,8 @@ interface PropagateRootComponentSlotOptions extends GlobalOptions {
130
130
  }
131
131
  interface ConvertCompositionsToEntriesOptions extends GlobalOptions {
132
132
  compositionTypes: string;
133
- flattenComponentIds?: string;
133
+ componentsToReferences?: string;
134
+ componentsToBlocks?: string;
134
135
  }
135
136
  interface RemoveParameterOptions extends GlobalOptions {
136
137
  componentType: string;
@@ -199,6 +200,14 @@ declare class ComponentService {
199
200
  }>;
200
201
  saveComponent(filePath: string, component: ComponentDefinition): Promise<void>;
201
202
  private sortComponentArrays;
203
+ sortParametersByGroup<T extends {
204
+ id: string;
205
+ type: string;
206
+ typeConfig?: {
207
+ childrenParams?: string[];
208
+ [key: string]: unknown;
209
+ };
210
+ }>(parameters: T[]): T[];
202
211
  findParameter(component: ComponentDefinition, parameterName: string, options?: FindOptions$1): Parameter | undefined;
203
212
  isGroupParameter(parameter: Parameter): boolean;
204
213
  resolveGroupParameters(component: ComponentDefinition, groupParameter: Parameter, options?: FindOptions$1): Parameter[];
@@ -409,11 +418,13 @@ interface ConvertCompositionsToEntriesInternalOptions {
409
418
  contentTypesDir: string;
410
419
  entriesDir: string;
411
420
  compositionTypes: string[];
412
- flattenComponentIds: string[];
421
+ componentsToReferences: string[];
422
+ componentsToBlocks: string[];
413
423
  whatIf: boolean;
414
424
  strict: boolean;
415
425
  }
416
426
  interface ContentTypeDefinition {
427
+ type?: string;
417
428
  id: string;
418
429
  name: string;
419
430
  fields: ContentTypeField[];
@@ -452,8 +463,9 @@ interface FlattenedInstance {
452
463
  interface ConvertResult {
453
464
  contentTypesWritten: number;
454
465
  entriesFromCompositions: number;
455
- entriesFromFlattened: number;
466
+ entriesFromReferences: number;
456
467
  entriesReused: number;
468
+ blocksEmbedded: number;
457
469
  }
458
470
  declare class CompositionConverterService {
459
471
  private fileSystem;
package/dist/index.js CHANGED
@@ -185,19 +185,51 @@ var ComponentService = class {
185
185
  sortComponentArrays(component) {
186
186
  const result = { ...component };
187
187
  if (result.parameters) {
188
- result.parameters = [...result.parameters].sort((a, b) => a.id.localeCompare(b.id));
188
+ result.parameters = this.sortParametersByGroup(result.parameters);
189
189
  }
190
190
  if (result.slots) {
191
- result.slots = [...result.slots].sort((a, b) => a.id.localeCompare(b.id)).map((slot) => {
191
+ result.slots = [...result.slots].sort((a, b) => a.id.localeCompare(b.id, void 0, { sensitivity: "base" })).map((slot) => {
192
192
  if (slot.allowedComponents) {
193
- return { ...slot, allowedComponents: [...slot.allowedComponents].sort((a, b) => a.localeCompare(b)) };
193
+ return { ...slot, allowedComponents: [...slot.allowedComponents].sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" })) };
194
194
  }
195
195
  return slot;
196
196
  });
197
197
  }
198
198
  const variants = result.variants;
199
199
  if (Array.isArray(variants)) {
200
- result.variants = [...variants].sort((a, b) => a.id.localeCompare(b.id));
200
+ result.variants = [...variants].sort((a, b) => a.id.localeCompare(b.id, void 0, { sensitivity: "base" }));
201
+ }
202
+ return result;
203
+ }
204
+ sortParametersByGroup(parameters) {
205
+ const compare = (a, b) => a.localeCompare(b, void 0, { sensitivity: "base" });
206
+ const groups = [];
207
+ const childToGroup = /* @__PURE__ */ new Set();
208
+ for (const param of parameters) {
209
+ if (param.type === "group") {
210
+ groups.push(param);
211
+ if (param.typeConfig?.childrenParams) {
212
+ param.typeConfig.childrenParams = [...param.typeConfig.childrenParams].sort(compare);
213
+ }
214
+ for (const childId of param.typeConfig?.childrenParams ?? []) {
215
+ childToGroup.add(childId.toLowerCase());
216
+ }
217
+ }
218
+ }
219
+ const ungrouped = parameters.filter(
220
+ (p) => p.type !== "group" && !childToGroup.has(p.id.toLowerCase())
221
+ );
222
+ const sortedGroups = [...groups].sort((a, b) => compare(a.id, b.id));
223
+ const result = [];
224
+ result.push(...[...ungrouped].sort((a, b) => compare(a.id, b.id)));
225
+ for (const group of sortedGroups) {
226
+ result.push(group);
227
+ for (const childId of group.typeConfig?.childrenParams ?? []) {
228
+ const child = parameters.find((p) => p.id.toLowerCase() === childId.toLowerCase());
229
+ if (child) {
230
+ result.push(child);
231
+ }
232
+ }
201
233
  }
202
234
  return result;
203
235
  }
@@ -550,7 +582,8 @@ var CompositionConverterService = class {
550
582
  contentTypesDir,
551
583
  entriesDir,
552
584
  compositionTypes,
553
- flattenComponentIds,
585
+ componentsToReferences,
586
+ componentsToBlocks,
554
587
  whatIf,
555
588
  strict
556
589
  } = options;
@@ -560,13 +593,17 @@ var CompositionConverterService = class {
560
593
  const entriesDirFull = this.fileSystem.resolvePath(rootDir, entriesDir);
561
594
  let contentTypesWritten = 0;
562
595
  let entriesFromCompositions = 0;
563
- let entriesFromFlattened = 0;
596
+ let entriesFromReferences = 0;
564
597
  let entriesReused = 0;
598
+ let blocksEmbedded = 0;
565
599
  this.logger.info(`Composition types: ${compositionTypes.join(", ")}`);
566
- if (flattenComponentIds.length > 0) {
567
- this.logger.info(`Flatten component types: ${flattenComponentIds.join(", ")}`);
600
+ if (componentsToReferences.length > 0) {
601
+ this.logger.info(`Components to references: ${componentsToReferences.join(", ")}`);
602
+ }
603
+ if (componentsToBlocks.length > 0) {
604
+ this.logger.info(`Components to blocks: ${componentsToBlocks.join(", ")}`);
568
605
  }
569
- const sourceItemMap = flattenComponentIds.length > 0 ? await this.buildSourceItemMap(entriesDirFull) : /* @__PURE__ */ new Map();
606
+ const sourceItemMap = componentsToReferences.length > 0 ? await this.buildSourceItemMap(entriesDirFull) : /* @__PURE__ */ new Map();
570
607
  if (sourceItemMap.size > 0) {
571
608
  this.logger.info(`Found ${sourceItemMap.size} existing entry(ies) with sourceItem values`);
572
609
  }
@@ -577,7 +614,7 @@ var CompositionConverterService = class {
577
614
  );
578
615
  if (compositionResults.length === 0) {
579
616
  this.logger.warn("No compositions found matching the specified types");
580
- return { contentTypesWritten: 0, entriesFromCompositions: 0, entriesFromFlattened: 0, entriesReused: 0 };
617
+ return { contentTypesWritten: 0, entriesFromCompositions: 0, entriesFromReferences: 0, entriesReused: 0, blocksEmbedded: 0 };
581
618
  }
582
619
  this.logger.info(`Found ${compositionResults.length} composition(s)`);
583
620
  const rootComponentTypes = /* @__PURE__ */ new Set();
@@ -594,28 +631,76 @@ var CompositionConverterService = class {
594
631
  const contentType = this.generateContentType(component);
595
632
  contentTypeMap.set(rootType, contentType);
596
633
  }
597
- const flattenContentTypeMap = /* @__PURE__ */ new Map();
598
- const missingFlattenTypes = [];
599
- const foundMissingFlattenTypes = /* @__PURE__ */ new Set();
600
- for (const flattenType of flattenComponentIds) {
634
+ const allTargetTypes = [.../* @__PURE__ */ new Set([...componentsToReferences, ...componentsToBlocks])];
635
+ const targetContentTypeMap = /* @__PURE__ */ new Map();
636
+ const missingTargetTypes = [];
637
+ const foundMissingTargetTypes = /* @__PURE__ */ new Set();
638
+ const blockTypeIdMap = /* @__PURE__ */ new Map();
639
+ for (const targetType of allTargetTypes) {
601
640
  const isRootType = [...rootComponentTypes].some(
602
- (rt) => this.compareTypes(rt, flattenType, strict)
641
+ (rt) => this.compareTypes(rt, targetType, strict)
603
642
  );
604
643
  if (isRootType) {
605
644
  continue;
606
645
  }
646
+ const isBlockType = componentsToBlocks.some(
647
+ (bt) => this.compareTypes(bt, targetType, strict)
648
+ );
649
+ const isRefType = componentsToReferences.some(
650
+ (rt) => this.compareTypes(rt, targetType, strict)
651
+ );
607
652
  try {
608
653
  const { component } = await this.componentService.loadComponent(
609
654
  componentsDirFull,
610
- flattenType,
655
+ targetType,
611
656
  { strict }
612
657
  );
613
- const contentType = this.generateContentType(component);
614
- flattenContentTypeMap.set(flattenType, contentType);
658
+ if (isRefType) {
659
+ const contentType = this.generateContentType(component);
660
+ targetContentTypeMap.set(targetType, contentType);
661
+ }
662
+ if (isBlockType) {
663
+ let blockId = targetType;
664
+ let needsRename = false;
665
+ if (isRefType) {
666
+ needsRename = true;
667
+ }
668
+ if (!needsRename) {
669
+ const existingPath = this.fileSystem.joinPath(contentTypesDirFull, `${targetType}.json`);
670
+ if (await this.fileSystem.fileExists(existingPath)) {
671
+ try {
672
+ const existing = await this.fileSystem.readFile(existingPath);
673
+ if (existing?.type !== "block") {
674
+ needsRename = true;
675
+ }
676
+ } catch {
677
+ }
678
+ }
679
+ }
680
+ if (needsRename) {
681
+ blockId = `${targetType}Block`;
682
+ this.logger.info(`Content type "${targetType}" already exists as non-block, using "${blockId}" for block`);
683
+ }
684
+ blockTypeIdMap.set(targetType, blockId);
685
+ const blockContentType = this.generateContentType(component);
686
+ blockContentType.type = "block";
687
+ blockContentType.id = blockId;
688
+ blockContentType.name = needsRename ? `${blockContentType.name} Block` : blockContentType.name;
689
+ targetContentTypeMap.set(blockId, blockContentType);
690
+ }
691
+ if (!isBlockType) {
692
+ if (!isRefType) {
693
+ const contentType = this.generateContentType(component);
694
+ targetContentTypeMap.set(targetType, contentType);
695
+ }
696
+ }
615
697
  } catch (error) {
616
698
  if (error instanceof ComponentNotFoundError) {
617
- this.logger.info(`Flatten component type not found: ${flattenType}`);
618
- missingFlattenTypes.push(flattenType);
699
+ this.logger.info(`Component type not found: ${targetType}`);
700
+ missingTargetTypes.push(targetType);
701
+ if (isBlockType) {
702
+ blockTypeIdMap.set(targetType, targetType);
703
+ }
619
704
  continue;
620
705
  }
621
706
  throw error;
@@ -627,48 +712,84 @@ var CompositionConverterService = class {
627
712
  const compositionName = comp._name ?? compositionId;
628
713
  const compositionType = comp.type;
629
714
  const entry = this.generateEntryFromComposition(composition);
630
- const flattenedByType = /* @__PURE__ */ new Map();
631
- if (flattenComponentIds.length > 0 && comp.slots) {
632
- for (const flattenType of flattenComponentIds) {
633
- if (this.compareTypes(flattenType, compositionType, strict)) {
715
+ const refsByType = /* @__PURE__ */ new Map();
716
+ if (componentsToReferences.length > 0 && comp.slots) {
717
+ for (const refType of componentsToReferences) {
718
+ if (this.compareTypes(refType, compositionType, strict)) {
634
719
  this.logger.warn(
635
- `Skipping flatten of "${flattenType}" \u2014 same as root component type`
720
+ `Skipping reference of "${refType}" \u2014 same as root component type`
636
721
  );
637
722
  continue;
638
723
  }
639
724
  const instances = this.findFlattenTargets(
640
725
  comp.slots,
641
- flattenType,
726
+ refType,
642
727
  compositionId,
643
728
  compositionName,
644
729
  strict
645
730
  );
646
731
  if (instances.length > 0) {
647
- flattenedByType.set(flattenType, instances);
648
- if (missingFlattenTypes.includes(flattenType)) {
649
- foundMissingFlattenTypes.add(flattenType);
732
+ refsByType.set(refType, instances);
733
+ if (missingTargetTypes.includes(refType)) {
734
+ foundMissingTargetTypes.add(refType);
650
735
  }
651
736
  }
652
737
  }
653
738
  }
654
739
  const resolvedRefIds = /* @__PURE__ */ new Map();
655
- for (const [flattenType, instances] of flattenedByType) {
740
+ for (const [refType, instances] of refsByType) {
656
741
  const refIds = [];
657
742
  for (const inst of instances) {
658
743
  const existingId = this.findExistingEntryBySourceItem(inst, sourceItemMap);
659
744
  refIds.push(existingId ?? inst.determinisiticId);
660
745
  }
661
- resolvedRefIds.set(flattenType, refIds);
746
+ resolvedRefIds.set(refType, refIds);
662
747
  }
663
- for (const [flattenType] of flattenedByType) {
664
- entry.entry.fields[flattenType] = {
748
+ for (const [refType] of refsByType) {
749
+ entry.entry.fields[refType] = {
665
750
  type: "contentReference",
666
- value: resolvedRefIds.get(flattenType)
751
+ value: resolvedRefIds.get(refType)
667
752
  };
668
753
  }
669
- if (flattenComponentIds.length > 0) {
754
+ if (componentsToReferences.length > 0) {
670
755
  this.transformContentReferences(entry);
671
756
  }
757
+ const blocksByType = /* @__PURE__ */ new Map();
758
+ if (componentsToBlocks.length > 0 && comp.slots) {
759
+ for (const blockType of componentsToBlocks) {
760
+ if (this.compareTypes(blockType, compositionType, strict)) {
761
+ this.logger.warn(
762
+ `Skipping block of "${blockType}" \u2014 same as root component type`
763
+ );
764
+ continue;
765
+ }
766
+ const instances = this.findFlattenTargets(
767
+ comp.slots,
768
+ blockType,
769
+ compositionId,
770
+ compositionName,
771
+ strict
772
+ );
773
+ if (instances.length > 0) {
774
+ blocksByType.set(blockType, instances);
775
+ if (missingTargetTypes.includes(blockType)) {
776
+ foundMissingTargetTypes.add(blockType);
777
+ }
778
+ }
779
+ }
780
+ }
781
+ for (const [blockType, instances] of blocksByType) {
782
+ const resolvedBlockId = blockTypeIdMap.get(blockType) ?? blockType;
783
+ const blockValues = instances.map((inst) => ({
784
+ type: resolvedBlockId,
785
+ fields: { ...inst.instance.parameters ?? {} }
786
+ }));
787
+ entry.entry.fields[resolvedBlockId] = {
788
+ type: "$block",
789
+ value: blockValues
790
+ };
791
+ blocksEmbedded += instances.length;
792
+ }
672
793
  const entryId = entry.entry._id;
673
794
  const entryFilePath = this.fileSystem.joinPath(entriesDirFull, `${entryId}.json`);
674
795
  this.logger.action(
@@ -680,7 +801,7 @@ var CompositionConverterService = class {
680
801
  await this.fileSystem.writeFile(entryFilePath, entry);
681
802
  }
682
803
  entriesFromCompositions++;
683
- for (const [flattenType, instances] of flattenedByType) {
804
+ for (const [refType, instances] of refsByType) {
684
805
  for (const inst of instances) {
685
806
  const existingId = this.findExistingEntryBySourceItem(inst, sourceItemMap);
686
807
  if (existingId) {
@@ -691,7 +812,7 @@ var CompositionConverterService = class {
691
812
  this.logger.action(
692
813
  whatIf,
693
814
  "UPDATE",
694
- `${entriesDir}/${existingId}.json (${flattenType}, merged fields from "${this.truncate(compositionName, 50)}")`
815
+ `${entriesDir}/${existingId}.json (${refType}, merged fields from "${this.truncate(compositionName, 50)}")`
695
816
  );
696
817
  if (!whatIf) {
697
818
  const existingEntry = await this.fileSystem.readFile(existingEntryPath);
@@ -715,53 +836,86 @@ var CompositionConverterService = class {
715
836
  this.logger.action(
716
837
  whatIf,
717
838
  "WRITE",
718
- `${entriesDir}/${inst.determinisiticId}.json (${flattenType} from "${this.truncate(compositionName, 50)}")`
839
+ `${entriesDir}/${inst.determinisiticId}.json (${refType} from "${this.truncate(compositionName, 50)}")`
719
840
  );
720
841
  if (!whatIf) {
721
842
  await this.fileSystem.writeFile(flatEntryPath, flatEntry);
722
843
  }
723
- entriesFromFlattened++;
844
+ entriesFromReferences++;
724
845
  }
725
846
  }
726
847
  }
727
- if (flattenComponentIds.length > 0) {
848
+ if (componentsToReferences.length > 0) {
728
849
  for (const contentType of contentTypeMap.values()) {
729
- for (const flattenType of flattenComponentIds) {
730
- if (this.compareTypes(flattenType, contentType.id, strict)) {
850
+ for (const refType of componentsToReferences) {
851
+ if (this.compareTypes(refType, contentType.id, strict)) {
731
852
  continue;
732
853
  }
733
- if (missingFlattenTypes.includes(flattenType) && !foundMissingFlattenTypes.has(flattenType)) {
854
+ if (missingTargetTypes.includes(refType) && !foundMissingTargetTypes.has(refType)) {
734
855
  continue;
735
856
  }
736
857
  contentType.fields.push({
737
- id: flattenType,
738
- name: flattenType,
858
+ id: refType,
859
+ name: refType,
739
860
  type: "contentReference",
740
861
  typeConfig: {
741
862
  isMulti: true,
742
- allowedContentTypes: [flattenType]
863
+ allowedContentTypes: [refType]
743
864
  },
744
865
  localizable: false
745
866
  });
746
867
  }
747
868
  }
748
869
  }
870
+ if (componentsToBlocks.length > 0) {
871
+ for (const contentType of contentTypeMap.values()) {
872
+ for (const blockType of componentsToBlocks) {
873
+ if (this.compareTypes(blockType, contentType.id, strict)) {
874
+ continue;
875
+ }
876
+ if (missingTargetTypes.includes(blockType) && !foundMissingTargetTypes.has(blockType)) {
877
+ continue;
878
+ }
879
+ const resolvedBlockId = blockTypeIdMap.get(blockType) ?? blockType;
880
+ contentType.fields.push({
881
+ id: resolvedBlockId,
882
+ name: resolvedBlockId,
883
+ type: "$block",
884
+ typeConfig: {
885
+ allowedContentTypes: [resolvedBlockId]
886
+ },
887
+ localizable: false
888
+ });
889
+ }
890
+ }
891
+ }
892
+ for (const contentType of contentTypeMap.values()) {
893
+ contentType.fields = this.componentService.sortParametersByGroup(contentType.fields);
894
+ }
895
+ for (const contentType of targetContentTypeMap.values()) {
896
+ contentType.fields = this.componentService.sortParametersByGroup(contentType.fields);
897
+ }
749
898
  for (const [typeName, contentType] of contentTypeMap) {
750
899
  const filePath = this.fileSystem.joinPath(contentTypesDirFull, `${typeName}.json`);
751
- const fieldCount = contentType.fields.filter((f) => f.type !== "contentReference").length;
900
+ const baseFieldCount = contentType.fields.filter((f) => f.type !== "contentReference" && f.type !== "$block").length;
752
901
  const refCount = contentType.fields.filter((f) => f.type === "contentReference").length;
753
- const refInfo = refCount > 0 ? ` + ${refCount} reference(s)` : "";
902
+ const blockCount = contentType.fields.filter((f) => f.type === "$block").length;
903
+ const extras = [
904
+ refCount > 0 ? `${refCount} reference(s)` : "",
905
+ blockCount > 0 ? `${blockCount} block(s)` : ""
906
+ ].filter(Boolean).join(", ");
907
+ const extrasInfo = extras ? ` + ${extras}` : "";
754
908
  this.logger.action(
755
909
  whatIf,
756
910
  "WRITE",
757
- `${contentTypesDir}/${typeName}.json (${fieldCount} fields${refInfo})`
911
+ `${contentTypesDir}/${typeName}.json (${baseFieldCount} fields${extrasInfo})`
758
912
  );
759
913
  if (!whatIf) {
760
914
  await this.fileSystem.writeFile(filePath, contentType);
761
915
  }
762
916
  contentTypesWritten++;
763
917
  }
764
- for (const [typeName, contentType] of flattenContentTypeMap) {
918
+ for (const [typeName, contentType] of targetContentTypeMap) {
765
919
  const filePath = this.fileSystem.joinPath(contentTypesDirFull, `${typeName}.json`);
766
920
  this.logger.action(
767
921
  whatIf,
@@ -773,15 +927,15 @@ var CompositionConverterService = class {
773
927
  }
774
928
  contentTypesWritten++;
775
929
  }
776
- const neverFoundMissingTypes = missingFlattenTypes.filter(
777
- (type) => !foundMissingFlattenTypes.has(type)
930
+ const neverFoundMissingTypes = missingTargetTypes.filter(
931
+ (type) => !foundMissingTargetTypes.has(type)
778
932
  );
779
933
  if (neverFoundMissingTypes.length > 0) {
780
934
  this.logger.warn(
781
- `Flatten component type(s) not found in any composition: ${neverFoundMissingTypes.join(", ")}`
935
+ `Component type(s) not found in any composition: ${neverFoundMissingTypes.join(", ")}`
782
936
  );
783
937
  }
784
- return { contentTypesWritten, entriesFromCompositions, entriesFromFlattened, entriesReused };
938
+ return { contentTypesWritten, entriesFromCompositions, entriesFromReferences, entriesReused, blocksEmbedded };
785
939
  }
786
940
  // --- Content Type Generation ---
787
941
  generateContentType(component) {