@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/cli/index.js CHANGED
@@ -607,11 +607,15 @@ var CompositionConverterService = class {
607
607
  compositionTypes,
608
608
  componentsToReferences: rawComponentsToReferences,
609
609
  componentsToBlocks: rawComponentsToBlocks,
610
+ slotsToReferences: rawSlotsToReferences,
611
+ slotsToBlocks: rawSlotsToBlocks,
610
612
  whatIf,
611
613
  strict
612
614
  } = options;
613
615
  const initialComponentsToReferences = [...new Set(rawComponentsToReferences)];
614
616
  const initialComponentsToBlocks = [...new Set(rawComponentsToBlocks)];
617
+ const initialSlotsToReferences = [...new Set(rawSlotsToReferences)];
618
+ const initialSlotsToBlocks = [...new Set(rawSlotsToBlocks)];
615
619
  const compositionsDirFull = this.fileSystem.resolvePath(rootDir, compositionsDir);
616
620
  const componentsDirFull = this.fileSystem.resolvePath(rootDir, componentsDir);
617
621
  const contentTypesDirFull = this.fileSystem.resolvePath(rootDir, contentTypesDir);
@@ -628,7 +632,13 @@ var CompositionConverterService = class {
628
632
  if (initialComponentsToBlocks.length > 0) {
629
633
  this.logger.info(`Components to blocks: ${initialComponentsToBlocks.join(", ")}`);
630
634
  }
631
- const sourceItemMap = initialComponentsToReferences.length > 0 ? await this.buildSourceItemMap(entriesDirFull) : /* @__PURE__ */ new Map();
635
+ if (initialSlotsToReferences.length > 0) {
636
+ this.logger.info(`Slots to references: ${initialSlotsToReferences.join(", ")}`);
637
+ }
638
+ if (initialSlotsToBlocks.length > 0) {
639
+ this.logger.info(`Slots to blocks: ${initialSlotsToBlocks.join(", ")}`);
640
+ }
641
+ const sourceItemMap = initialComponentsToReferences.length > 0 || initialSlotsToReferences.length > 0 ? await this.buildSourceItemMap(entriesDirFull) : /* @__PURE__ */ new Map();
632
642
  if (sourceItemMap.size > 0) {
633
643
  this.logger.info(`Found ${sourceItemMap.size} existing entry(ies) with sourceItem values`);
634
644
  }
@@ -645,6 +655,8 @@ var CompositionConverterService = class {
645
655
  this.logger.info(`Found ${compositionResults.length} composition(s)`);
646
656
  const componentsToReferences = this.expandWildcardTypes(compositionResults, initialComponentsToReferences, strict);
647
657
  const componentsToBlocks = this.expandWildcardTypes(compositionResults, initialComponentsToBlocks, strict);
658
+ const slotsToReferences = this.expandWildcardSlots(compositionResults, initialSlotsToReferences, strict);
659
+ const slotsToBlocks = this.expandWildcardSlots(compositionResults, initialSlotsToBlocks, strict);
648
660
  const rootComponentTypes = /* @__PURE__ */ new Set();
649
661
  for (const { composition } of compositionResults) {
650
662
  rootComponentTypes.add(composition.composition.type);
@@ -745,6 +757,83 @@ var CompositionConverterService = class {
745
757
  throw error;
746
758
  }
747
759
  }
760
+ const slotToRefTypes = /* @__PURE__ */ new Map();
761
+ const slotToBlockTypes = /* @__PURE__ */ new Map();
762
+ for (const slotName of slotsToReferences) slotToRefTypes.set(slotName, /* @__PURE__ */ new Set());
763
+ for (const slotName of slotsToBlocks) slotToBlockTypes.set(slotName, /* @__PURE__ */ new Set());
764
+ for (const { composition: discoverComp } of compositionResults) {
765
+ const dc = discoverComp.composition;
766
+ if (!dc.slots) continue;
767
+ const dcName = dc._name ?? dc._id;
768
+ for (const slotName of slotsToReferences) {
769
+ const instances = this.findInstancesInSlot(dc.slots, slotName, dc._id, dcName, strict);
770
+ for (const inst of instances) {
771
+ if (!this.compareTypes(inst.componentType, dc.type, strict)) {
772
+ slotToRefTypes.get(slotName).add(inst.componentType);
773
+ }
774
+ }
775
+ }
776
+ for (const slotName of slotsToBlocks) {
777
+ const instances = this.findInstancesInSlot(dc.slots, slotName, dc._id, dcName, strict);
778
+ for (const inst of instances) {
779
+ if (!this.compareTypes(inst.componentType, dc.type, strict)) {
780
+ slotToBlockTypes.get(slotName).add(inst.componentType);
781
+ }
782
+ }
783
+ }
784
+ }
785
+ const allSlotRefTypes = /* @__PURE__ */ new Set();
786
+ for (const types of slotToRefTypes.values()) for (const t of types) allSlotRefTypes.add(t);
787
+ const allSlotBlockTypes = /* @__PURE__ */ new Set();
788
+ for (const types of slotToBlockTypes.values()) for (const t of types) allSlotBlockTypes.add(t);
789
+ const allSlotTargetTypes = /* @__PURE__ */ new Set([...allSlotRefTypes, ...allSlotBlockTypes]);
790
+ for (const targetType of allSlotTargetTypes) {
791
+ if (targetContentTypeMap.has(targetType) || missingTargetTypes.includes(targetType)) continue;
792
+ const isRootType = [...rootComponentTypes].some((rt) => this.compareTypes(rt, targetType, strict));
793
+ if (isRootType) continue;
794
+ const isSlotBlockType = allSlotBlockTypes.has(targetType);
795
+ const isSlotRefType = allSlotRefTypes.has(targetType);
796
+ try {
797
+ const { component } = await this.componentService.loadComponent(componentsDirFull, targetType, { strict });
798
+ if (isSlotRefType) {
799
+ const contentType = this.generateContentType(component);
800
+ targetContentTypeMap.set(targetType, contentType);
801
+ this.logger.debug(`Generated slot reference content type "${targetType}" with ${contentType.fields.length} field(s)`);
802
+ }
803
+ if (isSlotBlockType && !blockTypeIdMap.has(targetType)) {
804
+ let blockId = targetType;
805
+ let needsRename = isSlotRefType;
806
+ if (!needsRename) {
807
+ const existingPath = this.fileSystem.joinPath(contentTypesDirFull, `${targetType}.json`);
808
+ if (await this.fileSystem.fileExists(existingPath)) {
809
+ try {
810
+ const existing = await this.fileSystem.readFile(existingPath);
811
+ if (existing?.type !== "block") needsRename = true;
812
+ } catch {
813
+ }
814
+ }
815
+ }
816
+ if (needsRename) {
817
+ blockId = `${targetType}Block`;
818
+ this.logger.info(`Content type "${targetType}" already exists as non-block, using "${blockId}" for block`);
819
+ }
820
+ blockTypeIdMap.set(targetType, blockId);
821
+ const blockContentType = this.generateContentType(component);
822
+ blockContentType.type = "block";
823
+ blockContentType.id = blockId;
824
+ blockContentType.name = needsRename ? `${blockContentType.name} Block` : blockContentType.name;
825
+ targetContentTypeMap.set(blockId, blockContentType);
826
+ this.logger.debug(`Generated slot block content type "${blockId}" with ${blockContentType.fields.length} field(s)`);
827
+ }
828
+ } catch (error) {
829
+ if (error instanceof ComponentNotFoundError) {
830
+ this.logger.info(`Component type not found: ${targetType}`);
831
+ if (isSlotBlockType && !blockTypeIdMap.has(targetType)) blockTypeIdMap.set(targetType, targetType);
832
+ continue;
833
+ }
834
+ throw error;
835
+ }
836
+ }
748
837
  for (const { composition } of compositionResults) {
749
838
  const comp = composition.composition;
750
839
  const compositionId = comp._id;
@@ -810,7 +899,43 @@ var CompositionConverterService = class {
810
899
  value: resolvedRefIds.get(refType)
811
900
  };
812
901
  }
813
- if (componentsToReferences.length > 0) {
902
+ const refsBySlot = /* @__PURE__ */ new Map();
903
+ if (slotsToReferences.length > 0 && comp.slots) {
904
+ for (const slotName of slotsToReferences) {
905
+ const instances = this.findInstancesInSlot(
906
+ comp.slots,
907
+ slotName,
908
+ compositionId,
909
+ compositionName,
910
+ strict
911
+ );
912
+ const filtered = instances.filter((inst) => {
913
+ if (this.compareTypes(inst.componentType, compositionType, strict)) {
914
+ this.logger.warn(`Skipping reference of "${inst.componentType}" in slot "${slotName}" \u2014 same as root component type`);
915
+ return false;
916
+ }
917
+ return true;
918
+ });
919
+ this.logger.debug(`Composition "${compositionName}": found ${filtered.length} instance(s) in reference slot "${slotName}"`);
920
+ if (filtered.length > 0) refsBySlot.set(slotName, filtered);
921
+ }
922
+ }
923
+ const resolvedSlotRefIds = /* @__PURE__ */ new Map();
924
+ for (const [slotName, instances] of refsBySlot) {
925
+ const refIds = [];
926
+ for (const inst of instances) {
927
+ const existingId = this.findExistingEntryBySourceItem(inst, sourceItemMap);
928
+ refIds.push(existingId ?? inst.determinisiticId);
929
+ }
930
+ resolvedSlotRefIds.set(slotName, refIds);
931
+ }
932
+ for (const [slotName] of refsBySlot) {
933
+ entry.entry.fields[slotName] = {
934
+ type: "contentReference",
935
+ value: resolvedSlotRefIds.get(slotName)
936
+ };
937
+ }
938
+ if (componentsToReferences.length > 0 || slotsToReferences.length > 0) {
814
939
  this.transformContentReferences(entry);
815
940
  }
816
941
  const blocksByType = /* @__PURE__ */ new Map();
@@ -850,6 +975,35 @@ var CompositionConverterService = class {
850
975
  };
851
976
  blocksEmbedded += instances.length;
852
977
  }
978
+ const blocksBySlot = /* @__PURE__ */ new Map();
979
+ if (slotsToBlocks.length > 0 && comp.slots) {
980
+ for (const slotName of slotsToBlocks) {
981
+ const instances = this.findInstancesInSlot(
982
+ comp.slots,
983
+ slotName,
984
+ compositionId,
985
+ compositionName,
986
+ strict
987
+ );
988
+ const filtered = instances.filter((inst) => {
989
+ if (this.compareTypes(inst.componentType, compositionType, strict)) {
990
+ this.logger.warn(`Skipping block of "${inst.componentType}" in slot "${slotName}" \u2014 same as root component type`);
991
+ return false;
992
+ }
993
+ return true;
994
+ });
995
+ this.logger.debug(`Composition "${compositionName}": found ${filtered.length} instance(s) in block slot "${slotName}"`);
996
+ if (filtered.length > 0) blocksBySlot.set(slotName, filtered);
997
+ }
998
+ }
999
+ for (const [slotName, instances] of blocksBySlot) {
1000
+ const blockValues = instances.map((inst) => ({
1001
+ type: blockTypeIdMap.get(inst.componentType) ?? inst.componentType,
1002
+ fields: { ...inst.instance.parameters ?? {} }
1003
+ }));
1004
+ entry.entry.fields[slotName] = { type: "$block", value: blockValues };
1005
+ blocksEmbedded += instances.length;
1006
+ }
853
1007
  const entryId = entry.entry._id;
854
1008
  if (isExistingEntry) {
855
1009
  this.logger.action(
@@ -918,6 +1072,42 @@ var CompositionConverterService = class {
918
1072
  entriesFromReferences++;
919
1073
  }
920
1074
  }
1075
+ for (const [, instances] of refsBySlot) {
1076
+ for (const inst of instances) {
1077
+ const existingId = this.findExistingEntryBySourceItem(inst, sourceItemMap);
1078
+ if (existingId) {
1079
+ const existingSlotEntryPath = this.fileSystem.joinPath(entriesDirFull, `${existingId}.json`);
1080
+ this.logger.action(
1081
+ whatIf,
1082
+ "UPDATE",
1083
+ `${entriesDir}/${existingId}.json (${inst.componentType}, merged fields from "${this.truncate(compositionName, 50)}")`
1084
+ );
1085
+ if (!whatIf) {
1086
+ const existingEntry = await this.fileSystem.readFile(existingSlotEntryPath);
1087
+ if (existingEntry?.entry) {
1088
+ existingEntry.entry.fields = {
1089
+ ...existingEntry.entry.fields,
1090
+ ...inst.instance.parameters ?? {}
1091
+ };
1092
+ await this.fileSystem.writeFile(existingSlotEntryPath, existingEntry);
1093
+ }
1094
+ }
1095
+ entriesReused++;
1096
+ continue;
1097
+ }
1098
+ const flatEntry = this.generateEntryFromFlattenedInstance(inst);
1099
+ const flatEntryPath = this.fileSystem.joinPath(entriesDirFull, `${inst.determinisiticId}.json`);
1100
+ this.logger.action(
1101
+ whatIf,
1102
+ "WRITE",
1103
+ `${entriesDir}/${inst.determinisiticId}.json (${inst.componentType} from "${this.truncate(compositionName, 50)}")`
1104
+ );
1105
+ if (!whatIf) {
1106
+ await this.fileSystem.writeFile(flatEntryPath, flatEntry);
1107
+ }
1108
+ entriesFromReferences++;
1109
+ }
1110
+ }
921
1111
  }
922
1112
  if (componentsToReferences.length > 0) {
923
1113
  for (const contentType of contentTypeMap.values()) {
@@ -965,6 +1155,42 @@ var CompositionConverterService = class {
965
1155
  }
966
1156
  }
967
1157
  }
1158
+ if (slotsToReferences.length > 0) {
1159
+ for (const contentType of contentTypeMap.values()) {
1160
+ for (const slotName of slotsToReferences) {
1161
+ const typesInSlot = slotToRefTypes.get(slotName) ?? /* @__PURE__ */ new Set();
1162
+ const allowedTypes = [...typesInSlot].filter(
1163
+ (t) => !this.compareTypes(t, contentType.id, strict)
1164
+ );
1165
+ if (allowedTypes.length === 0) continue;
1166
+ contentType.fields.push({
1167
+ id: slotName,
1168
+ name: slotName,
1169
+ type: "contentReference",
1170
+ typeConfig: { isMulti: true, allowedTypes },
1171
+ localizable: false
1172
+ });
1173
+ this.logger.debug(`Field "${slotName}" (contentReference, allowedTypes: ${allowedTypes.join(", ")}) added to content type "${contentType.id}"`);
1174
+ }
1175
+ }
1176
+ }
1177
+ if (slotsToBlocks.length > 0) {
1178
+ for (const contentType of contentTypeMap.values()) {
1179
+ for (const slotName of slotsToBlocks) {
1180
+ const typesInSlot = slotToBlockTypes.get(slotName) ?? /* @__PURE__ */ new Set();
1181
+ const resolvedBlockIds = [...typesInSlot].filter((t) => !this.compareTypes(t, contentType.id, strict)).map((t) => blockTypeIdMap.get(t) ?? t);
1182
+ if (resolvedBlockIds.length === 0) continue;
1183
+ contentType.fields.push({
1184
+ id: slotName,
1185
+ name: slotName,
1186
+ type: "$block",
1187
+ typeConfig: { allowedTypes: resolvedBlockIds },
1188
+ localizable: false
1189
+ });
1190
+ this.logger.debug(`Field "${slotName}" ($block, allowedTypes: ${resolvedBlockIds.join(", ")}) added to content type "${contentType.id}"`);
1191
+ }
1192
+ }
1193
+ }
968
1194
  for (const contentType of contentTypeMap.values()) {
969
1195
  contentType.fields = this.componentService.sortParametersByGroup(contentType.fields);
970
1196
  }
@@ -1131,6 +1357,29 @@ var CompositionConverterService = class {
1131
1357
  }
1132
1358
  }
1133
1359
  }
