@uniformdev/cli 19.86.0 → 19.86.1-alpha.11

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.
Files changed (2) hide show
  1. package/dist/index.mjs +176 -42
  2. package/package.json +8 -8
package/dist/index.mjs CHANGED
@@ -669,30 +669,62 @@ var AssetListModule = {
669
669
 
670
670
  // src/commands/canvas/commands/asset/pull.ts
671
671
  import { UncachedAssetClient as UncachedAssetClient3 } from "@uniformdev/assets";
672
+ import { UncachedFileClient } from "@uniformdev/files";
672
673
 
673
674
  // src/files/index.ts
674
675
  import { preferredType } from "@thi.ng/mime";
675
676
  import { FILE_READY_STATE, getFileNameFromUrl } from "@uniformdev/files";
676
- import { createHash } from "crypto";
677
677
  import fsj from "fs-jetpack";
678
678
  import sizeOf from "image-size";
679
679
  import PQueue from "p-queue";
680
680
  import { dirname as dirname2, join as join2 } from "path";
681
681
  var FILES_DIRECTORY_NAME = "files";
682
+ var escapeRegExp = (string) => {
683
+ return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
684
+ };
682
685
  var urlToHash = (url) => {
683
- const hash = createHash("sha256");
684
- hash.update(url);
685
- return hash.digest("hex");
686
+ return Buffer.from(
687
+ // We take only the first 64 characters of the pathname as
688
+ // that's enough to guarantee uniqueness
689
+ new URL(url).pathname.substring(0, 64)
690
+ ).toString("base64");
691
+ };
692
+ var hashToPartialPathname = (hash) => {
693
+ try {
694
+ return Buffer.from(hash, "base64").toString("utf8");
695
+ } catch {
696
+ return null;
697
+ }
698
+ };
699
+ var findUrlMatchingPartialPathname = (source, pathname) => {
700
+ const escapedPathname = escapeRegExp(pathname);
701
+ const regex = new RegExp(`"(https://([^"]*?)?img.uniform.(rocks|global)${escapedPathname}([^"]*?))"`);
702
+ const match = source.match(regex);
703
+ if (match && match[1]) {
704
+ return match[1];
705
+ }
706
+ return null;
686
707
  };
687
- var urlToFileName = (url) => {
688
- const fileName = urlToHash(url);
708
+ var urlToFileName = (url, hash) => {
709
+ const fileName = hash ?? urlToHash(url);
689
710
  const fileNameChunks = url.split(".");
690
711
  const fileExtension = fileNameChunks.length > 1 ? fileNameChunks.at(-1) : "";
691
712
  return `${fileName}${fileExtension ? `.${fileExtension}` : ""}`;
692
713
  };
714
+ var getFilesDirectory = (directory) => {
715
+ const isPackage = isPathAPackageFile(directory);
716
+ return isPackage ? dirname2(directory) : (
717
+ // If we are syncing to a directory, we want to write all files into a
718
+ // top-lvl folder. That way any entities that contain files will sync to the
719
+ // same directory, so there is no duplication
720
+ join2(directory, "..")
721
+ );
722
+ };
723
+ var getUniformFileUrlMatches = (string) => {
724
+ return string.matchAll(/"(https:\/\/([^"]*?)?img\.uniform\.(rocks|global)\/([^"]*?))"/g);
725
+ };
693
726
  var deleteDownloadedFileByUrl = async (url, options) => {
694
- const isPackage = isPathAPackageFile(options.directory);
695
- const writeDirectory = isPackage ? dirname2(options.directory) : options.directory;
727
+ const writeDirectory = getFilesDirectory(options.directory);
696
728
  const fileName = urlToFileName(url);
697
729
  const fileToDelete = join2(writeDirectory, FILES_DIRECTORY_NAME, fileName);
698
730
  try {
@@ -703,18 +735,14 @@ var deleteDownloadedFileByUrl = async (url, options) => {
703
735
  };
704
736
  var extractAndDownloadUniformFilesForObject = async (object, options) => {
705
737
  const objectAsString = JSON.stringify(object);
706
- const uniformFileUrlMatches = objectAsString.matchAll(
707
- /"(https:\/\/(.*)?img\.uniform\.(rocks|global)\/(.*?))"/g
708
- );
709
- const isPackage = isPathAPackageFile(options.directory);
710
- const writeDirectory = isPackage ? dirname2(options.directory) : options.directory;
738
+ const uniformFileUrlMatches = getUniformFileUrlMatches(objectAsString);
739
+ const writeDirectory = getFilesDirectory(options.directory);
711
740
  if (uniformFileUrlMatches) {
712
741
  const fileDownloadQueue = new PQueue({ concurrency: 10 });
713
742
  for (const match of uniformFileUrlMatches) {
714
743
  const url = new URL(match[1]);
715
744
  fileDownloadQueue.add(async () => {
716
745
  try {
717
- const fetchUrl = `${url.origin}${url.pathname}?format=original`;
718
746
  const fileName = urlToFileName(url.toString());
719
747
  const fileAlreadyExists = await fsj.existsAsync(
720
748
  join2(writeDirectory, FILES_DIRECTORY_NAME, fileName)
@@ -722,6 +750,23 @@ var extractAndDownloadUniformFilesForObject = async (object, options) => {
722
750
  if (fileAlreadyExists) {
723
751
  return;
724
752
  }
753
+ const file = await options.fileClient.get({ url: url.toString() }).catch(() => null);
754
+ if (!file) {
755
+ console.warn(`Skipping file ${url} as it does not exist in the project anymore`);
756
+ return;
757
+ }
758
+ if (file.sourceId) {
759
+ try {
760
+ const hashAlreadyExists = await fsj.findAsync(join2(writeDirectory, FILES_DIRECTORY_NAME), {
761
+ matching: [file.sourceId, `${file.sourceId}.*`]
762
+ });
763
+ if (hashAlreadyExists.length > 0) {
764
+ return;
765
+ }
766
+ } catch {
767
+ }
768
+ }
769
+ const fetchUrl = `${url.origin}${url.pathname}?format=original`;
725
770
  const response = await fetch(fetchUrl);
726
771
  if (!response.ok) {
727
772
  return;
@@ -739,11 +784,8 @@ var extractAndDownloadUniformFilesForObject = async (object, options) => {
739
784
  };
740
785
  var extractAndUploadUniformFilesForObject = async (object, options) => {
741
786
  let objectAsString = JSON.stringify(object);
742
- const uniformFileUrlMatches = objectAsString.matchAll(
743
- /"(https:\/\/(.*)?img\.uniform\.(rocks|global)\/(.*?))"/g
744
- );
745
- const isPackage = isPathAPackageFile(options.directory);
746
- const writeDirectory = isPackage ? dirname2(options.directory) : options.directory;
787
+ const uniformFileUrlMatches = getUniformFileUrlMatches(objectAsString);
788
+ const writeDirectory = getFilesDirectory(options.directory);
747
789
  if (uniformFileUrlMatches) {
748
790
  const fileUploadQueue = new PQueue({ concurrency: 3 });
749
791
  for (const match of uniformFileUrlMatches) {
@@ -815,8 +857,8 @@ var extractAndUploadUniformFilesForObject = async (object, options) => {
815
857
  return file.url;
816
858
  };
817
859
  const abortTimeout = setTimeout(() => {
818
- throw new Error(`Failed to upload file ${url}`);
819
- }, 1e4);
860
+ throw new Error(`Failed to upload file ${url} (upload timed out)`);
861
+ }, 3e4);
820
862
  const uploadedFileUrl = await checkForFile();
821
863
  clearTimeout(abortTimeout);
822
864
  objectAsString = objectAsString.replaceAll(`"${url}"`, `"${uploadedFileUrl}"`);
@@ -831,9 +873,7 @@ var extractAndUploadUniformFilesForObject = async (object, options) => {
831
873
  };
832
874
  var swapOutUniformFileUrlsForTargetProject = async (object, options) => {
833
875
  let objectAsString = JSON.stringify(object);
834
- const uniformFileUrlMatches = objectAsString.matchAll(
835
- /"(https:\/\/(.*)?img\.uniform\.(rocks|global)\/(.*?))"/g
836
- );
876
+ const uniformFileUrlMatches = getUniformFileUrlMatches(objectAsString);
837
877
  if (uniformFileUrlMatches) {
838
878
  const fileUrlReplacementQueue = new PQueue({ concurrency: 3 });
839
879
  for (const match of uniformFileUrlMatches) {
@@ -858,6 +898,45 @@ var swapOutUniformFileUrlsForTargetProject = async (object, options) => {
858
898
  }
859
899
  return JSON.parse(objectAsString);
860
900
  };
901
+ var replaceRemoteUrlsWithLocalReferences = async (sourceObject, targetObject, options) => {
902
+ let sourceObjectAsString = JSON.stringify(sourceObject);
903
+ const targetObjectAsString = JSON.stringify(targetObject);
904
+ const uniformFileUrlMatches = getUniformFileUrlMatches(sourceObjectAsString);
905
+ const writeDirectory = getFilesDirectory(options.directory);
906
+ if (uniformFileUrlMatches) {
907
+ const fileUrlReplacementQueue = new PQueue({ concurrency: 3 });
908
+ for (const match of uniformFileUrlMatches) {
909
+ const url = match[1];
910
+ fileUrlReplacementQueue.add(async () => {
911
+ try {
912
+ const localFileName = urlToFileName(url);
913
+ const fileExistsLocally = await fsj.existsAsync(
914
+ join2(writeDirectory, FILES_DIRECTORY_NAME, localFileName)
915
+ );
916
+ if (fileExistsLocally) {
917
+ return;
918
+ }
919
+ const file = await options.fileClient.get({ url }).catch(() => null);
920
+ if (!file || !file.sourceId) {
921
+ return;
922
+ }
923
+ const originalPartialPath = hashToPartialPathname(file.sourceId);
924
+ if (!originalPartialPath) {
925
+ return;
926
+ }
927
+ const originalUrl = findUrlMatchingPartialPathname(targetObjectAsString, originalPartialPath);
928
+ if (!originalUrl) {
929
+ return;
930
+ }
931
+ sourceObjectAsString = sourceObjectAsString.replaceAll(`"${url}"`, `"${originalUrl}"`);
932
+ } catch {
933
+ }
934
+ });
935
+ }
936
+ await fileUrlReplacementQueue.onIdle();
937
+ }
938
+ return JSON.parse(sourceObjectAsString);
939
+ };
861
940
  var updateAssetFileIdBasedOnUrl = async (asset, options) => {
862
941
  var _a, _b, _c;
863
942
  const fileUrl = (_b = (_a = asset.asset.fields) == null ? void 0 : _a.url) == null ? void 0 : _b.value;
@@ -1009,6 +1088,7 @@ var AssetPullModule = {
1009
1088
  fetch: fetch3,
1010
1089
  projectId
1011
1090
  });
1091
+ const fileClient = new UncachedFileClient({ apiKey, apiHost, fetch: fetch3, projectId });
1012
1092
  const source = createAssetEngineDataSource({ client });
1013
1093
  let target;
1014
1094
  const isPackage = isPathAPackageFile(directory);
@@ -1050,14 +1130,27 @@ var AssetPullModule = {
1050
1130
  whatIf,
1051
1131
  allowEmptySource: true,
1052
1132
  log: createSyncEngineConsoleLogger({ diffMode }),
1053
- onBeforeCompareObjects: async (sourceObject) => {
1133
+ onBeforeCompareObjects: async (sourceObject, targetObject) => {
1134
+ var _a, _b;
1054
1135
  delete sourceObject.object.asset._author;
1055
- return sourceObject;
1136
+ const sourceObjectWithPotentiallySwappedUrl = await replaceRemoteUrlsWithLocalReferences(
1137
+ sourceObject,
1138
+ targetObject,
1139
+ {
1140
+ directory,
1141
+ fileClient
1142
+ }
1143
+ );
1144
+ if (((_a = sourceObjectWithPotentiallySwappedUrl.object.asset.fields) == null ? void 0 : _a.url) && ((_b = targetObject.object.asset.fields) == null ? void 0 : _b.url) && sourceObjectWithPotentiallySwappedUrl.object.asset.fields.url.value === targetObject.object.asset.fields.url.value) {
1145
+ targetObject.object.asset.fields.file = sourceObjectWithPotentiallySwappedUrl.object.asset.fields.file;
1146
+ }
1147
+ return sourceObjectWithPotentiallySwappedUrl;
1056
1148
  },
1057
1149
  onBeforeWriteObject: async (sourceObject) => {
1058
1150
  delete sourceObject.object.asset._author;
1059
1151
  return extractAndDownloadUniformFilesForObject(sourceObject, {
1060
- directory
1152
+ directory,
1153
+ fileClient
1061
1154
  });
1062
1155
  }
1063
1156
  });
@@ -1066,7 +1159,7 @@ var AssetPullModule = {
1066
1159
 
1067
1160
  // src/commands/canvas/commands/asset/push.ts
1068
1161
  import { UncachedAssetClient as UncachedAssetClient4 } from "@uniformdev/assets";
1069
- import { UncachedFileClient } from "@uniformdev/files";
1162
+ import { UncachedFileClient as UncachedFileClient2 } from "@uniformdev/files";
1070
1163
  var AssetPushModule = {
1071
1164
  command: "push <directory>",
1072
1165
  describe: "Pushes all assets from files in a directory to Uniform",
@@ -1127,7 +1220,7 @@ var AssetPushModule = {
1127
1220
  });
1128
1221
  }
1129
1222
  const target = createAssetEngineDataSource({ client });
1130
- const fileClient = new UncachedFileClient({ apiKey, apiHost, fetch: fetch3, projectId });
1223
+ const fileClient = new UncachedFileClient2({ apiKey, apiHost, fetch: fetch3, projectId });
1131
1224
  await syncEngine({
1132
1225
  source,
1133
1226
  target,
@@ -1150,10 +1243,15 @@ var AssetPushModule = {
1150
1243
  return sourceObjectWithNewFileUrls;
1151
1244
  },
1152
1245
  onBeforeWriteObject: async (sourceObject) => {
1153
- const sourceObjectWithNewFileUrls = await extractAndUploadUniformFilesForObject(sourceObject, {
1154
- directory,
1155
- fileClient
1156
- });
1246
+ const sourceObjectWithNewFileUrls = await swapOutUniformFileUrlsForTargetProject(
1247
+ await extractAndUploadUniformFilesForObject(sourceObject, {
1248
+ directory,
1249
+ fileClient
1250
+ }),
1251
+ {
1252
+ fileClient
1253
+ }
1254
+ );
1157
1255
  sourceObjectWithNewFileUrls.object = await updateAssetFileIdBasedOnUrl(
1158
1256
  sourceObjectWithNewFileUrls.object,
1159
1257
  {
@@ -2089,6 +2187,7 @@ var CompositionPublishModule = {
2089
2187
 
2090
2188
  // src/commands/canvas/commands/composition/pull.ts
2091
2189
  import { UncachedCanvasClient as UncachedCanvasClient10 } from "@uniformdev/canvas";
2190
+ import { UncachedFileClient as UncachedFileClient3 } from "@uniformdev/files";
2092
2191
  var CompositionPullModule = {
2093
2192
  command: "pull <directory>",
2094
2193
  describe: "Pulls all compositions to local files in a directory",
@@ -2148,6 +2247,7 @@ var CompositionPullModule = {
2148
2247
  }) => {
2149
2248
  const fetch3 = nodeFetchProxy(proxy);
2150
2249
  const client = new UncachedCanvasClient10({ apiKey, apiHost, fetch: fetch3, projectId });
2250
+ const fileClient = new UncachedFileClient3({ apiKey, apiHost, fetch: fetch3, projectId });
2151
2251
  const source = createComponentInstanceEngineDataSource({ client, state, onlyCompositions, onlyPatterns });
2152
2252
  const isPackage = isPathAPackageFile(directory);
2153
2253
  let target;
@@ -2177,9 +2277,16 @@ var CompositionPullModule = {
2177
2277
  whatIf,
2178
2278
  allowEmptySource: true,
2179
2279
  log: createSyncEngineConsoleLogger({ diffMode }),
2280
+ onBeforeCompareObjects: async (sourceObject, targetObject) => {
2281
+ return replaceRemoteUrlsWithLocalReferences(sourceObject, targetObject, {
2282
+ directory,
2283
+ fileClient
2284
+ });
2285
+ },
2180
2286
  onBeforeWriteObject: async (sourceObject) => {
2181
2287
  return extractAndDownloadUniformFilesForObject(sourceObject, {
2182
- directory
2288
+ directory,
2289
+ fileClient
2183
2290
  });
2184
2291
  }
2185
2292
  });
@@ -2188,7 +2295,7 @@ var CompositionPullModule = {
2188
2295
 
2189
2296
  // src/commands/canvas/commands/composition/push.ts
2190
2297
  import { UncachedCanvasClient as UncachedCanvasClient11 } from "@uniformdev/canvas";
2191
- import { UncachedFileClient as UncachedFileClient2 } from "@uniformdev/files";
2298
+ import { UncachedFileClient as UncachedFileClient4 } from "@uniformdev/files";
2192
2299
  var CompositionPushModule = {
2193
2300
  command: "push <directory>",
2194
2301
  describe: "Pushes all compositions from files in a directory to Uniform Canvas",
@@ -2258,7 +2365,7 @@ var CompositionPushModule = {
2258
2365
  });
2259
2366
  }
2260
2367
  const target = createComponentInstanceEngineDataSource({ client, state, onlyCompositions, onlyPatterns });
2261
- const fileClient = new UncachedFileClient2({ apiKey, apiHost, fetch: fetch3, projectId });
2368
+ const fileClient = new UncachedFileClient4({ apiKey, apiHost, fetch: fetch3, projectId });
2262
2369
  await syncEngine({
2263
2370
  source,
2264
2371
  target,
@@ -3061,6 +3168,7 @@ var EntryListModule = {
3061
3168
 
3062
3169
  // src/commands/canvas/commands/entry/pull.ts
3063
3170
  import { ContentClient as ContentClient10 } from "@uniformdev/canvas";
3171
+ import { UncachedFileClient as UncachedFileClient5 } from "@uniformdev/files";
3064
3172
 
3065
3173
  // src/commands/canvas/entryEngineDataSource.ts
3066
3174
  import { convertEntryToPutEntry } from "@uniformdev/canvas";
@@ -3160,6 +3268,7 @@ var EntryPullModule = {
3160
3268
  projectId,
3161
3269
  bypassCache: true
3162
3270
  });
3271
+ const fileClient = new UncachedFileClient5({ apiKey, apiHost, fetch: fetch3, projectId });
3163
3272
  const source = createEntryEngineDataSource({ client, state });
3164
3273
  let target;
3165
3274
  const isPackage = isPathAPackageFile(directory);
@@ -3188,13 +3297,26 @@ var EntryPullModule = {
3188
3297
  mode,
3189
3298
  whatIf,
3190
3299
  allowEmptySource: true,
3191
- log: createSyncEngineConsoleLogger({ diffMode })
3300
+ log: createSyncEngineConsoleLogger({ diffMode }),
3301
+ onBeforeCompareObjects: async (sourceObject, targetObject) => {
3302
+ return replaceRemoteUrlsWithLocalReferences(sourceObject, targetObject, {
3303
+ directory,
3304
+ fileClient
3305
+ });
3306
+ },
3307
+ onBeforeWriteObject: async (sourceObject) => {
3308
+ return extractAndDownloadUniformFilesForObject(sourceObject, {
3309
+ directory,
3310
+ fileClient
3311
+ });
3312
+ }
3192
3313
  });
3193
3314
  }
3194
3315
  };
3195
3316
 
3196
3317
  // src/commands/canvas/commands/entry/push.ts
3197
3318
  import { ContentClient as ContentClient11 } from "@uniformdev/canvas";
3319
+ import { UncachedFileClient as UncachedFileClient6 } from "@uniformdev/files";
3198
3320
  var EntryPushModule = {
3199
3321
  command: "push <directory>",
3200
3322
  describe: "Pushes all entries from files in a directory to Uniform",
@@ -3259,12 +3381,24 @@ var EntryPushModule = {
3259
3381
  });
3260
3382
  }
3261
3383
  const target = createEntryEngineDataSource({ client, state });
3384
+ const fileClient = new UncachedFileClient6({ apiKey, apiHost, fetch: fetch3, projectId });
3262
3385
  await syncEngine({
3263
3386
  source,
3264
3387
  target,
3265
3388
  mode,
3266
3389
  whatIf,
3267
- log: createSyncEngineConsoleLogger({ diffMode })
3390
+ log: createSyncEngineConsoleLogger({ diffMode }),
3391
+ onBeforeCompareObjects: async (sourceObject) => {
3392
+ return swapOutUniformFileUrlsForTargetProject(sourceObject, {
3393
+ fileClient
3394
+ });
3395
+ },
3396
+ onBeforeWriteObject: async (sourceObject) => {
3397
+ return extractAndUploadUniformFilesForObject(sourceObject, {
3398
+ directory,
3399
+ fileClient
3400
+ });
3401
+ }
3268
3402
  });
3269
3403
  }
3270
3404
  };
@@ -7581,6 +7715,7 @@ var SyncPullModule = {
7581
7715
  handler: async ({ serialization, ...otherParams }) => {
7582
7716
  const config2 = serialization;
7583
7717
  const enabledEntities = Object.entries({
7718
+ asset: AssetPullModule,
7584
7719
  category: CategoryPullModule,
7585
7720
  dataType: DataTypePullModule,
7586
7721
  prompt: PromptPullModule,
@@ -7596,8 +7731,7 @@ var SyncPullModule = {
7596
7731
  projectMapNode: ProjectMapNodePullModule,
7597
7732
  redirect: RedirectDefinitionPullModule,
7598
7733
  entry: EntryPullModule,
7599
- contentType: ContentTypePullModule,
7600
- asset: AssetPullModule
7734
+ contentType: ContentTypePullModule
7601
7735
  }).filter(([entityType]) => {
7602
7736
  var _a, _b, _c, _d, _e, _f;
7603
7737
  return Boolean((_a = config2.entitiesConfig) == null ? void 0 : _a[entityType]) && ((_c = (_b = config2.entitiesConfig) == null ? void 0 : _b[entityType]) == null ? void 0 : _c.disabled) !== true && ((_f = (_e = (_d = config2.entitiesConfig) == null ? void 0 : _d[entityType]) == null ? void 0 : _e.pull) == null ? void 0 : _f.disabled) !== true;
@@ -7673,6 +7807,7 @@ var SyncPushModule = {
7673
7807
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
7674
7808
  const config2 = serialization;
7675
7809
  const enabledEntities = Object.entries({
7810
+ asset: AssetPushModule,
7676
7811
  category: CategoryPushModule,
7677
7812
  dataType: DataTypePushModule,
7678
7813
  prompt: PromptPushModule,
@@ -7688,8 +7823,7 @@ var SyncPushModule = {
7688
7823
  projectMapNode: ProjectMapNodePushModule,
7689
7824
  redirect: RedirectDefinitionPushModule,
7690
7825
  contentType: ContentTypePushModule,
7691
- entry: EntryPushModule,
7692
- asset: AssetPushModule
7826
+ entry: EntryPushModule
7693
7827
  }).filter(([entityType]) => {
7694
7828
  var _a2, _b2, _c2, _d2, _e2, _f2;
7695
7829
  return Boolean((_a2 = config2.entitiesConfig) == null ? void 0 : _a2[entityType]) && ((_c2 = (_b2 = config2.entitiesConfig) == null ? void 0 : _b2[entityType]) == null ? void 0 : _c2.disabled) !== true && ((_f2 = (_e2 = (_d2 = config2.entitiesConfig) == null ? void 0 : _d2[entityType]) == null ? void 0 : _e2.push) == null ? void 0 : _f2.disabled) !== true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/cli",
3
- "version": "19.86.0",
3
+ "version": "19.86.1-alpha.11+cb2b44bdd",
4
4
  "description": "Uniform command line interface tool",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./cli.js",
@@ -17,12 +17,12 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "@thi.ng/mime": "^2.2.23",
20
- "@uniformdev/assets": "19.86.0",
21
- "@uniformdev/canvas": "19.86.0",
22
- "@uniformdev/context": "19.86.0",
23
- "@uniformdev/files": "19.86.0",
24
- "@uniformdev/project-map": "19.86.0",
25
- "@uniformdev/redirect": "19.86.0",
20
+ "@uniformdev/assets": "19.86.1-alpha.11+cb2b44bdd",
21
+ "@uniformdev/canvas": "19.86.1-alpha.11+cb2b44bdd",
22
+ "@uniformdev/context": "19.86.1-alpha.11+cb2b44bdd",
23
+ "@uniformdev/files": "19.86.1-alpha.11+cb2b44bdd",
24
+ "@uniformdev/project-map": "19.86.1-alpha.11+cb2b44bdd",
25
+ "@uniformdev/redirect": "19.86.1-alpha.11+cb2b44bdd",
26
26
  "call-bind": "^1.0.2",
27
27
  "colorette": "2.0.20",
28
28
  "cosmiconfig": "8.3.6",
@@ -69,5 +69,5 @@
69
69
  "publishConfig": {
70
70
  "access": "public"
71
71
  },
72
- "gitHead": "33b5e38f48fe693bf6a4b195009222fd34b9e9f3"
72
+ "gitHead": "cb2b44bdd700124c26e17f1840dbb6049030af81"
73
73
  }