@uniformdev/cli 19.194.1-alpha.3 → 19.194.1-alpha.4

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 +284 -94
  2. package/package.json +8 -8
package/dist/index.mjs CHANGED
@@ -460,6 +460,14 @@ import { UncachedFileClient } from "@uniformdev/files";
460
460
 
461
461
  // src/files/index.ts
462
462
  import { preferredType } from "@thi.ng/mime";
463
+ import {
464
+ findParameterInNodeTree,
465
+ getLocalizedPropertyValues,
466
+ isAssetData,
467
+ isAssetParamValue,
468
+ isComposition,
469
+ isEntry
470
+ } from "@uniformdev/canvas";
463
471
  import { FILE_READY_STATE, getFileNameFromUrl } from "@uniformdev/files";
464
472
  import { createHash } from "crypto";
465
473
  import fsj from "fs-jetpack";
@@ -507,6 +515,10 @@ var urlToFileName = (url, hash) => {
507
515
  const fileExtension = urlToFileExtension(url);
508
516
  return `${fileName}${fileExtension ? `.${fileExtension}` : ""}`;
509
517
  };
518
+ var fileIdToFileName = (asset) => {
519
+ const fileExtension = urlToFileExtension(asset.asset.fields?.url?.value ?? "");
520
+ return asset.asset.fields?.file?.value && fileExtension ? `${asset.asset.fields?.file?.value}.${fileExtension}` : "";
521
+ };
510
522
  var getFilesDirectory = (directory) => {
511
523
  const isPackage = isPathAPackageFile(directory);
512
524
  return isPackage ? dirname(directory) : (
@@ -519,10 +531,14 @@ var getFilesDirectory = (directory) => {
519
531
  var getUniformFileUrlMatches = (string) => {
520
532
  return string.matchAll(/"(https:\/\/([^"]*?)?img\.uniform\.(rocks|global)\/([^"]*?))"/g);
521
533
  };
522
- var deleteDownloadedFileByUrl = async (url, options) => {
534
+ var deleteDownloadedFile = async (asset, options) => {
535
+ const fileNameViaURL = urlToFileName(asset.asset.fields?.url?.value ?? "");
536
+ const fileNameViaFileId = fileIdToFileName(asset);
523
537
  const writeDirectory = getFilesDirectory(options.directory);
524
- const fileName = urlToFileName(url);
525
- const fileToDelete = join2(writeDirectory, FILES_DIRECTORY_NAME, fileName);
538
+ let fileToDelete = join2(writeDirectory, FILES_DIRECTORY_NAME, fileNameViaFileId);
539
+ if (!await fsj.existsAsync(fileToDelete)) {
540
+ fileToDelete = join2(writeDirectory, FILES_DIRECTORY_NAME, fileNameViaURL);
541
+ }
526
542
  try {
527
543
  await fsj.removeAsync(fileToDelete);
528
544
  } catch {
@@ -533,46 +549,145 @@ var extractAndDownloadUniformFilesForObject = async (object, options) => {
533
549
  const objectAsString = JSON.stringify(object);
534
550
  const uniformFileUrlMatches = getUniformFileUrlMatches(objectAsString);
535
551
  const writeDirectory = getFilesDirectory(options.directory);
552
+ const urlsToFileIds = /* @__PURE__ */ new Map();
553
+ const uniformObject = object.object;
554
+ if (isAssetData(uniformObject) && uniformObject.asset.fields?.file?.value) {
555
+ const url = uniformObject.asset.fields?.url?.value ?? "";
556
+ const fileId = uniformObject.asset.fields.file.value;
557
+ if (url) {
558
+ try {
559
+ const urlObject = new URL(url);
560
+ const fileExtension = urlToFileExtension(url);
561
+ const fileName = `${fileId}.${fileExtension}`;
562
+ const fileAlreadyExists = await fsj.existsAsync(join2(writeDirectory, FILES_DIRECTORY_NAME, fileName));
563
+ urlsToFileIds.set(url, fileId);
564
+ if (!fileAlreadyExists) {
565
+ const file = await options.fileClient.get({ id: fileId }).catch(() => null);
566
+ if (file) {
567
+ const fetchUrl = `${urlObject.origin}${urlObject.pathname}?format=original`;
568
+ const response = await fetch(fetchUrl);
569
+ if (response.ok) {
570
+ const fileBuffer = await response.arrayBuffer();
571
+ await fsj.writeAsync(
572
+ join2(writeDirectory, FILES_DIRECTORY_NAME, fileName),
573
+ Buffer.from(fileBuffer)
574
+ );
575
+ }
576
+ } else {
577
+ console.warn(`Skipping file ${url} as it does not exist in the project anymore`);
578
+ }
579
+ }
580
+ } catch (e) {
581
+ console.warn(`Failed to download file: id - ${fileId} url - ${url}`, e);
582
+ }
583
+ }
584
+ } else if (isEntry(uniformObject) || isComposition(uniformObject)) {
585
+ const sourceObject = isEntry(uniformObject) ? uniformObject.entry : uniformObject.composition;
586
+ const foundAssetParamValues = findParameterInNodeTree(
587
+ sourceObject,
588
+ (parameter) => parameter.type === "asset"
589
+ );
590
+ for (const foundAssetParamValue of foundAssetParamValues) {
591
+ const assetParamValue = foundAssetParamValue.parameter;
592
+ if (!assetParamValue) {
593
+ continue;
594
+ }
595
+ const allValues = getLocalizedPropertyValues(
596
+ assetParamValue
597
+ );
598
+ for (const [, paramValue] of allValues) {
599
+ if (isAssetParamValue(paramValue)) {
600
+ for (const item of paramValue) {
601
+ const url = item.fields?.url?.value ?? "";
602
+ const fileId = item.fields?.file?.value;
603
+ if (url && fileId) {
604
+ const urlObject = new URL(url);
605
+ const fileExtension = urlToFileExtension(url);
606
+ const fileName = `${fileId}.${fileExtension}`;
607
+ const fileAlreadyExists = await fsj.existsAsync(
608
+ join2(writeDirectory, FILES_DIRECTORY_NAME, fileName)
609
+ );
610
+ urlsToFileIds.set(url, fileId);
611
+ if (!fileAlreadyExists) {
612
+ const file = await options.fileClient.get({ id: fileId }).catch(() => null);
613
+ if (file) {
614
+ const fetchUrl = `${urlObject.origin}${urlObject.pathname}?format=original`;
615
+ const response = await fetch(fetchUrl);
616
+ if (response.ok) {
617
+ const fileBuffer = await response.arrayBuffer();
618
+ await fsj.writeAsync(
619
+ join2(writeDirectory, FILES_DIRECTORY_NAME, fileName),
620
+ Buffer.from(fileBuffer)
621
+ );
622
+ }
623
+ } else {
624
+ console.warn(`Skipping file ${url} as it does not exist in the project anymore`);
625
+ }
626
+ }
627
+ } else {
628
+ console.warn(`Skipping file because it does not have url or fileId`, item);
629
+ }
630
+ }
631
+ }
632
+ }
633
+ }
634
+ }
536
635
  if (uniformFileUrlMatches) {
537
636
  const fileDownloadQueue = new PQueue({ concurrency: 10 });
538
637
  for (const match of uniformFileUrlMatches) {
539
638
  const url = new URL(match[1]);
540
- fileDownloadQueue.add(async () => {
541
- try {
542
- const fileName = urlToFileName(url.toString());
543
- const fileAlreadyExists = await fsj.existsAsync(
544
- join2(writeDirectory, FILES_DIRECTORY_NAME, fileName)
545
- );
546
- if (fileAlreadyExists) {
547
- return;
548
- }
549
- const file = await options.fileClient.get({ url: url.toString() }).catch(() => null);
550
- if (!file) {
551
- console.warn(`Skipping file ${url} as it does not exist in the project anymore`);
552
- return;
553
- }
554
- if (file.sourceId) {
555
- try {
556
- const hashAlreadyExists = await fsj.findAsync(join2(writeDirectory, FILES_DIRECTORY_NAME), {
557
- matching: [file.sourceId, `${file.sourceId}.*`]
558
- });
559
- if (hashAlreadyExists.length > 0) {
560
- return;
639
+ if (!urlsToFileIds.has(url.toString())) {
640
+ fileDownloadQueue.add(async () => {
641
+ try {
642
+ const fileName = urlToFileName(url.toString());
643
+ const fileAlreadyExists = await fsj.existsAsync(
644
+ join2(writeDirectory, FILES_DIRECTORY_NAME, fileName)
645
+ );
646
+ if (fileAlreadyExists) {
647
+ return;
648
+ }
649
+ const file = await options.fileClient.get({ url: url.toString() }).catch(() => null);
650
+ if (!file) {
651
+ console.warn(`Skipping file ${url} as it does not exist in the project anymore`);
652
+ return;
653
+ }
654
+ if (file.sourceId) {
655
+ try {
656
+ const hashAlreadyExists = await fsj.findAsync(join2(writeDirectory, FILES_DIRECTORY_NAME), {
657
+ matching: [file.sourceId, `${file.sourceId}.*`]
658
+ });
659
+ if (hashAlreadyExists.length > 0) {
660
+ return;
661
+ }
662
+ } catch {
561
663
  }
562
- } catch {
563
664
  }
665
+ if (file.id) {
666
+ try {
667
+ const hashAlreadyExists = await fsj.findAsync(join2(writeDirectory, FILES_DIRECTORY_NAME), {
668
+ matching: [file.id, `${file.id}.*`]
669
+ });
670
+ if (hashAlreadyExists.length > 0) {
671
+ return;
672
+ }
673
+ } catch {
674
+ }
675
+ }
676
+ const fetchUrl = `${url.origin}${url.pathname}?format=original`;
677
+ const response = await fetch(fetchUrl);
678
+ if (!response.ok) {
679
+ return;
680
+ }
681
+ const fileBuffer = await response.arrayBuffer();
682
+ await fsj.writeAsync(
683
+ join2(writeDirectory, FILES_DIRECTORY_NAME, fileName),
684
+ Buffer.from(fileBuffer)
685
+ );
686
+ } catch {
687
+ console.warn(`Failed to download file ${url}`);
564
688
  }
565
- const fetchUrl = `${url.origin}${url.pathname}?format=original`;
566
- const response = await fetch(fetchUrl);
567
- if (!response.ok) {
568
- return;
569
- }
570
- const fileBuffer = await response.arrayBuffer();
571
- await fsj.writeAsync(join2(writeDirectory, FILES_DIRECTORY_NAME, fileName), Buffer.from(fileBuffer));
572
- } catch {
573
- console.warn(`Failed to download file ${url}`);
574
- }
575
- });
689
+ });
690
+ }
576
691
  }
577
692
  await fileDownloadQueue.onIdle();
578
693
  }
@@ -681,6 +796,60 @@ var extractAndUploadUniformFilesForObject = async (object, options) => {
681
796
  return JSON.parse(objectAsString);
682
797
  };
683
798
  var swapOutUniformFileUrlsForTargetProject = async (object, options) => {
799
+ const urlReplacements = /* @__PURE__ */ new Map();
800
+ const uniformObject = object.object;
801
+ if (isAssetData(uniformObject) && uniformObject.asset?.fields?.file?.value) {
802
+ const fileId = uniformObject.asset.fields.file.value;
803
+ if (fileId) {
804
+ const file = await options.fileClient.get({ id: fileId });
805
+ if (file.url && uniformObject.asset.fields?.url?.value) {
806
+ urlReplacements.set(uniformObject.asset.fields.url.value, file.url);
807
+ uniformObject.asset.fields = {
808
+ ...uniformObject.asset.fields,
809
+ url: {
810
+ ...uniformObject.asset.fields.url,
811
+ value: file.url
812
+ }
813
+ };
814
+ return object;
815
+ }
816
+ }
817
+ } else if (isEntry(uniformObject) || isComposition(uniformObject)) {
818
+ const sourceObject = isEntry(uniformObject) ? uniformObject.entry : uniformObject.composition;
819
+ const foundAssetParamValues = findParameterInNodeTree(
820
+ sourceObject,
821
+ (parameter) => parameter.type === "asset"
822
+ );
823
+ for (const foundAssetParamValue of foundAssetParamValues) {
824
+ const assetParamValue = foundAssetParamValue.parameter;
825
+ if (!assetParamValue) {
826
+ continue;
827
+ }
828
+ const allValues = getLocalizedPropertyValues(
829
+ assetParamValue
830
+ );
831
+ for (const [, paramValue] of allValues) {
832
+ if (isAssetParamValue(paramValue)) {
833
+ for (const item of paramValue) {
834
+ const fileId = item.fields?.file?.value;
835
+ if (fileId) {
836
+ const file = await options.fileClient.get({ id: fileId });
837
+ if (file.url && item.fields?.url?.value) {
838
+ urlReplacements.set(item.fields.url.value, file.url);
839
+ item.fields = {
840
+ ...item.fields,
841
+ url: {
842
+ ...item.fields.url,
843
+ value: file.url
844
+ }
845
+ };
846
+ }
847
+ }
848
+ }
849
+ }
850
+ }
851
+ }
852
+ }
684
853
  let objectAsString = JSON.stringify(object);
685
854
  const uniformFileUrlMatches = getUniformFileUrlMatches(objectAsString);
686
855
  if (uniformFileUrlMatches) {
@@ -714,58 +883,94 @@ var replaceRemoteUrlsWithLocalReferences = async (sourceObject, targetObject, op
714
883
  const targetObjectAsString = JSON.stringify(targetObject);
715
884
  const uniformFileUrlMatches = getUniformFileUrlMatches(sourceObjectAsString);
716
885
  const writeDirectory = getFilesDirectory(options.directory);
886
+ const urlReplacements = /* @__PURE__ */ new Map();
887
+ if (isAssetData(sourceObject) && sourceObject.asset.fields?.file?.value) {
888
+ const fileId = sourceObject.asset.fields?.file?.value;
889
+ if (fileId) {
890
+ const file = await options.fileClient.get({ id: fileId });
891
+ if (file.url && sourceObject.asset.fields?.url?.value) {
892
+ urlReplacements.set(sourceObject.asset.fields.url.value, file.url);
893
+ sourceObject.asset.fields = {
894
+ ...sourceObject.asset.fields,
895
+ url: {
896
+ ...sourceObject.asset.fields.url,
897
+ value: file.url
898
+ }
899
+ };
900
+ return sourceObject;
901
+ }
902
+ }
903
+ } else if (isEntry(sourceObject) || isComposition(sourceObject)) {
904
+ const object = isEntry(sourceObject) ? sourceObject.entry : sourceObject.composition;
905
+ const foundAssetParamValues = findParameterInNodeTree(object, (parameter) => parameter.type === "asset");
906
+ for (const foundAssetParamValue of foundAssetParamValues) {
907
+ const assetParamValue = foundAssetParamValue.parameter;
908
+ if (!assetParamValue) {
909
+ continue;
910
+ }
911
+ const allValues = getLocalizedPropertyValues(
912
+ assetParamValue
913
+ );
914
+ for (const [, paramValue] of allValues) {
915
+ if (isAssetParamValue(paramValue)) {
916
+ for (const item of paramValue) {
917
+ const fileId = item.fields?.file?.value;
918
+ if (fileId) {
919
+ const file = await options.fileClient.get({ id: fileId });
920
+ if (file.url && item.fields?.url?.value) {
921
+ urlReplacements.set(item.fields.url.value, file.url);
922
+ item.fields = {
923
+ ...item.fields,
924
+ url: {
925
+ ...item.fields.url,
926
+ value: file.url
927
+ }
928
+ };
929
+ }
930
+ }
931
+ }
932
+ }
933
+ }
934
+ }
935
+ }
717
936
  if (uniformFileUrlMatches) {
718
937
  const fileUrlReplacementQueue = new PQueue({ concurrency: 3 });
719
938
  for (const match of uniformFileUrlMatches) {
720
939
  const url = match[1];
721
- fileUrlReplacementQueue.add(async () => {
722
- try {
723
- const localFileName = urlToFileName(url);
724
- const fileExistsLocally = await fsj.existsAsync(
725
- join2(writeDirectory, FILES_DIRECTORY_NAME, localFileName)
726
- );
727
- if (fileExistsLocally) {
728
- return;
729
- }
730
- const file = await options.fileClient.get({ url }).catch(() => null);
731
- if (!file || !file.sourceId) {
732
- return;
733
- }
734
- const originalPartialPath = hashToPartialPathname(file.sourceId);
735
- if (!originalPartialPath) {
736
- return;
737
- }
738
- const originalUrl = findUrlMatchingPartialPathname(targetObjectAsString, originalPartialPath);
739
- if (!originalUrl) {
740
- return;
940
+ if (urlReplacements.has(url)) {
941
+ sourceObjectAsString = sourceObjectAsString.replaceAll(`"${url}"`, `"${urlReplacements.get(url)}"`);
942
+ } else {
943
+ fileUrlReplacementQueue.add(async () => {
944
+ try {
945
+ const localFileName = urlToFileName(url);
946
+ const fileExistsLocally = await fsj.existsAsync(
947
+ join2(writeDirectory, FILES_DIRECTORY_NAME, localFileName)
948
+ );
949
+ if (fileExistsLocally) {
950
+ return;
951
+ }
952
+ const file = await options.fileClient.get({ url }).catch(() => null);
953
+ if (!file || !file.sourceId) {
954
+ return;
955
+ }
956
+ const originalPartialPath = hashToPartialPathname(file.sourceId);
957
+ if (!originalPartialPath) {
958
+ return;
959
+ }
960
+ const originalUrl = findUrlMatchingPartialPathname(targetObjectAsString, originalPartialPath);
961
+ if (!originalUrl) {
962
+ return;
963
+ }
964
+ sourceObjectAsString = sourceObjectAsString.replaceAll(`"${url}"`, `"${originalUrl}"`);
965
+ } catch {
741
966
  }
742
- sourceObjectAsString = sourceObjectAsString.replaceAll(`"${url}"`, `"${originalUrl}"`);
743
- } catch {
744
- }
745
- });
967
+ });
968
+ }
746
969
  }
747
970
  await fileUrlReplacementQueue.onIdle();
748
971
  }
749
972
  return JSON.parse(sourceObjectAsString);
750
973
  };
751
- var updateAssetFileIdBasedOnUrl = async (asset, options) => {
752
- if (!asset.asset.fields) {
753
- return asset;
754
- }
755
- const fileUrl = asset.asset.fields.url?.value;
756
- if (!fileUrl) {
757
- return asset;
758
- }
759
- const file = await options.fileClient.get({ url: fileUrl }).catch(() => null);
760
- if (!file) {
761
- return asset;
762
- }
763
- asset.asset.fields.file = {
764
- type: "file",
765
- value: file.id
766
- };
767
- return asset;
768
- };
769
974
  var legacyUrlToHash = (url) => {
770
975
  const hash = createHash("sha256");
771
976
  hash.update(url);
@@ -922,7 +1127,7 @@ var AssetPullModule = {
922
1127
  if (!asset.asset.fields?.url?.value) {
923
1128
  return;
924
1129
  }
925
- await deleteDownloadedFileByUrl(asset.asset.fields.url.value, {
1130
+ await deleteDownloadedFile(asset, {
926
1131
  directory
927
1132
  });
928
1133
  };
@@ -965,9 +1170,6 @@ var AssetPullModule = {
965
1170
  fileClient
966
1171
  }
967
1172
  );
968
- if (sourceObjectWithPotentiallySwappedUrl.object.asset.fields?.url && targetObject.object.asset.fields?.url && sourceObjectWithPotentiallySwappedUrl.object.asset.fields.url.value === targetObject.object.asset.fields.url.value) {
969
- targetObject.object.asset.fields.file = sourceObjectWithPotentiallySwappedUrl.object.asset.fields.file;
970
- }
971
1173
  return sourceObjectWithPotentiallySwappedUrl;
972
1174
  },
973
1175
  onBeforeWriteObject: async (sourceObject) => {
@@ -1061,12 +1263,6 @@ var AssetPushModule = {
1061
1263
  const sourceObjectWithNewFileUrls = await swapOutUniformFileUrlsForTargetProject(sourceObject, {
1062
1264
  fileClient
1063
1265
  });
1064
- sourceObjectWithNewFileUrls.object = await updateAssetFileIdBasedOnUrl(
1065
- sourceObjectWithNewFileUrls.object,
1066
- {
1067
- fileClient
1068
- }
1069
- );
1070
1266
  return sourceObjectWithNewFileUrls;
1071
1267
  },
1072
1268
  onBeforeWriteObject: async (sourceObject) => {
@@ -1074,12 +1270,6 @@ var AssetPushModule = {
1074
1270
  directory,
1075
1271
  fileClient
1076
1272
  });
1077
- sourceObjectWithNewFileUrls.object = await updateAssetFileIdBasedOnUrl(
1078
- sourceObjectWithNewFileUrls.object,
1079
- {
1080
- fileClient
1081
- }
1082
- );
1083
1273
  return sourceObjectWithNewFileUrls;
1084
1274
  }
1085
1275
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/cli",
3
- "version": "19.194.1-alpha.3+9ba3c9e6f0",
3
+ "version": "19.194.1-alpha.4+a46691a815",
4
4
  "description": "Uniform command line interface tool",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./cli.js",
@@ -27,12 +27,12 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@thi.ng/mime": "^2.2.23",
30
- "@uniformdev/assets": "19.194.1-alpha.3+9ba3c9e6f0",
31
- "@uniformdev/canvas": "19.194.1-alpha.3+9ba3c9e6f0",
32
- "@uniformdev/context": "19.194.1-alpha.3+9ba3c9e6f0",
33
- "@uniformdev/files": "19.194.1-alpha.3+9ba3c9e6f0",
34
- "@uniformdev/project-map": "19.194.1-alpha.3+9ba3c9e6f0",
35
- "@uniformdev/redirect": "19.194.1-alpha.3+9ba3c9e6f0",
30
+ "@uniformdev/assets": "19.194.1-alpha.4+a46691a815",
31
+ "@uniformdev/canvas": "19.194.1-alpha.4+a46691a815",
32
+ "@uniformdev/context": "19.194.1-alpha.4+a46691a815",
33
+ "@uniformdev/files": "19.194.1-alpha.4+a46691a815",
34
+ "@uniformdev/project-map": "19.194.1-alpha.4+a46691a815",
35
+ "@uniformdev/redirect": "19.194.1-alpha.4+a46691a815",
36
36
  "call-bind": "^1.0.2",
37
37
  "colorette": "2.0.20",
38
38
  "cosmiconfig": "9.0.0",
@@ -78,5 +78,5 @@
78
78
  "publishConfig": {
79
79
  "access": "public"
80
80
  },
81
- "gitHead": "9ba3c9e6f09642d4f7e77a9f4b90f416f2521073"
81
+ "gitHead": "a46691a815b94e40c8f5e8d982e2cf66938a4548"
82
82
  }