1360
+ // --- Slot-Based Instance Finding ---
1361
+ findInstancesInSlot(slots, slotName, compositionId, compositionName, strict) {
1362
+ const results = [];
1363
+ for (const [name, instances] of Object.entries(slots)) {
1364
+ const matches = strict ? name === slotName : name.toLowerCase() === slotName.toLowerCase();
1365
+ if (!matches) continue;
1366
+ if (!Array.isArray(instances)) continue;
1367
+ for (let i = 0; i < instances.length; i++) {
1368
+ const instance = instances[i];
1369
+ if (instance._pattern) continue;
1370
+ const path2 = `${compositionId}-${name}-[${i}]-${instance.type}`;
1371
+ results.push({
1372
+ instance,
1373
+ path: path2,
1374
+ determinisiticId: computeGuidHash(path2),
1375
+ componentType: instance.type,
1376
+ compositionId,
1377
+ compositionName
1378
+ });
1379
+ }
1380
+ }
1381
+ return results;
1382
+ }
1134
1383
  // --- Content Reference Transformation ---
1135
1384
  transformContentReferences(entry) {
1136
1385
  const dataResources = {};
@@ -1233,6 +1482,34 @@ var CompositionConverterService = class {
1233
1482
  }
1234
1483
  return [...new Set(expanded)];
1235
1484
  }
