@uniformdev/transformer 1.1.36 → 1.1.37

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
@@ -148,6 +148,8 @@ interface ConvertCompositionsToEntriesOptions extends GlobalOptions {
148
148
  compositionTypes: string;
149
149
  componentsToReferences?: string;
150
150
  componentsToBlocks?: string;
151
+ slotsToReferences?: string;
152
+ slotsToBlocks?: string;
151
153
  }
152
154
  interface RemoveParameterOptions extends GlobalOptions {
153
155
  componentType: string;
@@ -461,6 +463,8 @@ interface ConvertCompositionsToEntriesInternalOptions {
461
463
  compositionTypes: string[];
462
464
  componentsToReferences: string[];
463
465
  componentsToBlocks: string[];
466
+ slotsToReferences: string[];
467
+ slotsToBlocks: string[];
464
468
  whatIf: boolean;
465
469
  strict: boolean;
466
470
  }
@@ -521,6 +525,7 @@ declare class CompositionConverterService {
521
525
  generateEntryFromFlattenedInstance(inst: FlattenedInstance): EntryDefinition;
522
526
  findFlattenTargets(slots: Record<string, ComponentInstance[]>, targetType: string, compositionId: string, compositionName: string, strict: boolean): FlattenedInstance[];
523
527
  private walkSlots;
528
+ findInstancesInSlot(slots: Record<string, ComponentInstance[]>, slotName: string, compositionId: string, compositionName: string, strict: boolean): FlattenedInstance[];
524
529
  private transformContentReferences;
525
530
  buildEntryIdMap(entriesDirFull: string): Promise<Map<string, string>>;
526
531
  buildSourceItemMap(entriesDirFull: string): Promise<Map<string, string>>;
@@ -528,6 +533,7 @@ declare class CompositionConverterService {
528
533
  private matchesType;
529
534
  private compareTypes;
530
535
  private expandWildcardTypes;
536
+ private expandWildcardSlots;
531
537
  private collectMatchingTypes;
532
538
  private truncate;
533
539
  private truncateName;
package/dist/index.js CHANGED
@@ -597,11 +597,15 @@ var CompositionConverterService = class {
597
597
  compositionTypes,
598
598
  componentsToReferences: rawComponentsToReferences,
599
599
  componentsToBlocks: rawComponentsToBlocks,
600
+ slotsToReferences: rawSlotsToReferences,
601
+ slotsToBlocks: rawSlotsToBlocks,
600
602
  whatIf,
601
603
  strict
602
604
  } = options;
603
605
  const initialComponentsToReferences = [...new Set(rawComponentsToReferences)];
604
606
  const initialComponentsToBlocks = [...new Set(rawComponentsToBlocks)];
607
+ const initialSlotsToReferences = [...new Set(rawSlotsToReferences)];
608
+ const initialSlotsToBlocks = [...new Set(rawSlotsToBlocks)];
605
609
  const compositionsDirFull = this.fileSystem.resolvePath(rootDir, compositionsDir);
606
610
  const componentsDirFull = this.fileSystem.resolvePath(rootDir, componentsDir);
607
611
  const contentTypesDirFull = this.fileSystem.resolvePath(rootDir, contentTypesDir);
@@ -618,7 +622,13 @@ var CompositionConverterService = class {
618
622
  if (initialComponentsToBlocks.length > 0) {
619
623
  this.logger.info(`Components to blocks: ${initialComponentsToBlocks.join(", ")}`);
620
624
  }
621
- const sourceItemMap = initialComponentsToReferences.length > 0 ? await this.buildSourceItemMap(entriesDirFull) : /* @__PURE__ */ new Map();
625
+ if (initialSlotsToReferences.length > 0) {
626
+ this.logger.info(`Slots to references: ${initialSlotsToReferences.join(", ")}`);
627
+ }
628
+ if (initialSlotsToBlocks.length > 0) {
629
+ this.logger.info(`Slots to blocks: ${initialSlotsToBlocks.join(", ")}`);
630
+ }
631
+ const sourceItemMap = initialComponentsToReferences.length > 0 || initialSlotsToReferences.length > 0 ? await this.buildSourceItemMap(entriesDirFull) : /* @__PURE__ */ new Map();
622
632
  if (sourceItemMap.size > 0) {
623
633
  this.logger.info(`Found ${sourceItemMap.size} existing entry(ies) with sourceItem values`);
624
634
  }
@@ -635,6 +645,8 @@ var CompositionConverterService = class {
635
645
  this.logger.info(`Found ${compositionResults.length} composition(s)`);
636
646
  const componentsToReferences = this.expandWildcardTypes(compositionResults, initialComponentsToReferences, strict);
637
647
  const componentsToBlocks = this.expandWildcardTypes(compositionResults, initialComponentsToBlocks, strict);
648
+ const slotsToReferences = this.expandWildcardSlots(compositionResults, initialSlotsToReferences, strict);
649
+ const slotsToBlocks = this.expandWildcardSlots(compositionResults, initialSlotsToBlocks, strict);
638
650
  const rootComponentTypes = /* @__PURE__ */ new Set();
639
651
  for (const { composition } of compositionResults) {
640
652
  rootComponentTypes.add(composition.composition.type);
@@ -735,6 +747,83 @@ var CompositionConverterService = class {
735
747
  throw error;
736
748
  }
737
749
  }
750
+ const slotToRefTypes = /* @__PURE__ */ new Map();
751
+ const slotToBlockTypes = /* @__PURE__ */ new Map();
752
+ for (const slotName of slotsToReferences) slotToRefTypes.set(slotName, /* @__PURE__ */ new Set());
753
+ for (const slotName of slotsToBlocks) slotToBlockTypes.set(slotName, /* @__PURE__ */ new Set());
754
+ for (const { composition: discoverComp } of compositionResults) {
755
+ const dc = discoverComp.composition;
756
+ if (!dc.slots) continue;
757
+ const dcName = dc._name ?? dc._id;
758
+ for (const slotName of slotsToReferences) {
759
+ const instances = this.findInstancesInSlot(dc.slots, slotName, dc._id, dcName, strict);
760
+ for (const inst of instances) {
761
+ if (!this.compareTypes(inst.componentType, dc.type, strict)) {
762
+ slotToRefTypes.get(slotName).add(inst.componentType);
763
+ }
764
+ }
765
+ }
766
+ for (const slotName of slotsToBlocks) {
767
+ const instances = this.findInstancesInSlot(dc.slots, slotName, dc._id, dcName, strict);
768
+ for (const inst of instances) {
769
+ if (!this.compareTypes(inst.componentType, dc.type, strict)) {
770
+ slotToBlockTypes.get(slotName).add(inst.componentType);
771
+ }
772
+ }
773
+ }
774
+ }
775
+ const allSlotRefTypes = /* @__PURE__ */ new Set();
776
+ for (const types of slotToRefTypes.values()) for (const t of types) allSlotRefTypes.add(t);
777
+ const allSlotBlockTypes = /* @__PURE__ */ new Set();
778
+ for (const types of slotToBlockTypes.values()) for (const t of types) allSlotBlockTypes.add(t);
779
+ const allSlotTargetTypes = /* @__PURE__ */ new Set([...allSlotRefTypes, ...allSlotBlockTypes]);
780
+ for (const targetType of allSlotTargetTypes) {
781
+ if (targetContentTypeMap.has(targetType) || missingTargetTypes.includes(targetType)) continue;
782
+ const isRootType = [...rootComponentTypes].some((rt) => this.compareTypes(rt, targetType, strict));
783
+ if (isRootType) continue;
784
+ const isSlotBlockType = allSlotBlockTypes.has(targetType);
785
+ const isSlotRefType = allSlotRefTypes.has(targetType);
786
+ try {
787
+ const { component } = await this.componentService.loadComponent(componentsDirFull, targetType, { strict });
788
+ if (isSlotRefType) {
789
+ const contentType = this.generateContentType(component);
790
+ targetContentTypeMap.set(targetType, contentType);
791
+ this.logger.debug(`Generated slot reference content type "${targetType}" with ${contentType.fields.length} field(s)`);
792
+ }
793
+ if (isSlotBlockType && !blockTypeIdMap.has(targetType)) {
794
+ let blockId = targetType;
795
+ let needsRename = isSlotRefType;
796
+ if (!needsRename) {
797
+ const existingPath = this.fileSystem.joinPath(contentTypesDirFull, `${targetType}.json`);
798
+ if (await this.fileSystem.fileExists(existingPath)) {
799
+ try {
800
+ const existing = await this.fileSystem.readFile(existingPath);
801
+ if (existing?.type !== "block") needsRename = true;
802
+ } catch {
803
+ }
804
+ }
805
+ }
806
+ if (needsRename) {
807
+ blockId = `${targetType}Block`;
808
+ this.logger.info(`Content type "${targetType}" already exists as non-block, using "${blockId}" for block`);
809
+ }
810
+ blockTypeIdMap.set(targetType, blockId);
811
+ const blockContentType = this.generateContentType(component);
812
+ blockContentType.type = "block";
813
+ blockContentType.id = blockId;
814
+ blockContentType.name = needsRename ? `${blockContentType.name} Block` : blockContentType.name;
815
+ targetContentTypeMap.set(blockId, blockContentType);
816
+ this.logger.debug(`Generated slot block content type "${blockId}" with ${blockContentType.fields.length} field(s)`);
817
+ }
818
+ } catch (error) {
819
+ if (error instanceof ComponentNotFoundError) {
820
+ this.logger.info(`Component type not found: ${targetType}`);
821
+ if (isSlotBlockType && !blockTypeIdMap.has(targetType)) blockTypeIdMap.set(targetType, targetType);
822
+ continue;
823
+ }
824
+ throw error;
825
+ }
826
+ }
738
827
  for (const { composition } of compositionResults) {
739
828
  const comp = composition.composition;
740
829
  const compositionId = comp._id;
@@ -800,7 +889,43 @@ var CompositionConverterService = class {
800
889
  value: resolvedRefIds.get(refType)
801
890
  };
802
891
  }
803
- if (componentsToReferences.length > 0) {
892
+ const refsBySlot = /* @__PURE__ */ new Map();
893
+ if (slotsToReferences.length > 0 && comp.slots) {
894
+ for (const slotName of slotsToReferences) {
895
+ const instances = this.findInstancesInSlot(
896
+ comp.slots,
897
+ slotName,
898
+ compositionId,
899
+ compositionName,
900
+ strict
901
+ );
902
+ const filtered = instances.filter((inst) => {
903
+ if (this.compareTypes(inst.componentType, compositionType, strict)) {
904
+ this.logger.warn(`Skipping reference of "${inst.componentType}" in slot "${slotName}" \u2014 same as root component type`);
905
+ return false;
906
+ }
907
+ return true;
908
+ });
909
+ this.logger.debug(`Composition "${compositionName}": found ${filtered.length} instance(s) in reference slot "${slotName}"`);
910
+ if (filtered.length > 0) refsBySlot.set(slotName, filtered);
911
+ }
912
+ }
913
+ const resolvedSlotRefIds = /* @__PURE__ */ new Map();
914
+ for (const [slotName, instances] of refsBySlot) {
915
+ const refIds = [];
916
+ for (const inst of instances) {
917
+ const existingId = this.findExistingEntryBySourceItem(inst, sourceItemMap);
918
+ refIds.push(existingId ?? inst.determinisiticId);
919
+ }
920
+ resolvedSlotRefIds.set(slotName, refIds);
921
+ }
922
+ for (const [slotName] of refsBySlot) {
923
+ entry.entry.fields[slotName] = {
924
+ type: "contentReference",
925
+ value: resolvedSlotRefIds.get(slotName)
926
+ };
927
+ }
928
+ if (componentsToReferences.length > 0 || slotsToReferences.length > 0) {
804
929
  this.transformContentReferences(entry);
805
930
  }
806
931
  const blocksByType = /* @__PURE__ */ new Map();
@@ -840,6 +965,35 @@ var CompositionConverterService = class {
840
965
  };
841
966
  blocksEmbedded += instances.length;
842
967
  }
968
+ const blocksBySlot = /* @__PURE__ */ new Map();
969
+ if (slotsToBlocks.length > 0 && comp.slots) {
970
+ for (const slotName of slotsToBlocks) {
971
+ const instances = this.findInstancesInSlot(
972
+ comp.slots,
973
+ slotName,
974
+ compositionId,
975
+ compositionName,
976
+ strict
977
+ );
978
+ const filtered = instances.filter((inst) => {
979
+ if (this.compareTypes(inst.componentType, compositionType, strict)) {
980
+ this.logger.warn(`Skipping block of "${inst.componentType}" in slot "${slotName}" \u2014 same as root component type`);
981
+ return false;
982
+ }
983
+ return true;
984
+ });
985
+ this.logger.debug(`Composition "${compositionName}": found ${filtered.length} instance(s) in block slot "${slotName}"`);
986
+ if (filtered.length > 0) blocksBySlot.set(slotName, filtered);
987
+ }
988
+ }
989
+ for (const [slotName, instances] of blocksBySlot) {
990
+ const blockValues = instances.map((inst) => ({
991
+ type: blockTypeIdMap.get(inst.componentType) ?? inst.componentType,
992
+ fields: { ...inst.instance.parameters ?? {} }
993
+ }));
994
+ entry.entry.fields[slotName] = { type: "$block", value: blockValues };
995
+ blocksEmbedded += instances.length;
996
+ }
843
997
  const entryId = entry.entry._id;
844
998
  if (isExistingEntry) {
845
999
  this.logger.action(
@@ -908,6 +1062,42 @@ var CompositionConverterService = class {
908
1062
  entriesFromReferences++;
909
1063
  }
910
1064
  }
1065
+ for (const [, instances] of refsBySlot) {
1066
+ for (const inst of instances) {
1067
+ const existingId = this.findExistingEntryBySourceItem(inst, sourceItemMap);
1068
+ if (existingId) {
1069
+ const existingSlotEntryPath = this.fileSystem.joinPath(entriesDirFull, `${existingId}.json`);
1070
+ this.logger.action(
1071
+ whatIf,
1072
+ "UPDATE",
1073
+ `${entriesDir}/${existingId}.json (${inst.componentType}, merged fields from "${this.truncate(compositionName, 50)}")`
1074
+ );
1075
+ if (!whatIf) {
1076
+ const existingEntry = await this.fileSystem.readFile(existingSlotEntryPath);
1077
+ if (existingEntry?.entry) {
1078
+ existingEntry.entry.fields = {
1079
+ ...existingEntry.entry.fields,
1080
+ ...inst.instance.parameters ?? {}
1081
+ };
1082
+ await this.fileSystem.writeFile(existingSlotEntryPath, existingEntry);
1083
+ }
1084
+ }
1085
+ entriesReused++;
1086
+ continue;
1087
+ }
1088
+ const flatEntry = this.generateEntryFromFlattenedInstance(inst);
1089
+ const flatEntryPath = this.fileSystem.joinPath(entriesDirFull, `${inst.determinisiticId}.json`);
1090
+ this.logger.action(
1091
+ whatIf,
1092
+ "WRITE",
1093
+ `${entriesDir}/${inst.determinisiticId}.json (${inst.componentType} from "${this.truncate(compositionName, 50)}")`
1094
+ );
1095
+ if (!whatIf) {
1096
+ await this.fileSystem.writeFile(flatEntryPath, flatEntry);
1097
+ }
1098
+ entriesFromReferences++;
1099
+ }
1100
+ }
911
1101
  }
912
1102
  if (componentsToReferences.length > 0) {
913
1103
  for (const contentType of contentTypeMap.values()) {
@@ -955,6 +1145,42 @@ var CompositionConverterService = class {
955
1145
  }
956
1146
  }
957
1147
  }
1148
+ if (slotsToReferences.length > 0) {
1149
+ for (const contentType of contentTypeMap.values()) {
1150
+ for (const slotName of slotsToReferences) {
1151
+ const typesInSlot = slotToRefTypes.get(slotName) ?? /* @__PURE__ */ new Set();
1152
+ const allowedTypes = [...typesInSlot].filter(
1153
+ (t) => !this.compareTypes(t, contentType.id, strict)
1154
+ );
1155
+ if (allowedTypes.length === 0) continue;
1156
+ contentType.fields.push({
1157
+ id: slotName,
1158
+ name: slotName,
1159
+ type: "contentReference",
1160
+ typeConfig: { isMulti: true, allowedTypes },
1161
+ localizable: false
1162
+ });
1163
+ this.logger.debug(`Field "${slotName}" (contentReference, allowedTypes: ${allowedTypes.join(", ")}) added to content type "${contentType.id}"`);
1164
+ }
1165
+ }
1166
+ }
1167
+ if (slotsToBlocks.length > 0) {
1168
+ for (const contentType of contentTypeMap.values()) {
1169
+ for (const slotName of slotsToBlocks) {
1170
+ const typesInSlot = slotToBlockTypes.get(slotName) ?? /* @__PURE__ */ new Set();
1171
+ const resolvedBlockIds = [...typesInSlot].filter((t) => !this.compareTypes(t, contentType.id, strict)).map((t) => blockTypeIdMap.get(t) ?? t);
1172
+ if (resolvedBlockIds.length === 0) continue;
1173
+ contentType.fields.push({
1174
+ id: slotName,
1175
+ name: slotName,
1176
+ type: "$block",
1177
+ typeConfig: { allowedTypes: resolvedBlockIds },
1178
+ localizable: false
1179
+ });
1180
+ this.logger.debug(`Field "${slotName}" ($block, allowedTypes: ${resolvedBlockIds.join(", ")}) added to content type "${contentType.id}"`);
1181
+ }
1182
+ }
1183
+ }
958
1184
  for (const contentType of contentTypeMap.values()) {
959
1185
  contentType.fields = this.componentService.sortParametersByGroup(contentType.fields);
960
1186
  }
@@ -1121,6 +1347,29 @@ var CompositionConverterService = class {
1121
1347
  }
1122
1348
  }
1123
1349
  }
1350
+ // --- Slot-Based Instance Finding ---
1351
+ findInstancesInSlot(slots, slotName, compositionId, compositionName, strict) {
1352
+ const results = [];
1353
+ for (const [name, instances] of Object.entries(slots)) {
1354
+ const matches = strict ? name === slotName : name.toLowerCase() === slotName.toLowerCase();
1355
+ if (!matches) continue;
1356
+ if (!Array.isArray(instances)) continue;
1357
+ for (let i = 0; i < instances.length; i++) {
1358
+ const instance = instances[i];
1359
+ if (instance._pattern) continue;
1360
+ const path2 = `${compositionId}-${name}-[${i}]-${instance.type}`;
1361
+ results.push({
1362
+ instance,
1363
+ path: path2,
1364
+ determinisiticId: computeGuidHash(path2),
1365
+ componentType: instance.type,
1366
+ compositionId,
1367
+ compositionName
1368
+ });
1369
+ }
1370
+ }
1371
+ return results;
1372
+ }
1124
1373
  // --- Content Reference Transformation ---
1125
1374
  transformContentReferences(entry) {
1126
1375
  const dataResources = {};
@@ -1223,6 +1472,34 @@ var CompositionConverterService = class {
1223
1472
  }
1224
1473
  return [...new Set(expanded)];
1225
1474
  }
1475
+ expandWildcardSlots(compositionResults, patterns, strict) {
1476
+ const expanded = [];
1477
+ for (const pattern of patterns) {
1478
+ if (!pattern.includes("*")) {
1479
+ expanded.push(pattern);
1480
+ continue;
1481
+ }
1482
+ const matched = /* @__PURE__ */ new Set();
1483
+ for (const { composition } of compositionResults) {
1484
+ if (composition.composition.slots) {
1485
+ for (const slotName of Object.keys(composition.composition.slots)) {
1486
+ if (this.matchesType(slotName, pattern, strict)) {
1487
+ matched.add(slotName);
1488
+ }
1489
+ }
1490
+ }
1491
+ }
1492
+ if (matched.size === 0) {
1493
+ this.logger.warn(`Wildcard pattern "${pattern}" did not match any slot names`);
1494
+ } else {
1495
+ this.logger.info(`Wildcard "${pattern}" expanded to: ${[...matched].join(", ")}`);
1496
+ }
1497
+ for (const name of matched) {
1498
+ expanded.push(name);
1499
+ }
1500
+ }
1501
+ return [...new Set(expanded)];
1502
+ }
1226
1503
  collectMatchingTypes(slots, pattern, strict, matched) {
1227
1504
  for (const instances of Object.values(slots)) {
1228
1505
  if (!Array.isArray(instances)) continue;