@uniformdev/cli 20.79.1 → 20.80.0

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.
@@ -21,7 +21,7 @@ import { dirname, extname, isAbsolute, resolve, sep } from "path";
21
21
  // package.json
22
22
  var package_default = {
23
23
  name: "@uniformdev/cli",
24
- version: "20.79.1",
24
+ version: "20.80.0",
25
25
  description: "Uniform command line interface tool",
26
26
  license: "SEE LICENSE IN LICENSE.txt",
27
27
  main: "./cli.js",
@@ -409,23 +409,41 @@ function readFileToObject(filename) {
409
409
  const file = readFileSync(filename, "utf8");
410
410
  return load(file, { filename, json: true });
411
411
  }
412
+ var ENTITY_ID_CHUNK_SIZE = 100;
413
+ function* chunkEntityIds(ids, chunkSize = ENTITY_ID_CHUNK_SIZE) {
414
+ if (!ids) {
415
+ yield void 0;
416
+ return;
417
+ }
418
+ for (let index = 0; index < ids.length; index += chunkSize) {
419
+ yield ids.slice(index, index + chunkSize);
420
+ }
421
+ }
412
422
  async function* paginateAsync(fetchPage, options) {
413
423
  const pageSize = options.pageSize ?? 100;
414
424
  if (pageSize < 1) {
415
425
  throw new Error(`pageSize must be at least 1, got ${pageSize}`);
416
426
  }
427
+ const { maxItems } = options;
417
428
  let offset = 0;
429
+ let yielded = 0;
430
+ let limit = pageSize;
418
431
  let pageData = [];
419
432
  do {
433
+ limit = maxItems === void 0 ? pageSize : Math.min(pageSize, maxItems - yielded);
434
+ if (limit < 1) {
435
+ return;
436
+ }
420
437
  if (options.verbose) {
421
- console.log(`Fetching ${options.entityName ?? "items"} batch: offset=${offset}, pageSize=${pageSize}`);
438
+ console.log(`Fetching ${options.entityName ?? "items"} batch: offset=${offset}, pageSize=${limit}`);
422
439
  }
423
- pageData = await fetchPage(offset, pageSize);
440
+ pageData = await fetchPage(offset, limit);
424
441
  for (const item of pageData) {
425
442
  yield item;
426
443
  }
427
- offset += pageSize;
428
- } while (pageData.length === pageSize);
444
+ yielded += pageData.length;
445
+ offset += limit;
446
+ } while (pageData.length === limit);
429
447
  }
430
448
  var entityBatchSizeDefaults = {
431
449
  composition: 100,
@@ -461,6 +479,21 @@ function getEntityBatchSize(entityType, config) {
461
479
  }
462
480
  return entityBatchSizeDefaults[entityType];
463
481
  }