1485
+ expandWildcardSlots(compositionResults, patterns, strict) {
1486
+ const expanded = [];
1487
+ for (const pattern of patterns) {
1488
+ if (!pattern.includes("*")) {
1489
+ expanded.push(pattern);
1490
+ continue;
1491
+ }
1492
+ const matched = /* @__PURE__ */ new Set();
1493
+ for (const { composition } of compositionResults) {
1494
+ if (composition.composition.slots) {
1495
+ for (const slotName of Object.keys(composition.composition.slots)) {
1496
+ if (this.matchesType(slotName, pattern, strict)) {
1497
+ matched.add(slotName);
1498
+ }
1499
+ }
1500
+ }
1501
+ }
1502
+ if (matched.size === 0) {
1503
+ this.logger.warn(`Wildcard pattern "${pattern}" did not match any slot names`);
1504
+ } else {
1505
+ this.logger.info(`Wildcard "${pattern}" expanded to: ${[...matched].join(", ")}`);
1506
+ }
1507
+ for (const name of matched) {
1508
+ expanded.push(name);
1509
+ }
1510
+ }
1511
+ return [...new Set(expanded)];
1512
+ }
1236
1513
  collectMatchingTypes(slots, pattern, strict, matched) {
1237
1514
  for (const instances of Object.values(slots)) {
1238
1515
  if (!Array.isArray(instances)) continue;
@@ -4488,6 +4765,12 @@ function createConvertCompositionsToEntriesCommand() {
4488
4765
  ).option(
4489
4766
  "--componentsToBlocks <types>",
4490
4767
  "Pipe-separated list of component types to convert into inline blocks (e.g., DetailHero|ArticleDetail)"
4768
+ ).option(
4769
+ "--slotsToReferences <slots>",
4770
+ "Pipe-separated list of slot names whose instances should be converted into separate referenced entries (e.g., main|sidebar)"
4771
+ ).option(
4772
+ "--slotsToBlocks <slots>",
4773
+ "Pipe-separated list of slot names whose instances should be converted into inline blocks (e.g., main|sidebar)"
4491
4774
  ).option("--verbose", "Enable verbose output with detailed progress information").hook("preAction", (thisCommand) => {
4492
4775
  const opts = thisCommand.opts();
4493
4776
  const requiredOptions = [
@@ -4504,7 +4787,9 @@ function createConvertCompositionsToEntriesCommand() {
4504
4787
  ...globalOpts,
4505
4788
  compositionTypes: opts.compositionTypes,
4506
4789
  componentsToReferences: opts.componentsToReferences,
4507
- componentsToBlocks: opts.componentsToBlocks
4790
+ componentsToBlocks: opts.componentsToBlocks,
4791
+ slotsToReferences: opts.slotsToReferences,
4792
+ slotsToBlocks: opts.slotsToBlocks
4508
4793
  };
4509
4794
  const logger = new Logger(opts.verbose ?? false);
4510
4795
  const fileSystem = new FileSystemService();
@@ -4521,6 +4806,8 @@ function createConvertCompositionsToEntriesCommand() {
4521
4806
  const parsePipeSeparated = (value) => value ? [...new Set(value.split("|").map((t) => t.trim()).filter((t) => t.length > 0))] : [];
4522
4807
  const componentsToReferences = parsePipeSeparated(options.componentsToReferences);
4523
4808
  const componentsToBlocks = parsePipeSeparated(options.componentsToBlocks);
4809
+ const slotsToReferences = parsePipeSeparated(options.slotsToReferences);
4810
+ const slotsToBlocks = parsePipeSeparated(options.slotsToBlocks);
4524
4811
  const result = await converter.convert({
4525
4812
  rootDir: options.rootDir,
4526
4813
  compositionsDir: options.compositionsDir,
@@ -4530,6 +4817,8 @@ function createConvertCompositionsToEntriesCommand() {
4530
4817
  compositionTypes,
4531
4818
  componentsToReferences,
4532
4819
  componentsToBlocks,
4820
+ slotsToReferences,
4821
+ slotsToBlocks,
4533
4822
  whatIf: options.whatIf ?? false,
4534
4823
  strict: options.strict ?? false
4535
4824
  });
@@ -6074,7 +6363,7 @@ function createRemoveOrphanEntriesCommand() {
6074
6363
  // package.json
6075
6364
  var package_default = {
6076
6365
  name: "@uniformdev/transformer",
6077
- version: "1.1.36",
6366
+ version: "1.1.37",
6078
6367
  description: "CLI tool for transforming Uniform.dev serialization files offline",
6079
6368
  type: "module",
6080
6369
  bin: {