482
+ function getPublishScope(entityType, config) {
483
+ const publish = config.entitiesConfig?.[entityType]?.publish;
484
+ if (!publish) {
485
+ return void 0;
486
+ }
487
+ if (publish === true || publish === "all") {
488
+ return "all";
489
+ }
490
+ if (publish === "pushed") {
491
+ return "pushed";
492
+ }
493
+ throw new Error(
494
+ `Invalid publish option '${publish}' for ${entityType}. Expected true, false, 'all', or 'pushed'.`
495
+ );
496
+ }
464
497
  function resolveEntityBatchSize({
465
498
  entityType,
466
499
  cliBatchSize,
@@ -572,9 +605,11 @@ export {
572
605
  isPathAPackageFile,
573
606
  emitWithFormat,
574
607
  readFileToObject,
608
+ chunkEntityIds,
575
609
  paginateAsync,
576
610
  isPaginatedSyncEntity,
577
611
  getEntityBatchSize,
612
+ getPublishScope,
578
613
  withBatchSizeOptions,
579
614
  applyDefaultSyncConfiguration,
580
615
  getEntityOption,
@@ -1,4 +1,4 @@
1
- import { C as CLIConfiguration, E as EntityTypes } from './index-DeoTNXj-.mjs';
1
+ import { C as CLIConfiguration, E as EntityTypes } from './index-FdhH3tn0.mjs';
2
2
 
3
3
  type UniformConfigAllOptions = {
4
4
  /**
@@ -1,4 +1,4 @@
1
- import "./chunk-QGXYDPOL.mjs";
1
+ import "./chunk-ACIL44HT.mjs";
2
2
 
3
3
  // src/sync/allSerializableEntitiesConfig.ts
4
4
  var allSerializableEntitiesConfig = {
@@ -11,11 +11,11 @@ var allSerializableEntitiesConfig = {
11
11
  projectMapDefinition: {},
12
12
  projectMapNode: {},
13
13
  contentType: {},
14
- composition: { publish: true },
15
- entry: { publish: true },
16
- entryPattern: { publish: true },
17
- componentPattern: { publish: true },
18
- compositionPattern: { publish: true },
14
+ composition: { publish: "all" },
15
+ entry: { publish: "all" },
16
+ entryPattern: { publish: "all" },
17
+ componentPattern: { publish: "all" },
18
+ compositionPattern: { publish: "all" },
19
19
  asset: {},
20
20
  workflow: {},
21
21
  webhook: {},
@@ -13,8 +13,21 @@ type EntityConfiguration = {
13
13
  disabled?: true;
14
14
  };
15
15
  type EntityWithStateConfiguration = EntityConfiguration & Partial<StateArgs>;
16
+ /**
17
+ * What a push should publish once it has written its entities to preview.
18
+ *
19
+ * - `all`: publish every entity of this type in the project that has unpublished changes, whether or
20
+ * not it came from the push source. This is what `publish: true` has always done.
21
+ * - `pushed`: publish only the entities this run actually created or updated. This is narrower than
22
+ * "everything in the push source": an entity whose preview copy already matches the source is not
23
+ * written, so it is not published either. A run that changes nothing therefore publishes nothing,
24
+ * which also means a failed publish is not retried by re-running an unchanged push. Use `all` when
25
+ * the publish set needs to converge on its own.
26
+ */
27
+ type PublishScope = 'all' | 'pushed';
16
28
  type PublishableEntitiesConfiguration = EntityWithStateConfiguration & {
17
- publish?: boolean;
29
+ /** `true` is an alias for `'all'`, kept for backwards compatibility. */
30
+ publish?: boolean | PublishScope;
18
31
  batchSize?: number;
19
32
  };
20
33
  type SerializationEntitiesConfiguration = Record<EntityTypes, {
package/dist/index.d.mts CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export { C as CLIConfiguration } from './index-DeoTNXj-.mjs';
2
+ export { C as CLIConfiguration } from './index-FdhH3tn0.mjs';
package/dist/index.mjs CHANGED
@@ -3,11 +3,13 @@ import {
3
3
  CLI_USER_AGENT,
4
4
  __require,
5
5
  applyDefaultSyncConfiguration,
6
+ chunkEntityIds,
6
7
  emitWithFormat,
7
8
  exitOnCliError,
8
9
  getDirectoryOrFilename,
9
10
  getEntityBatchSize,
10
11
  getEntityOption,
12
+ getPublishScope,
11
13
  isPaginatedSyncEntity,
12
14
  isPathAPackageFile,
13
15
  maskApiKey,
@@ -23,7 +25,7 @@ import {
23
25
  withFormatOptions,
24
26
  withProjectOptions,
25
27
  withTeamOptions
26
- } from "./chunk-QGXYDPOL.mjs";
28
+ } from "./chunk-ACIL44HT.mjs";
27
29
 
28
30
  // src/index.ts
29
31
  import * as dotenv from "dotenv";
@@ -818,10 +820,12 @@ async function syncEngine({
818
820
  onBeforeCompareObjects,
819
821
  onBeforeWriteObject,
820
822
  onError,
821
- actionConcurrency
823
+ actionConcurrency,
824
+ selectWriteWave
822
825
  //verbose = false,
823
826
  }) {
824
827
  const status = new ReactiveStatusUpdate((status2) => syncEngineEvents.emit("statusUpdate", status2));
828
+ const selectWave = (sourceObject) => selectWriteWave?.(sourceObject) ?? 0;
825
829
  const targetItems = /* @__PURE__ */ new Map();
826
830
  const deleteTracker = /* @__PURE__ */ new Set();
827
831
  const processDelete = async (object4) => {
@@ -879,6 +883,7 @@ async function syncEngine({
879
883
  await target.writeObject(finalSourceObject, targetObject2);
880
884
  status.changesApplied++;
881
885
  }
886
+ syncEngineEvents.emit("objectWritten", { id: ids[0], action: "update" });
882
887
  } catch (e) {
883
888
  if (onError) {
884
889
  onError(e, sourceObject2);
@@ -902,7 +907,10 @@ async function syncEngine({
902
907
  if (!compareResult) {
903
908
  if (mode === "createOrUpdate" || mode === "mirror") {
904
909
  status.changeCount++;
905
- actions.push(() => processUpdate(sourceObject, targetObject));
910
+ actions.push({
911
+ wave: selectWave(sourceObject),
912
+ run: () => processUpdate(sourceObject, targetObject)
913
+ });
906
914
  }
907
915
  }
908
916
  processedIds.forEach((i) => targetItems.delete(i));
@@ -914,6 +922,7 @@ async function syncEngine({
914
922
  await target.writeObject(finalSourceObject);
915
923
  status.changesApplied++;
916
924
  }
925
+ syncEngineEvents.emit("objectWritten", { id, action: "create" });
917
926
  } catch (e) {
918
927
  if (onError) {
919
928
  onError(e, sourceObject2);
@@ -938,7 +947,10 @@ async function syncEngine({
938
947
  const compareResult = compareContents(sourceObject, matchedTargetObject);
939
948
  if (!compareResult) {
940
949
  status.changeCount++;
941
- actions.push(() => processUpdate(sourceObject, matchedTargetObject));
950
+ actions.push({
951
+ wave: selectWave(sourceObject),
952
+ run: () => processUpdate(sourceObject, matchedTargetObject)
953
+ });
942
954
  }
943
955
  (Array.isArray(matchedTargetObject.id) ? matchedTargetObject.id : [matchedTargetObject.id]).forEach(
944
956
  (i) => targetItems.delete(i)
@@ -958,15 +970,21 @@ async function syncEngine({
958
970
  if (targetObject) {
959
971
  deletes.push(() => processDelete(targetObject));
960
972
  }
961
- actions.push(async () => {
962
- for (const deleteFn of deletes) {
963
- await deleteFn();
973
+ actions.push({
974
+ wave: selectWave(sourceObject),
975
+ run: async () => {
976
+ for (const deleteFn of deletes) {
977
+ await deleteFn();
978
+ }
979
+ await processUpsert(sourceObject, ids[0]);
964
980
  }
965
- await processUpsert(sourceObject, ids[0]);
966
981
  });
967
982
  } else {
968
983
  status.changeCount++;
969
- actions.push(() => processUpsert(sourceObject, ids[0]));
984
+ actions.push({
985
+ wave: selectWave(sourceObject),
986
+ run: () => processUpsert(sourceObject, ids[0])
987
+ });
970
988
  }
971
989
  }
972
990
  }
@@ -985,9 +1003,27 @@ async function syncEngine({
985
1003
  });
986
1004
  await runSyncActions(deletes, actionConcurrency);
987
1005
  }
988
- await runSyncActions(actions, actionConcurrency);
1006
+ await runSyncWriteWaves(actions, actionConcurrency);
989
1007
  await Promise.all([source.onSyncComplete?.(false), target.onSyncComplete?.(true)]);
990
1008
  }
1009
+ var runSyncWriteWaves = async (actions, actionConcurrency) => {
1010
+ if (actions.length === 0) {
1011
+ return;
1012
+ }
1013
+ const waves = /* @__PURE__ */ new Map();
1014
+ for (const { wave, run } of actions) {
1015
+ const waveActions = waves.get(wave);
1016
+ if (waveActions) {
1017
+ waveActions.push(run);
1018
+ } else {
1019
+ waves.set(wave, [run]);
1020
+ }
1021
+ }
1022
+ const orderedWaves = Array.from(waves.entries()).sort(([first], [second]) => first - second);
1023
+ for (const [, waveActions] of orderedWaves) {
1024
+ await runSyncActions(waveActions, actionConcurrency);
1025
+ }
1026
+ };
991
1027
  var runSyncActions = async (actions, actionConcurrency) => {
992
1028
  if (actions.length === 0) {
993
1029
  return;
@@ -2692,6 +2728,7 @@ var deleteDownloadedFileByUrl = async (url, options) => {
2692
2728
  };
2693
2729
 
2694
2730
  // src/files/files.ts
2731
+ import { selectWritableAssetFields } from "@uniformdev/assets";
2695
2732
  import {
2696
2733
  ASSETS_SOURCE_UNIFORM,
2697
2734
  getPropertiesValue as getPropertiesValue2,
@@ -3148,17 +3185,15 @@ var compareCompositionsOrEntriesWithoutAssetUrlsForPublishing = (source, target)
3148
3185
  }
3149
3186
  return compareCompositionsOrEntriesWithoutAssetUrls(source, target);
3150
3187
  };
3151
- var removeUrlFromAsset = (asset) => {
3152
- if (asset.asset.fields?.url?.value) {
3153
- asset.asset.fields.url.value = "";
3154
- }
3155
- return asset;
3156
- };
3188
+ var selectComparableAsset = ({ asset }) => ({
3189
+ _id: asset._id,
3190
+ _name: asset._name,
3191
+ _dataResources: asset._dataResources,
3192
+ labels: asset.labels,
3193
+ fields: selectWritableAssetFields(asset.fields)
3194
+ });
3157
3195
  var compareAssetsWithoutUrls = (source, target) => {
3158
- return serializedDequal(
3159
- removeUrlFromAsset(structuredClone(source.object)),
3160
- removeUrlFromAsset(structuredClone(target.object))
3161
- );
3196
+ return serializedDequal(selectComparableAsset(source.object), selectComparableAsset(target.object));
3162
3197
  };
3163
3198
  var downloadFilesForCompositionOrEntry = async ({
3164
3199
  entity,
@@ -4759,16 +4794,28 @@ var selectIdentifier3 = (response) => {
4759
4794
  }
4760
4795
  return baseId;
4761
4796
  };
4762
- function parseCompositionSerializedId(providerId) {
4763
- const [compositionId, editionId] = providerId.split(" (");
4764
- return { compositionId, editionId: editionId?.slice(0, -1) };
4765
- }
4766
4797
  var selectDisplayName3 = (component) => {
4767
4798
  const name = component.composition._name ?? component.composition._slug ?? component.composition._id;
4768
4799
  const edition = component.editionId ? component.editionName ?? component.editionId : void 0;
4769
4800
  return `${name} (pid: ${component.composition._id}${edition ? `, edition: ${edition}` : ""})`;
4770
4801
  };
4771
4802
 
4803
+ // src/commands/canvas/util/serializedIds.ts
4804
+ function parseSerializedId(serializedId) {
4805
+ const [id, editionId] = serializedId.split(" (");
4806
+ return { id, editionId: editionId?.slice(0, -1) };
4807
+ }
4808
+ function splitSerializedIds(ids) {
4809
+ return ids.split(",").map((id) => id.trim()).filter(Boolean);
4810
+ }
4811
+ function toRawEntityIds(serializedIds) {
4812
+ return Array.from(new Set(serializedIds.map(toRawEntityId)));
4813
+ }
4814
+ function toRawEntityId(serializedId) {
4815
+ const { id, editionId } = parseSerializedId(serializedId);
4816
+ return editionId ?? id;
4817
+ }
4818
+
4772
4819
  // src/commands/canvas/componentInstanceEngineDataSource.ts
4773
4820
  function createComponentInstanceEngineDataSource({
4774
4821
  client,
@@ -4778,36 +4825,47 @@ function createComponentInstanceEngineDataSource({
4778
4825
  patternType,
4779
4826
  verbose,
4780
4827
  batchSize,
4828
+ editions = "all",
4781
4829
  ...clientOptions
4782
4830
  }) {
4783
4831
  const stateId = convertStateOption(state);
4784
4832
  async function* getObjects() {
4785
- const componentInstances = paginateAsync(
4786
- async (offset, limit2) => {
4787
- const parameters = {
4788
- ...clientOptions,
4789
- limit: limit2,
4790
- offset,
4791
- pattern: onlyCompositions ? false : onlyPatterns ? true : void 0,
4792
- state: stateId,
4793
- patternType,
4794
- editions: "all"
4795
- };
4796
- if (verbose) {
4797
- console.log(`\u{1F41B} pull compositions: `, parameters);
4833
+ const pageSize = batchSize ?? 100;
4834
+ for (const compositionIDsChunk of chunkEntityIds(clientOptions.compositionIDs)) {
4835
+ const componentInstances = paginateAsync(
4836
+ async (offset, limit2) => {
4837
+ const parameters = {
4838
+ ...clientOptions,
4839
+ compositionIDs: compositionIDsChunk,
4840
+ limit: limit2,
4841
+ offset,
4842
+ pattern: onlyCompositions ? false : onlyPatterns ? true : void 0,
4843
+ state: stateId,
4844
+ patternType,
4845
+ editions
4846
+ };
4847
+ if (verbose) {
4848
+ console.log(`\u{1F41B} pull compositions: `, parameters);
4849
+ }
4850
+ return (await client.list(parameters)).compositions;
4851
+ },
4852
+ {
4853
+ pageSize,
4854
+ verbose,
4855
+ entityName: "compositions",
4856
+ // a raw id resolves to exactly one row, so the chunk bounds the result
4857
+ maxItems: editions === "raw" ? compositionIDsChunk?.length : void 0
4798
4858
  }
4799
- return (await client.list(parameters)).compositions;
4800
- },
4801
- { pageSize: batchSize ?? 100, verbose, entityName: "compositions" }
4802
- );
4803
- for await (const compositionListItem of componentInstances) {
4804
- const result = {
4805
- id: selectIdentifier3(compositionListItem),
4806
- displayName: selectDisplayName3(compositionListItem),
4807
- providerId: selectIdentifier3(compositionListItem),
4808
- object: prepCompositionForDisk(compositionListItem)
4809
- };
4810
- yield result;
4859
+ );
4860
+ for await (const compositionListItem of componentInstances) {
4861
+ const result = {
4862
+ id: selectIdentifier3(compositionListItem),
4863
+ displayName: selectDisplayName3(compositionListItem),
4864
+ providerId: selectIdentifier3(compositionListItem),
4865
+ object: prepCompositionForDisk(compositionListItem)
4866
+ };
4867
+ yield result;
4868
+ }
4811
4869
  }
4812
4870
  }
4813
4871
  return {
@@ -4815,9 +4873,10 @@ function createComponentInstanceEngineDataSource({
4815
4873
  objects: getObjects(),
4816
4874
  deleteObject: async (providerId) => {
4817
4875
  if (verbose) {
4818
- console.log(`\u{1F41B} delete composition: (id: ${parseCompositionSerializedId(providerId)})`);
4876
+ console.log(`\u{1F41B} delete composition: (id: ${providerId})`);
4819
4877
  }
4820
- await client.remove(parseCompositionSerializedId(providerId));
4878
+ const { id: compositionId, editionId } = parseSerializedId(providerId);
4879
+ await client.remove({ compositionId, editionId });
4821
4880
  },
4822
4881
  writeObject: async (object4) => {
4823
4882
  if (verbose) {
@@ -4882,29 +4941,23 @@ var CompositionPublishModule = {
4882
4941
  console.error(`Specify --all or composition ID(s) to publish.`);
4883
4942
  process.exit(1);
4884
4943
  }
4885
- const compositionIDsArray = ids ? ids.split(",").map((id) => id.trim()) : void 0;
4944
+ const compositionIDs = ids ? toRawEntityIds(splitSerializedIds(ids)) : void 0;
4886
4945
  const fetch2 = nodeFetchProxy(proxy, verbose);
4887
4946
  const client = getCompositionManagementClient({ apiKey, apiHost, fetch: fetch2, projectId });
4888
- const source = createComponentInstanceEngineDataSource({
4947
+ const createDataSource = (state) => createComponentInstanceEngineDataSource({
4889
4948
  client,
4890
- state: "preview",
4891
- compositionIDs: compositionIDsArray,
4892
- onlyCompositions,
4893
- onlyPatterns,
4894
- patternType,
4895
- verbose,
4896
- batchSize: resolvedBatchSize
4897
- });
4898
- const target = createComponentInstanceEngineDataSource({
4899
- client,
4900
- state: "published",
4901
- compositionIDs: compositionIDsArray,
4949
+ state,
4950
+ compositionIDs,
4951
+ // ids name exact entities or editions; resolving editions would publish siblings nobody asked for
4952
+ editions: compositionIDs ? "raw" : "all",
4902
4953
  onlyCompositions,
4903
4954
  onlyPatterns,
4904
4955
  patternType,
4905
4956
  verbose,
4906
4957
  batchSize: resolvedBatchSize
4907
4958
  });
4959
+ const source = createDataSource("preview");
4960
+ const target = createDataSource("published");
4908
4961
  const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
4909
4962
  await syncEngine({
4910
4963
  source,
@@ -5461,7 +5514,7 @@ var CompositionUnpublishModule = {
5461
5514
  console.error(`Specify --all or composition ID(s) to unpublish.`);
5462
5515
  process.exit(1);
5463
5516
  }
5464
- const compositionIDsArray = ids ? ids.split(",").map((id) => id.trim()) : void 0;
5517
+ const compositionIDsArray = ids ? toRawEntityIds(splitSerializedIds(ids)) : void 0;
5465
5518
  const targetItems = /* @__PURE__ */ new Map();
5466
5519
  const fetch2 = nodeFetchProxy(proxy, verbose);
5467
5520
  const client = getCompositionManagementClient({ apiKey, apiHost, fetch: fetch2, projectId });
@@ -5469,6 +5522,8 @@ var CompositionUnpublishModule = {
5469
5522
  client,
5470
5523
  state: "published",
5471
5524
  compositionIDs: compositionIDsArray,
5525
+ // matched exactly as publish matches them, so the two stay inverses
5526
+ editions: compositionIDsArray ? "raw" : "all",
5472
5527
  onlyCompositions,
5473
5528
  onlyPatterns,
5474
5529
  patternType,
@@ -5479,6 +5534,8 @@ var CompositionUnpublishModule = {
5479
5534
  client,
5480
5535
  state: "preview",
5481
5536
  compositionIDs: compositionIDsArray,
5537
+ // matched exactly as publish matches them, so the two stay inverses
5538
+ editions: compositionIDsArray ? "raw" : "all",
5482
5539
  onlyCompositions,
5483
5540
  onlyPatterns,
5484
5541
  patternType,
@@ -5505,8 +5562,9 @@ var CompositionUnpublishModule = {
5505
5562
  console.log(`Composition ${id} did not have a draft (removing published)`);
5506
5563
  }
5507
5564
  if (!whatIf) {
5565
+ const { id: compositionId } = parseSerializedId(id);
5508
5566
  actions.push(
5509
- client.unpublish(parseCompositionSerializedId(id)).catch((err) => {
5567
+ client.unpublish({ compositionId, editionId: toRawEntityId(id) }).catch((err) => {
5510
5568
  const isNotFound = err instanceof ApiClientError && err.statusCode === 404;
5511
5569
  if (isNotFound) {
5512
5570
  console.warn(
@@ -6787,10 +6845,6 @@ var selectEntryIdentifier = (e) => {
6787
6845
  }
6788
6846
  return baseId;
6789
6847
  };
6790
- function parseEntrySerializedId(providerId) {
6791
- const [entryId, editionId] = providerId.split(" (");
6792
- return { entryId, editionId: editionId?.slice(0, -1) };
6793
- }
6794
6848
  var selectEntryDisplayName = (e) => {
6795
6849
  const name = e.entry._name ?? "Untitled";
6796
6850
  const edition = e.editionId ? e.editionName ?? e.editionId : void 0;
@@ -6805,45 +6859,56 @@ function createEntryEngineDataSource({
6805
6859
  onlyPatterns,
6806
6860
  entryIDs,
6807
6861
  batchSize,
6808
- verbose
6862
+ verbose,
6863
+ editions = "all"
6809
6864
  }) {
6810
6865
  const stateId = convertStateOption(state);
6811
6866
  async function* getObjects() {
6812
- const entries = paginateAsync(
6813
- async (offset, limit2) => {
6814
- try {
6815
- return (await client.list({
6816
- offset,
6817
- limit: limit2,
6818
- entryIDs,
6819
- pattern: onlyEntries ? false : onlyPatterns ? true : void 0,
6820
- state: stateId,
6821
- editions: "all"
6822
- })).entries;
6823
- } catch (error) {
6824
- if (error instanceof ApiClientError2 && error.errorMessage === "Entry not found or not published") {
6825
- return [];
6867
+ const pageSize = batchSize ?? 100;
6868
+ for (const entryIDsChunk of chunkEntityIds(entryIDs)) {
6869
+ const entries = paginateAsync(
6870
+ async (offset, limit2) => {
6871
+ try {
6872
+ return (await client.list({
6873
+ offset,
6874
+ limit: limit2,
6875
+ entryIDs: entryIDsChunk,
6876
+ pattern: onlyEntries ? false : onlyPatterns ? true : void 0,
6877
+ state: stateId,
6878
+ editions
6879
+ })).entries;
6880
+ } catch (error) {
6881
+ if (error instanceof ApiClientError2 && error.errorMessage?.startsWith("Entry not found")) {
6882
+ return [];
6883
+ }
6884
+ throw error;
6826
6885
  }
6827
- throw error;
6886
+ },
6887
+ {
6888
+ pageSize,
6889
+ verbose,
6890
+ entityName: "entries",
6891
+ // a raw id resolves to exactly one row, so the chunk bounds the result
6892
+ maxItems: editions === "raw" ? entryIDsChunk?.length : void 0
6828
6893
  }
6829
- },
6830
- { pageSize: batchSize ?? 100, verbose, entityName: "entries" }
6831
- );
6832
- for await (const e of entries) {
6833
- const result = {
6834
- id: selectEntryIdentifier(e),
6835
- displayName: selectEntryDisplayName(e),
6836
- providerId: selectEntryIdentifier(e),
6837
- object: prepCompositionForDisk(e)
6838
- };
6839
- yield result;
6894
+ );
6895
+ for await (const e of entries) {
6896
+ const result = {
6897
+ id: selectEntryIdentifier(e),
6898
+ displayName: selectEntryDisplayName(e),
6899
+ providerId: selectEntryIdentifier(e),
6900
+ object: prepCompositionForDisk(e)
6901
+ };
6902
+ yield result;
6903
+ }
6840
6904
  }
6841
6905
  }
6842
6906
  return {
6843
6907
  name: "Uniform API",
6844
6908
  objects: getObjects(),
6845
6909
  deleteObject: async (providerId) => {
6846
- await client.remove(parseEntrySerializedId(providerId));
6910
+ const { id: entryId, editionId } = parseSerializedId(providerId);
6911
+ await client.remove({ entryId, editionId });
6847
6912
  },
6848
6913
  writeObject: async ({ object: object4 }) => {
6849
6914
  await client.save({ ...convertEntryToPutEntry(object4), state: stateId });
@@ -6893,23 +6958,21 @@ var EntryPublishModule = {
6893
6958
  console.error(`Specify --all or entry ID(s) to publish.`);
6894
6959
  process.exit(1);
6895
6960
  }
6896
- const entryIDsArray = ids ? ids.split(",").map((id) => id.trim()) : void 0;
6961
+ const entryIDs = ids ? toRawEntityIds(splitSerializedIds(ids)) : void 0;
6897
6962
  const fetch2 = nodeFetchProxy(proxy, verbose);
6898
6963
  const client = getEntryManagementClient({ apiKey, apiHost, fetch: fetch2, projectId });
6899
- const source = createEntryEngineDataSource({
6964
+ const createDataSource = (state) => createEntryEngineDataSource({
6900
6965
  client,
6901
- state: "preview",
6902
- entryIDs: entryIDsArray,
6903
- onlyEntries: true,
6904
- batchSize: resolvedBatchSize
6905
- });
6906
- const target = createEntryEngineDataSource({
6907
- client,
6908
- state: "published",
6909
- entryIDs: entryIDsArray,
6966
+ state,
6967
+ entryIDs,
6968
+ // ids name exact entities or editions; resolving editions would publish siblings nobody asked for
6969
+ editions: entryIDs ? "raw" : "all",
6910
6970
  onlyEntries: true,
6971
+ verbose,
6911
6972
  batchSize: resolvedBatchSize
6912
6973
  });
6974
+ const source = createDataSource("preview");
6975
+ const target = createDataSource("published");
6913
6976
  const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
6914
6977
  await syncEngine({
6915
6978
  source,
@@ -7255,7 +7318,7 @@ var EntryUnpublishModule = {
7255
7318
  console.error(`Specify --all or entry ID(s) to unpublish.`);
7256
7319
  process.exit(1);
7257
7320
  }
7258
- const entryIDsArray = ids ? ids.split(",").map((id) => id.trim()) : void 0;
7321
+ const entryIDsArray = ids ? toRawEntityIds(splitSerializedIds(ids)) : void 0;
7259
7322
  const targetItems = /* @__PURE__ */ new Map();
7260
7323
  const fetch2 = nodeFetchProxy(proxy, verbose);
7261
7324
  const client = getEntryManagementClient({ apiKey, apiHost, fetch: fetch2, projectId });
@@ -7263,6 +7326,8 @@ var EntryUnpublishModule = {
7263
7326
  client,
7264
7327
  state: "published",
7265
7328
  entryIDs: entryIDsArray,
7329
+ // matched exactly as publish matches them, so the two stay inverses
7330
+ editions: entryIDsArray ? "raw" : "all",
7266
7331
  onlyEntries: true,
7267
7332
  batchSize: resolvedBatchSize
7268
7333
  });
@@ -7270,6 +7335,8 @@ var EntryUnpublishModule = {
7270
7335
  client,
7271
7336
  state: "preview",
7272
7337
  entryIDs: entryIDsArray,
7338
+ // matched exactly as publish matches them, so the two stay inverses
7339
+ editions: entryIDsArray ? "raw" : "all",
7273
7340
  onlyEntries: true,
7274
7341
  batchSize: resolvedBatchSize
7275
7342
  });
@@ -7293,8 +7360,9 @@ var EntryUnpublishModule = {
7293
7360
  console.log(`Entry ${id} did not have a draft (removing published)`);
7294
7361
  }
7295
7362
  if (!whatIf) {
7363
+ const { id: entryId } = parseSerializedId(id);
7296
7364
  actions.push(
7297
- client.unpublish(parseEntrySerializedId(id)).catch((err) => {
7365
+ client.unpublish({ entryId, editionId: toRawEntityId(id) }).catch((err) => {
7298
7366
  const isNotFound = err instanceof ApiClientError3 && err.statusCode === 404;
7299
7367
  if (isNotFound) {
7300
7368
  console.warn(
@@ -7487,23 +7555,21 @@ var EntryPatternPublishModule = {
7487
7555
  console.error(`Specify --all or entry pattern ID(s) to publish.`);
7488
7556
  process.exit(1);
7489
7557
  }
7490
- const entryIDsArray = ids ? ids.split(",").map((id) => id.trim()) : void 0;
7558
+ const entryIDs = ids ? toRawEntityIds(splitSerializedIds(ids)) : void 0;
7491
7559
  const fetch2 = nodeFetchProxy(proxy, verbose);
7492
7560
  const client = getEntryManagementClient({ apiKey, apiHost, fetch: fetch2, projectId });
7493
- const source = createEntryEngineDataSource({
7494
- client,
7495
- state: "preview",
7496
- entryIDs: entryIDsArray,
7497
- onlyPatterns: true,
7498
- batchSize: resolvedBatchSize
7499
- });
7500
- const target = createEntryEngineDataSource({
7561
+ const createDataSource = (state) => createEntryEngineDataSource({
7501
7562
  client,
7502
- state: "published",
7503
- entryIDs: entryIDsArray,
7563
+ state,
7564
+ entryIDs,
7565
+ // ids name exact entities or editions; resolving editions would publish siblings nobody asked for
7566
+ editions: entryIDs ? "raw" : "all",
7504
7567
  onlyPatterns: true,
7568
+ verbose,
7505
7569
  batchSize: resolvedBatchSize
7506
7570
  });
7571
+ const source = createDataSource("preview");
7572
+ const target = createDataSource("published");
7507
7573
  const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
7508
7574
  await syncEngine({
7509
7575
  source,
@@ -7823,7 +7889,7 @@ var EntryPatternUnpublishModule = {
7823
7889
  console.error(`Specify --all or entry pattern ID(s) to unpublish.`);
7824
7890
  process.exit(1);
7825
7891
  }
7826
- const entryIDsArray = ids ? ids.split(",").map((id) => id.trim()) : void 0;
7892
+ const entryIDsArray = ids ? toRawEntityIds(splitSerializedIds(ids)) : void 0;
7827
7893
  const targetItems = /* @__PURE__ */ new Map();
7828
7894
  const fetch2 = nodeFetchProxy(proxy, verbose);
7829
7895
  const client = getEntryManagementClient({ apiKey, apiHost, fetch: fetch2, projectId });
@@ -7831,6 +7897,8 @@ var EntryPatternUnpublishModule = {
7831
7897
  client,
7832
7898
  state: "published",
7833
7899
  entryIDs: entryIDsArray,
7900
+ // matched exactly as publish matches them, so the two stay inverses
7901
+ editions: entryIDsArray ? "raw" : "all",
7834
7902
  onlyPatterns: true,
7835
7903
  batchSize: resolvedBatchSize
7836
7904
  });
@@ -7838,6 +7906,8 @@ var EntryPatternUnpublishModule = {
7838
7906
  client,
7839
7907
  state: "preview",
7840
7908
  entryIDs: entryIDsArray,
7909
+ // matched exactly as publish matches them, so the two stay inverses
7910
+ editions: entryIDsArray ? "raw" : "all",
7841
7911
  onlyPatterns: true,
7842
7912
  batchSize: resolvedBatchSize
7843
7913
  });
@@ -7861,8 +7931,9 @@ var EntryPatternUnpublishModule = {
7861
7931
  console.log(`Entry pattern ${id} did not have a draft (removing published)`);
7862
7932
  }
7863
7933
  if (!whatIf) {
7934
+ const { id: entryId } = parseSerializedId(id);
7864
7935
  actions.push(
7865
- client.unpublish(parseEntrySerializedId(id)).catch((err) => {
7936
+ client.unpublish({ entryId, editionId: toRawEntityId(id) }).catch((err) => {
7866
7937
  const isNotFound = err instanceof ApiClientError4 && err.statusCode === 404;
7867
7938
  if (isNotFound) {
7868
7939
  console.warn(
@@ -12722,6 +12793,7 @@ var selectIdentifier15 = (source, projectId) => [
12722
12793
  projectId + source.projectMapId + source.id,
12723
12794
  projectId + source.projectMapId + source.path
12724
12795
  ];
12796
+ var selectNodeDepth = (source) => source.path.split("/").filter((segment) => segment.length > 0).length;
12725
12797
  var selectFilename = (source) => cleanFileName(`${source.pathSegment}_${source.id}`);
12726
12798
  var selectDisplayName15 = (source) => `${source.name} (pid: ${source.id})`;
12727
12799
  function alignProjectMapNodeWithTargetIdentifier(sourceObject, targetObject) {
@@ -12928,7 +13000,7 @@ var ProjectMapNodePushModule = {
12928
13000
  source = await createArraySyncEngineDataSource({
12929
13001
  name: `Package file ${directory}`,
12930
13002
  objects: packageContents.projectMapNodes.sort((a, b) => {
12931
- return a.path.length - b.path.length;
13003
+ return selectNodeDepth(a) - selectNodeDepth(b);
12932
13004
  }) ?? [],
12933
13005
  selectIdentifier: expandedSelectIdentifier,
12934
13006
  selectDisplayName: selectDisplayName15
@@ -12954,6 +13026,9 @@ var ProjectMapNodePushModule = {
12954
13026
  whatIf,
12955
13027
  allowEmptySource,
12956
13028
  log: createSyncEngineConsoleLogger({ diffMode }),
13029
+ // Writes land parent-first: every node at one depth is written before any deeper node
13030
+ // starts, so a moved subtree's descendants are recomputed from the parent's new path.
13031
+ selectWriteWave: (sourceObject) => selectNodeDepth(sourceObject.object),
12957
13032
  onBeforeCompareObjects: async (sourceObject, targetObject) => {
12958
13033
  return alignProjectMapNodeWithTargetIdentifier(sourceObject, targetObject);
12959
13034
  },
@@ -13633,7 +13708,7 @@ var WebhookPullModule = {
13633
13708
  // src/commands/sync/commands/util.ts
13634
13709
  import ora2 from "ora";
13635
13710
  async function spinPromise(action, options) {
13636
- const { successText, failText } = typeof options === "object" ? options : { successText: void 0, failText: void 0 };
13711
+ const { failText } = options;
13637
13712
  const spinner = ora2(options).start();
13638
13713
  const consoleReplay = [];
13639
13714
  const revertLog = patchConsole({
@@ -13671,6 +13746,7 @@ async function spinPromise(action, options) {
13671
13746
  process.on("SIGINT", executeReplayOnSigint);
13672
13747
  try {
13673
13748
  const result = await action;
13749
+ const successText = typeof options.successText === "function" ? options.successText(result) : options.successText;
13674
13750
  const finalStatusText = spinner.text.startsWith(options.text) && spinner.text.length > options.text.length ? spinner.text.slice(options.text.length).trim() : `\u2699\uFE0F compared: ${numPad(0)} changes: 0`;
13675
13751
  const padding = " ".repeat(Math.max(4, 40 - successText.length));
13676
13752
  spinner.succeed(successText + padding + finalStatusText);
@@ -13952,160 +14028,115 @@ var SyncPushModule = {
13952
14028
  "No entities were configured to be pushed. Please make sure you have configuration file and at least one entity type is enabled."
13953
14029
  );
13954
14030
  }
13955
- for (const [entityType, module] of enabledEntities) {
14031
+ const publishScopes = /* @__PURE__ */ new Map();
14032
+ for (const { entityType } of publishableEntities) {
13956
14033
  try {
13957
- await spinPromise(
13958
- module.handler({
13959
- ...otherParams,
13960
- state: 0,
13961
- format: getFormat2(entityType, config2),
13962
- onlyCompositions: entityType === "composition" ? true : void 0,
13963
- onlyPatterns: ["pattern", "componentPattern", "compositionPattern"].includes(entityType) ? true : void 0,
13964
- patternType: entityType === "compositionPattern" ? "composition" : entityType === "componentPattern" ? "component" : void 0,
13965
- mode: getPushMode(entityType, config2),
13966
- directory: getPushFilename(entityType, config2),
13967
- allowEmptySource: config2.allowEmptySource,
13968
- ...isPaginatedSyncEntity(entityType) ? { resolvedBatchSize: getEntityBatchSize(entityType, config2) } : {}
13969
- }),
13970
- {
13971
- text: `${entityType}...`,
13972
- successText: entityType,
13973
- failText(error) {
13974
- return `${entityType}
13975
-
13976
- ${error.stack ?? error.message}`;
13977
- }
13978
- }
13979
- );
13980
- } catch {
14034
+ publishScopes.set(entityType, getPublishScope(entityType, config2));
14035
+ } catch (error) {
14036
+ console.error(error instanceof Error ? error.message : String(error));
13981
14037
  process.exit(1);
13982
14038
  }
13983
14039
  }
13984
- if (config2.entitiesConfig?.componentPattern && config2.entitiesConfig?.componentPattern?.push?.disabled !== true && config2.entitiesConfig?.componentPattern?.publish) {
13985
- try {
13986
- await spinPromise(
13987
- ComponentPatternPublishModule.handler({
13988
- ...otherParams,
13989
- serialization: config2,
13990
- patternType: "component",
13991
- onlyPatterns: true,
13992
- all: true,
13993
- directory: getPushFilename("componentPattern", config2),
13994
- resolvedBatchSize: getEntityBatchSize("componentPattern", config2)
13995
- }),
13996
- {
13997
- text: "publishing component patterns...",
13998
- successText: "published component patterns",
13999
- failText(error) {
14000
- return `publishing component patterns
14001
-
14002
- ${error.stack ?? error.message}`;
14003
- }
14004
- }
14005
- );
14006
- } catch {
14007
- process.exit(1);
14008
- }
14040
+ const pushedIds = /* @__PURE__ */ new Map();
14041
+ for (const [entityType, module] of enabledEntities) {
14042
+ const written = [];
14043
+ const recordWrite = ({ id }) => written.push(id);
14044
+ syncEngineEvents.on("objectWritten", recordWrite);
14045
+ pushedIds.set(entityType, written);
14046
+ await runStep({
14047
+ text: `${entityType}...`,
14048
+ successText: entityType,
14049
+ failLabel: entityType,
14050
+ run: () => module.handler({
14051
+ ...otherParams,
14052
+ state: 0,
14053
+ format: getFormat2(entityType, config2),
14054
+ ...getEntityDiscriminators(entityType),
14055
+ mode: getPushMode(entityType, config2),
14056
+ directory: getPushFilename(entityType, config2),
14057
+ allowEmptySource: config2.allowEmptySource,
14058
+ ...isPaginatedSyncEntity(entityType) ? { resolvedBatchSize: getEntityBatchSize(entityType, config2) } : {}
14059
+ })
14060
+ });
14061
+ syncEngineEvents.off("objectWritten", recordWrite);
14009
14062
  }
14010
- if (config2.entitiesConfig?.compositionPattern && config2.entitiesConfig?.compositionPattern?.push?.disabled !== true && config2.entitiesConfig?.compositionPattern?.publish) {
14011
- try {
14012
- await spinPromise(
14013
- CompositionPatternPublishModule.handler({
14014
- ...otherParams,
14015
- serialization: config2,
14016
- all: true,
14017
- onlyPatterns: true,
14018
- patternType: "composition",
14019
- directory: getPushFilename("compositionPattern", config2),
14020
- resolvedBatchSize: getEntityBatchSize("compositionPattern", config2)
14021
- }),
14022
- {
14023
- text: "publishing composition patterns...",
14024
- successText: "published composition patterns",
14025
- failText(error) {
14026
- return `publishing composition patterns
14027
-
14028
- ${error.stack ?? error.message}`;
14029
- }
14030
- }
14031
- );
14032
- } catch {
14033
- process.exit(1);
14063
+ for (const { entityType, module, label } of publishableEntities) {
14064
+ const entityConfig = config2.entitiesConfig?.[entityType];
14065
+ const scope = publishScopes.get(entityType);
14066
+ if (entityConfig?.disabled === true || entityConfig?.push?.disabled === true || !scope) {
14067
+ continue;
14034
14068
  }
14035
- }
14036
- if (config2.entitiesConfig?.composition && config2.entitiesConfig?.composition?.push?.disabled !== true && config2.entitiesConfig?.composition?.publish) {
14037
- try {
14038
- await spinPromise(
14039
- CompositionPublishModule.handler({
14040
- ...otherParams,
14041
- serialization: config2,
14042
- all: true,
14043
- onlyCompositions: true,
14044
- directory: getPushFilename("composition", config2),
14045
- resolvedBatchSize: getEntityBatchSize("composition", config2)
14046
- }),
14047
- {
14048
- text: "publishing compositions...",
14049
- successText: "published compositions",
14050
- failText(error) {
14051
- return `publishing compositions
14052
-
14053
- ${error.stack ?? error.message}`;
14054
- }
14069
+ const directory = getPushFilename(entityType, config2);
14070
+ await runStep({
14071
+ text: `publishing ${label}...`,
14072
+ // a push that changed nothing is not an error, but it must not read as "published" either
14073
+ successText: (outcome) => outcome.skippedReason ? `skipped ${label}: ${outcome.skippedReason}` : `published ${label}`,
14074
+ failLabel: `publishing ${label}`,
14075
+ run: async () => {
14076
+ if (otherParams.whatIf) {
14077
+ return { skippedReason: "what-if run did not write preview" };
14055
14078
  }
14056
- );
14057
- } catch {
14058
- process.exit(1);
14059
- }
14060
- }
14061
- if (config2.entitiesConfig?.entry && config2.entitiesConfig?.entry?.push?.disabled !== true && config2.entitiesConfig?.entry?.publish) {
14062
- try {
14063
- await spinPromise(
14064
- EntryPublishModule.handler({
14065
- ...otherParams,
14066
- serialization: config2,
14067
- all: true,
14068
- directory: getPushFilename("entry", config2),
14069
- resolvedBatchSize: getEntityBatchSize("entry", config2)
14070
- }),
14071
- {
14072
- text: "publishing entries...",
14073
- successText: "published entries",
14074
- failText(error) {
14075
- return `publishing entries
14076
-
14077
- ${error.stack ?? error.message}`;
14079
+ let ids;
14080
+ if (scope === "pushed") {
14081
+ const written = pushedIds.get(entityType) ?? [];
14082
+ if (written.length === 0) {
14083
+ return { skippedReason: "nothing was pushed" };
14078
14084
  }
14085
+ ids = written.join(",");
14079
14086
  }
14080
- );
14081
- } catch {
14082
- process.exit(1);
14083
- }
14084
- }
14085
- if (config2.entitiesConfig?.entryPattern && config2.entitiesConfig?.entryPattern?.push?.disabled !== true && config2.entitiesConfig?.entryPattern?.publish) {
14086
- try {
14087
- await spinPromise(
14088
- EntryPatternPublishModule.handler({
14087
+ await module.handler({
14089
14088
  ...otherParams,
14090
14089
  serialization: config2,
14091
- all: true,
14092
- directory: getPushFilename("entryPattern", config2),
14093
- resolvedBatchSize: getEntityBatchSize("entryPattern", config2)
14094
- }),
14095
- {
14096
- text: "publishing entry patterns...",
14097
- successText: "published entry patterns",
14098
- failText(error) {
14099
- return `publishing entry patterns
14090
+ all: scope === "all",
14091
+ ids,
14092
+ ...getEntityDiscriminators(entityType),
14093
+ directory,
14094
+ resolvedBatchSize: getEntityBatchSize(entityType, config2)
14095
+ });
14096
+ return {};
14097
+ }
14098
+ });
14099
+ }
14100
+ }
14101
+ };
14102
+ var publishableEntities = [
14103
+ {
14104
+ entityType: "componentPattern",
14105
+ module: ComponentPatternPublishModule,
14106
+ label: "component patterns"
14107
+ },
14108
+ {
14109
+ entityType: "compositionPattern",
14110
+ module: CompositionPatternPublishModule,
14111
+ label: "composition patterns"
14112
+ },
14113
+ { entityType: "composition", module: CompositionPublishModule, label: "compositions" },
14114
+ { entityType: "entry", module: EntryPublishModule, label: "entries" },
14115
+ { entityType: "entryPattern", module: EntryPatternPublishModule, label: "entry patterns" }
14116
+ ];
14117
+ var getEntityDiscriminators = (entityType) => ({
14118
+ onlyCompositions: entityType === "composition" ? true : void 0,
14119
+ onlyPatterns: ["pattern", "componentPattern", "compositionPattern"].includes(entityType) ? true : void 0,
14120
+ patternType: entityType === "compositionPattern" ? "composition" : entityType === "componentPattern" ? "component" : void 0
14121
+ });
14122
+ var runStep = async ({
14123
+ text,
14124
+ successText,
14125
+ failLabel,
14126
+ run
14127
+ }) => {
14128
+ try {
14129
+ await spinPromise(run(), {
14130
+ text,
14131
+ successText,
14132
+ failText(error) {
14133
+ return `${failLabel}
14100
14134
 
14101
14135
  ${error.stack ?? error.message}`;
14102
- }
14103
- }
14104
- );
14105
- } catch {
14106
- process.exit(1);
14107
14136
  }
14108
- }
14137
+ });
14138
+ } catch {
14139
+ process.exit(1);
14109
14140
  }
14110
14141
  };
14111
14142
  var getPushMode = (entityType, config2) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/cli",
3
- "version": "20.79.1",
3
+ "version": "20.80.0",
4
4
  "description": "Uniform command line interface tool",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./cli.js",
@@ -27,14 +27,14 @@
27
27
  "dependencies": {
28
28
  "@inquirer/prompts": "^8.5.2",
29
29
  "@thi.ng/mime": "^2.2.23",
30
- "@uniformdev/assets": "20.79.1",
31
- "@uniformdev/automations-sdk": "20.79.1",
32
- "@uniformdev/canvas": "20.79.1",
33
- "@uniformdev/context": "20.79.1",
34
- "@uniformdev/files": "20.79.1",
35
- "@uniformdev/project-map": "20.79.1",
36
- "@uniformdev/redirect": "20.79.1",
37
- "@uniformdev/richtext": "20.79.1",
30
+ "@uniformdev/assets": "20.80.0",
31
+ "@uniformdev/automations-sdk": "20.80.0",
32
+ "@uniformdev/canvas": "20.80.0",
33
+ "@uniformdev/context": "20.80.0",
34
+ "@uniformdev/files": "20.80.0",
35
+ "@uniformdev/project-map": "20.80.0",
36
+ "@uniformdev/redirect": "20.80.0",
37
+ "@uniformdev/richtext": "20.80.0",
38
38
  "call-bind": "^1.0.2",
39
39
  "colorette": "2.0.20",
40
40
  "cosmiconfig": "9.0.2",
@@ -78,5 +78,5 @@
78
78
  "publishConfig": {
79
79
  "access": "public"
80
80
  },
81
- "gitHead": "a9709918bf00f79101fcc46bda36105626931933"
81
+ "gitHead": "6eec8f028463f30667b59af913a74d56960dde11"
82
82
  }