@uniformdev/cli 20.7.1-alpha.63 → 20.7.1-alpha.67

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/LICENSE.txt CHANGED
@@ -1,2 +1,2 @@
1
- © 2024 Uniform Systems, Inc. All Rights Reserved.
1
+ © 2025 Uniform Systems, Inc. All Rights Reserved.
2
2
  See details of Uniform Systems, Inc. Master Subscription Agreement here: https://uniform.dev/eula
@@ -18,6 +18,57 @@ import { mkdirSync, readFileSync, writeFileSync } from "fs";
18
18
  import { dump, load } from "js-yaml";
19
19
  import { dirname, extname, isAbsolute, resolve, sep } from "path";
20
20
  import { fetch as undiciFetch, ProxyAgent } from "undici";
21
+
22
+ // src/sync/windowsRetry.ts
23
+ var RETRIABLE_ERRORS = [
24
+ "ECONNRESET",
25
+ "ECONNREFUSED",
26
+ "ENOTFOUND",
27
+ "ETIMEDOUT",
28
+ "ESOCKETTIMEDOUT",
29
+ "read ECONNRESET",
30
+ "write ECONNRESET",
31
+ "socket hang up",
32
+ "fetch failed"
33
+ ];
34
+ var isWindows = process.platform === "win32";
35
+ var isRetriableError = (error) => {
36
+ if (!(error instanceof Error)) return false;
37
+ const errorMessage = error.message.toLowerCase();
38
+ const errorCode = error.code?.toLowerCase();
39
+ return RETRIABLE_ERRORS.some(
40
+ (pattern) => errorMessage.includes(pattern.toLowerCase()) || errorCode?.includes(pattern.toLowerCase())
41
+ );
42
+ };
43
+ var retryWithBackoff = async (operation, maxRetries = isWindows ? 5 : 3, baseDelay = isWindows ? 2e3 : 1e3, verbose = false) => {
44
+ let lastError;
45
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
46
+ try {
47
+ return await operation();
48
+ } catch (error) {
49
+ lastError = error;
50
+ if (!isRetriableError(error) || attempt === maxRetries) {
51
+ throw error;
52
+ }
53
+ const delay = baseDelay * Math.pow(2, attempt - 1) + Math.random() * 1e3;
54
+ if (verbose) {
55
+ console.log(
56
+ `\u{1F504} Retrying operation (attempt ${attempt}/${maxRetries}) after ${Math.round(delay)}ms due to: ${error.message}`
57
+ );
58
+ }
59
+ await new Promise((resolve2) => setTimeout(resolve2, delay));
60
+ }
61
+ }
62
+ throw lastError;
63
+ };
64
+ var createFetchWithRetry = (baseFetch, verbose = false) => {
65
+ return async (input, init) => {
66
+ const fetchOperation = () => baseFetch(input, init);
67
+ return retryWithBackoff(fetchOperation, 5, 2e3, verbose);
68
+ };
69
+ };
70
+
71
+ // src/sync/util.ts
21
72
  function withConfiguration(yargs) {
22
73
  return yargs.option("serialization", {
23
74
  skipValidation: true,
@@ -65,7 +116,7 @@ function nodeFetchProxy(proxy, verbose) {
65
116
  if (proxy) {
66
117
  console.log(`\u{1F991} Using proxy ${proxy}`);
67
118
  }
68
- const wrappedFetch = (input, init) => {
119
+ const baseFetch = (input, init) => {
69
120
  const handleFetchError = (e) => {
70
121
  if (e instanceof Error) {
71
122
  e.message = `Error fetching ${input.toString()}
@@ -91,6 +142,7 @@ ${e.message}`;
91
142
  handleFetchError
92
143
  );
93
144
  };
145
+ const wrappedFetch = createFetchWithRetry(baseFetch, verbose);
94
146
  if (verbose) {
95
147
  return async function fetchWithVerboseLogging(input, init) {
96
148
  const method = init?.method ?? "GET";
@@ -1,4 +1,4 @@
1
- import "./chunk-JSQVEK7R.mjs";
1
+ import "./chunk-WMBIETON.mjs";
2
2
 
3
3
  // src/sync/allSerializableEntitiesConfig.ts
4
4
  var allSerializableEntitiesConfig = {
package/dist/index.mjs CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  withFormatOptions,
17
17
  withProjectOptions,
18
18
  withTeamOptions
19
- } from "./chunk-JSQVEK7R.mjs";
19
+ } from "./chunk-WMBIETON.mjs";
20
20
 
21
21
  // src/index.ts
22
22
  import * as dotenv from "dotenv";
@@ -312,6 +312,7 @@ async function syncEngine({
312
312
  whatIf = false,
313
313
  log: log2 = () => {
314
314
  },
315
+ onBeforeProcessObject,
315
316
  onBeforeCompareObjects,
316
317
  onBeforeWriteObject,
317
318
  onError
@@ -357,6 +358,9 @@ async function syncEngine({
357
358
  let sourceHasItems = false;
358
359
  for await (let sourceObject of source.objects) {
359
360
  sourceHasItems = true;
361
+ if (onBeforeProcessObject) {
362
+ await onBeforeProcessObject(sourceObject);
363
+ }
360
364
  const ids = Array.isArray(sourceObject.id) ? sourceObject.id : [sourceObject.id];
361
365
  const targetObject = targetItems.get(ids[0]);
362
366
  status.compared++;
@@ -853,7 +857,7 @@ import {
853
857
  walkNodeTree,
854
858
  walkPropertyValues
855
859
  } from "@uniformdev/canvas";
856
- var UNIFORM_FILE_MATCH = /"(https:\/\/([^"]*?)?(img|files)\.uniform\.(rocks|global)\/([^"]*?))"/g;
860
+ var UNIFORM_FILE_MATCH = /"(https:\/\/([^"]*?)?(img|files)\.(eu\.)?uniform\.(rocks|global)\/([^"]*?))"/g;
857
861
  var walkFileUrlsForCompositionOrEntry = ({
858
862
  entity,
859
863
  callback
@@ -2603,128 +2607,131 @@ var ComponentPatternPublishModule = {
2603
2607
  };
2604
2608
 
2605
2609
  // src/commands/canvas/commands/composition/pull.ts
2606
- var CompositionPullModule = {
2607
- command: "pull <directory>",
2608
- describe: "Pulls all compositions to local files in a directory",
2609
- builder: (yargs35) => withConfiguration(
2610
- withApiOptions(
2611
- withProjectOptions(
2612
- withStateOptions(
2613
- withDebugOptions(
2614
- withDiffOptions(
2615
- yargs35.positional("directory", {
2616
- describe: "Directory to save the component definitions to. If a filename ending in yaml or json is used, a package file will be created instead of files in the directory.",
2617
- type: "string"
2618
- }).option("format", {
2619
- alias: ["f"],
2620
- describe: "Output format",
2621
- default: "yaml",
2622
- choices: ["yaml", "json"],
2623
- type: "string"
2624
- }).option("onlyCompositions", {
2625
- describe: "Only pulling compositions and not patterns",
2626
- default: false,
2627
- type: "boolean"
2628
- }).option("onlyPatterns", {
2629
- describe: "Only pulling patterns and not compositions",
2630
- default: false,
2631
- type: "boolean",
2632
- hidden: true
2633
- }).option("mode", {
2634
- alias: ["m"],
2635
- describe: 'What kind of changes can be made. "create" = create new files, update nothing. "createOrUpdate" = create new files, update existing, delete nothing. "mirror" = create, update, and delete to mirror state',
2636
- choices: ["create", "createOrUpdate", "mirror"],
2637
- default: "mirror",
2638
- type: "string"
2639
- })
2610
+ var CompositionPullModule = componentInstancePullModuleFactory("compositions");
2611
+ function componentInstancePullModuleFactory(type) {
2612
+ return {
2613
+ command: "pull <directory>",
2614
+ describe: "Pulls all compositions to local files in a directory",
2615
+ builder: (yargs35) => withConfiguration(
2616
+ withApiOptions(
2617
+ withProjectOptions(
2618
+ withStateOptions(
2619
+ withDebugOptions(
2620
+ withDiffOptions(
2621
+ yargs35.positional("directory", {
2622
+ describe: "Directory to save the component definitions to. If a filename ending in yaml or json is used, a package file will be created instead of files in the directory.",
2623
+ type: "string"
2624
+ }).option("format", {
2625
+ alias: ["f"],
2626
+ describe: "Output format",
2627
+ default: "yaml",
2628
+ choices: ["yaml", "json"],
2629
+ type: "string"
2630
+ }).option("onlyCompositions", {
2631
+ describe: "Only pulling compositions and not patterns",
2632
+ default: false,
2633
+ type: "boolean"
2634
+ }).option("onlyPatterns", {
2635
+ describe: "Only pulling patterns and not compositions",
2636
+ default: false,
2637
+ type: "boolean",
2638
+ hidden: true
2639
+ }).option("mode", {
2640
+ alias: ["m"],
2641
+ describe: 'What kind of changes can be made. "create" = create new files, update nothing. "createOrUpdate" = create new files, update existing, delete nothing. "mirror" = create, update, and delete to mirror state',
2642
+ choices: ["create", "createOrUpdate", "mirror"],
2643
+ default: "mirror",
2644
+ type: "string"
2645
+ })
2646
+ )
2640
2647
  )
2641
2648
  )
2642
2649
  )
2643
2650
  )
2644
- )
2645
- ),
2646
- handler: async ({
2647
- apiHost,
2648
- apiKey,
2649
- proxy,
2650
- directory,
2651
- format,
2652
- onlyCompositions,
2653
- onlyPatterns,
2654
- patternType = "all",
2655
- mode,
2656
- whatIf,
2657
- state,
2658
- project: projectId,
2659
- diff: diffMode,
2660
- allowEmptySource,
2661
- verbose
2662
- }) => {
2663
- const fetch2 = nodeFetchProxy(proxy, verbose);
2664
- const client = getCanvasClient({ apiKey, apiHost, fetch: fetch2, projectId });
2665
- const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
2666
- const source = createComponentInstanceEngineDataSource({
2667
- client,
2668
- state,
2651
+ ),
2652
+ handler: async ({
2653
+ apiHost,
2654
+ apiKey,
2655
+ proxy,
2656
+ directory,
2657
+ format,
2669
2658
  onlyCompositions,
2670
2659
  onlyPatterns,
2671
- patternType,
2660
+ patternType = "all",
2661
+ mode,
2662
+ whatIf,
2663
+ state,
2664
+ project: projectId,
2665
+ diff: diffMode,
2666
+ allowEmptySource,
2672
2667
  verbose
2673
- });
2674
- const isPackage = isPathAPackageFile(directory);
2675
- let target;
2676
- if (isPackage) {
2677
- const packageContents = readCanvasPackage(directory, false, verbose);
2678
- target = await createArraySyncEngineDataSource({
2679
- name: `Package file ${directory}`,
2680
- objects: packageContents?.compositions ?? [],
2681
- selectIdentifier: selectIdentifier3,
2682
- selectDisplayName: selectDisplayName3,
2683
- onSyncComplete: async (_, synced) => {
2684
- packageContents.compositions = synced;
2685
- writeCanvasPackage(directory, packageContents);
2686
- }
2687
- });
2688
- } else {
2689
- target = await createFileSyncEngineDataSource({
2690
- directory,
2691
- selectIdentifier: selectIdentifier3,
2692
- selectDisplayName: selectDisplayName3,
2693
- format,
2668
+ }) => {
2669
+ const fetch2 = nodeFetchProxy(proxy, verbose);
2670
+ const client = getCanvasClient({ apiKey, apiHost, fetch: fetch2, projectId });
2671
+ const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
2672
+ const source = createComponentInstanceEngineDataSource({
2673
+ client,
2674
+ state,
2675
+ onlyCompositions,
2676
+ onlyPatterns,
2677
+ patternType,
2694
2678
  verbose
2695
2679
  });
2696
- }
2697
- await syncEngine({
2698
- source,
2699
- target,
2700
- mode,
2701
- whatIf,
2702
- allowEmptySource: allowEmptySource ?? true,
2703
- log: createSyncEngineConsoleLogger({ diffMode }),
2704
- onBeforeCompareObjects: async (sourceObject, targetObject) => {
2705
- return replaceRemoteUrlsWithLocalReferences({
2706
- sourceEntity: sourceObject,
2707
- targetEntity: targetObject,
2708
- directory,
2709
- fileClient
2680
+ const isPackage = isPathAPackageFile(directory);
2681
+ let target;
2682
+ if (isPackage) {
2683
+ const packageContents = readCanvasPackage(directory, false, verbose);
2684
+ target = await createArraySyncEngineDataSource({
2685
+ name: `Package file ${directory}`,
2686
+ objects: packageContents?.[type] ?? [],
2687
+ selectIdentifier: selectIdentifier3,
2688
+ selectDisplayName: selectDisplayName3,
2689
+ onSyncComplete: async (_, synced) => {
2690
+ packageContents[type] = synced;
2691
+ writeCanvasPackage(directory, packageContents);
2692
+ }
2710
2693
  });
2711
- },
2712
- compareContents: compareCompositionsOrEntriesWithoutAssetUrls,
2713
- onBeforeWriteObject: async (sourceObject) => {
2714
- await downloadFilesForCompositionOrEntry({
2715
- entity: sourceObject.object,
2694
+ } else {
2695
+ target = await createFileSyncEngineDataSource({
2716
2696
  directory,
2717
- fileClient
2697
+ selectIdentifier: selectIdentifier3,
2698
+ selectDisplayName: selectDisplayName3,
2699
+ format,
2700
+ verbose
2718
2701
  });
2719
- return sourceObject;
2720
2702
  }
2721
- });
2722
- }
2723
- };
2703
+ await syncEngine({
2704
+ source,
2705
+ target,
2706
+ mode,
2707
+ whatIf,
2708
+ allowEmptySource: allowEmptySource ?? true,
2709
+ log: createSyncEngineConsoleLogger({ diffMode }),
2710
+ onBeforeCompareObjects: async (sourceObject, targetObject) => {
2711
+ return replaceRemoteUrlsWithLocalReferences({
2712
+ sourceEntity: sourceObject,
2713
+ targetEntity: targetObject,
2714
+ directory,
2715
+ fileClient
2716
+ });
2717
+ },
2718
+ compareContents: compareCompositionsOrEntriesWithoutAssetUrls,
2719
+ onBeforeWriteObject: async (sourceObject) => {
2720
+ await downloadFilesForCompositionOrEntry({
2721
+ entity: sourceObject.object,
2722
+ directory,
2723
+ fileClient
2724
+ });
2725
+ return sourceObject;
2726
+ }
2727
+ });
2728
+ }
2729
+ };
2730
+ }
2724
2731
 
2725
2732
  // src/commands/canvas/commands/componentPattern/pull.ts
2726
2733
  var ComponentPatternPullModule = {
2727
- ...CompositionPullModule,
2734
+ ...componentInstancePullModuleFactory("componentPatterns"),
2728
2735
  describe: "Pulls all component patterns to local files in a directory",
2729
2736
  builder: (yargs35) => withConfiguration(
2730
2737
  withApiOptions(
@@ -2748,6 +2755,7 @@ var ComponentPatternPullModule = {
2748
2755
  type: "boolean",
2749
2756
  hidden: true
2750
2757
  }).option("patternType", {
2758
+ // This default differentiate this list command from composition list command
2751
2759
  default: "component",
2752
2760
  choices: ["all", "component", "composition"],
2753
2761
  hidden: true
@@ -2771,115 +2779,159 @@ var ComponentPatternPullModule = {
2771
2779
  )
2772
2780
  };
2773
2781
 
2782
+ // src/commands/canvas/util/localeValidation.ts
2783
+ import { LocaleClient } from "@uniformdev/canvas";
2784
+ async function fetchUniformLocales(options) {
2785
+ const client = new LocaleClient({
2786
+ ...options,
2787
+ bypassCache: true,
2788
+ limitPolicy: cliLimitPolicy
2789
+ });
2790
+ const locales = (await client.get()).results;
2791
+ return new Set(locales.map((locale) => locale.locale));
2792
+ }
2793
+ function validateEntityLocales(entity, uniformLocales, entityName) {
2794
+ if (!entity._locales || entity._locales.length === 0) {
2795
+ return;
2796
+ }
2797
+ const invalidLocales = entity._locales.filter((locale) => !uniformLocales.has(locale));
2798
+ if (invalidLocales.length > 0) {
2799
+ console.warn(
2800
+ `\u26A0\uFE0F ${entityName} enables locale${invalidLocales.length > 1 ? "s" : ""} ${invalidLocales.join(", ")} that are not registered in your Uniform project. This may cause unexpected behavior.`
2801
+ );
2802
+ }
2803
+ }
2804
+ function createLocaleValidationHook(uniformLocales) {
2805
+ return async (entity) => {
2806
+ validateEntityLocales(entity, uniformLocales, entity.displayName);
2807
+ };
2808
+ }
2809
+
2774
2810
  // src/commands/canvas/commands/composition/push.ts
2775
- var CompositionPushModule = {
2776
- command: "push <directory>",
2777
- describe: "Pushes all compositions from files in a directory to Uniform Canvas",
2778
- builder: (yargs35) => withConfiguration(
2779
- withApiOptions(
2780
- withProjectOptions(
2781
- withStateOptions(
2782
- withDebugOptions(
2783
- withDiffOptions(
2784
- yargs35.positional("directory", {
2785
- describe: "Directory to read the compositions/patterns from. If a filename is used, a package will be read instead.",
2786
- type: "string"
2787
- }).option("mode", {
2788
- alias: ["m"],
2789
- describe: 'What kind of changes can be made. "create" = create new, update nothing. "createOrUpdate" = create new, update existing, delete nothing. "mirror" = create, update, and delete',
2790
- choices: ["create", "createOrUpdate", "mirror"],
2791
- default: "mirror",
2792
- type: "string"
2793
- }).option("onlyCompositions", {
2794
- describe: "Only pulling compositions and not patterns",
2795
- default: false,
2796
- type: "boolean"
2797
- }).option("onlyPatterns", {
2798
- describe: "Only pulling patterns and not compositions",
2799
- default: false,
2800
- type: "boolean",
2801
- hidden: true
2802
- })
2811
+ var CompositionPushModule = componentInstancePushModuleFactory("compositions");
2812
+ function componentInstancePushModuleFactory(type) {
2813
+ return {
2814
+ command: "push <directory>",
2815
+ describe: "Pushes all compositions from files in a directory to Uniform Canvas",
2816
+ builder: (yargs35) => withConfiguration(
2817
+ withApiOptions(
2818
+ withProjectOptions(
2819
+ withStateOptions(
2820
+ withDebugOptions(
2821
+ withDiffOptions(
2822
+ yargs35.positional("directory", {
2823
+ describe: "Directory to read the compositions/patterns from. If a filename is used, a package will be read instead.",
2824
+ type: "string"
2825
+ }).option("mode", {
2826
+ alias: ["m"],
2827
+ describe: 'What kind of changes can be made. "create" = create new, update nothing. "createOrUpdate" = create new, update existing, delete nothing. "mirror" = create, update, and delete',
2828
+ choices: ["create", "createOrUpdate", "mirror"],
2829
+ default: "mirror",
2830
+ type: "string"
2831
+ }).option("onlyCompositions", {
2832
+ describe: "Only pulling compositions and not patterns",
2833
+ default: false,
2834
+ type: "boolean"
2835
+ }).option("onlyPatterns", {
2836
+ // backwards compatibility
2837
+ default: false,
2838
+ type: "boolean",
2839
+ hidden: true
2840
+ })
2841
+ )
2803
2842
  )
2804
2843
  )
2805
2844
  )
2806
2845
  )
2807
- )
2808
- ),
2809
- handler: async ({
2810
- apiHost,
2811
- apiKey,
2812
- proxy,
2813
- directory,
2814
- mode,
2815
- whatIf,
2816
- state,
2817
- project: projectId,
2818
- onlyCompositions,
2819
- onlyPatterns,
2820
- patternType,
2821
- diff: diffMode,
2822
- allowEmptySource,
2823
- verbose
2824
- }) => {
2825
- const fetch2 = nodeFetchProxy(proxy, verbose);
2826
- const client = getCanvasClient({ apiKey, apiHost, fetch: fetch2, projectId });
2827
- let source;
2828
- const isPackage = isPathAPackageFile(directory);
2829
- if (isPackage) {
2830
- const packageContents = readCanvasPackage(directory, true, verbose);
2831
- source = await createArraySyncEngineDataSource({
2832
- name: `Package file ${directory}`,
2833
- objects: packageContents.compositions ?? [],
2834
- selectIdentifier: selectIdentifier3,
2835
- selectDisplayName: selectDisplayName3
2836
- });
2837
- } else {
2838
- source = await createFileSyncEngineDataSource({
2839
- directory,
2840
- selectIdentifier: selectIdentifier3,
2841
- selectDisplayName: selectDisplayName3,
2842
- verbose
2843
- });
2844
- }
2845
- const target = createComponentInstanceEngineDataSource({
2846
- client,
2846
+ ),
2847
+ handler: async ({
2848
+ apiHost,
2849
+ apiKey,
2850
+ proxy,
2851
+ directory,
2852
+ mode,
2853
+ whatIf,
2847
2854
  state,
2855
+ project: projectId,
2848
2856
  onlyCompositions,
2849
2857
  onlyPatterns,
2850
2858
  patternType,
2851
- verbose
2852
- });
2853
- const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
2854
- await syncEngine({
2855
- source,
2856
- target,
2857
- mode,
2858
- whatIf,
2859
- verbose,
2859
+ diff: diffMode,
2860
2860
  allowEmptySource,
2861
- log: createSyncEngineConsoleLogger({ diffMode }),
2862
- onBeforeCompareObjects: async (sourceObject) => {
2863
- return replaceLocalUrlsWithRemoteReferences({
2864
- entity: sourceObject,
2865
- fileClient
2861
+ verbose
2862
+ }) => {
2863
+ const fetch2 = nodeFetchProxy(proxy, verbose);
2864
+ const client = getCanvasClient({ apiKey, apiHost, fetch: fetch2, projectId });
2865
+ let source;
2866
+ const isPackage = isPathAPackageFile(directory);
2867
+ if (isPackage) {
2868
+ const packageContents = readCanvasPackage(directory, true, verbose);
2869
+ source = await createArraySyncEngineDataSource({
2870
+ name: `Package file ${directory}`,
2871
+ objects: packageContents[type] ?? [],
2872
+ selectIdentifier: selectIdentifier3,
2873
+ selectDisplayName: selectDisplayName3
2866
2874
  });
2867
- },
2868
- compareContents: compareCompositionsOrEntriesWithoutAssetUrls,
2869
- onBeforeWriteObject: async (sourceObject) => {
2870
- return uploadFilesForCompositionOrEntry({
2871
- entity: sourceObject,
2875
+ } else {
2876
+ source = await createFileSyncEngineDataSource({
2872
2877
  directory,
2873
- fileClient
2878
+ selectIdentifier: selectIdentifier3,
2879
+ selectDisplayName: selectDisplayName3,
2880
+ verbose
2874
2881
  });
2875
2882
  }
2876
- });
2877
- }
2878
- };
2883
+ const target = createComponentInstanceEngineDataSource({
2884
+ client,
2885
+ state,
2886
+ onlyCompositions,
2887
+ onlyPatterns,
2888
+ patternType,
2889
+ verbose
2890
+ });
2891
+ const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
2892
+ const uniformLocales = await fetchUniformLocales({
2893
+ apiKey,
2894
+ apiHost,
2895
+ fetch: fetch2,
2896
+ projectId
2897
+ });
2898
+ const localeValidationHook = createLocaleValidationHook(uniformLocales);
2899
+ await syncEngine({
2900
+ source,
2901
+ target,
2902
+ mode,
2903
+ whatIf,
2904
+ verbose,
2905
+ allowEmptySource,
2906
+ log: createSyncEngineConsoleLogger({ diffMode }),
2907
+ onBeforeProcessObject: async (sourceObject) => {
2908
+ await localeValidationHook({
2909
+ _locales: sourceObject.object.composition._locales,
2910
+ displayName: sourceObject.displayName ?? sourceObject.providerId
2911
+ });
2912
+ },
2913
+ onBeforeCompareObjects: async (sourceObject) => {
2914
+ return replaceLocalUrlsWithRemoteReferences({
2915
+ entity: sourceObject,
2916
+ fileClient
2917
+ });
2918
+ },
2919
+ compareContents: compareCompositionsOrEntriesWithoutAssetUrls,
2920
+ onBeforeWriteObject: async (sourceObject) => {
2921
+ return uploadFilesForCompositionOrEntry({
2922
+ entity: sourceObject,
2923
+ directory,
2924
+ fileClient
2925
+ });
2926
+ }
2927
+ });
2928
+ }
2929
+ };
2930
+ }
2879
2931
 
2880
2932
  // src/commands/canvas/commands/componentPattern/push.ts
2881
2933
  var ComponentPatternPushModule = {
2882
- ...CompositionPushModule,
2934
+ ...componentInstancePushModuleFactory("componentPatterns"),
2883
2935
  describe: "Pushes all component patterns from files in a directory to Uniform Canvas",
2884
2936
  builder: (yargs35) => withConfiguration(
2885
2937
  withApiOptions(
@@ -2903,6 +2955,7 @@ var ComponentPatternPushModule = {
2903
2955
  type: "boolean",
2904
2956
  hidden: true
2905
2957
  }).option("patternType", {
2958
+ // This default differentiate this list command from composition list command
2906
2959
  default: "component",
2907
2960
  choices: ["all", "component", "composition"],
2908
2961
  hidden: true
@@ -3263,7 +3316,7 @@ var CompositionPatternPublishModule = {
3263
3316
 
3264
3317
  // src/commands/canvas/commands/compositionPattern/pull.ts
3265
3318
  var CompositionPatternPullModule = {
3266
- ...CompositionPullModule,
3319
+ ...componentInstancePullModuleFactory("compositionPatterns"),
3267
3320
  describe: "Pulls all composition patterns to local files in a directory",
3268
3321
  builder: (yargs35) => withConfiguration(
3269
3322
  withApiOptions(
@@ -3307,7 +3360,7 @@ var CompositionPatternPullModule = {
3307
3360
 
3308
3361
  // src/commands/canvas/commands/compositionPattern/push.ts
3309
3362
  var CompositionPatternPushModule = {
3310
- ...CompositionPushModule,
3363
+ ...componentInstancePushModuleFactory("compositionPatterns"),
3311
3364
  describe: "Pushes all composition patterns from files in a directory to Uniform Canvas",
3312
3365
  builder: (yargs35) => withConfiguration(
3313
3366
  withApiOptions(
@@ -3331,6 +3384,7 @@ var CompositionPatternPushModule = {
3331
3384
  type: "boolean",
3332
3385
  hidden: true
3333
3386
  }).option("patternType", {
3387
+ // This default differentiate this list command from composition list command
3334
3388
  default: "composition",
3335
3389
  choices: ["all", "component", "composition"],
3336
3390
  hidden: true
@@ -4142,6 +4196,11 @@ var EntryGetModule = {
4142
4196
  type: "number",
4143
4197
  default: 1,
4144
4198
  describe: "Controls how many levels deep content references should be resolved"
4199
+ },
4200
+ withComponentIDs: {
4201
+ type: "boolean",
4202
+ default: false,
4203
+ describe: "Include IDs of blocks in block fields"
4145
4204
  }
4146
4205
  }),
4147
4206
  // for backwards compatibility, we default to the "published" state, unlike compositions
@@ -4165,6 +4224,7 @@ var EntryGetModule = {
4165
4224
  resolveData,
4166
4225
  diagnostics,
4167
4226
  resolutionDepth,
4227
+ withComponentIDs,
4168
4228
  verbose
4169
4229
  }) => {
4170
4230
  const fetch2 = nodeFetchProxy(proxy, verbose);
@@ -4178,7 +4238,8 @@ var EntryGetModule = {
4178
4238
  skipPatternResolution: true,
4179
4239
  skipDataResolution: !resolveData,
4180
4240
  diagnostics: resolveData ? diagnostics : void 0,
4181
- resolutionDepth: resolveData ? resolutionDepth : void 0
4241
+ resolutionDepth: resolveData ? resolutionDepth : void 0,
4242
+ withComponentIDs
4182
4243
  });
4183
4244
  if (res.entries.length !== 1) {
4184
4245
  throw new Error(`Entry with ID ${id} not found`);
@@ -4205,7 +4266,12 @@ var EntryListModule = {
4205
4266
  type: "number",
4206
4267
  default: LEGACY_DEFAULT_LIMIT
4207
4268
  },
4208
- search: { describe: "Search query", type: "string", default: "" }
4269
+ search: { describe: "Search query", type: "string", default: "" },
4270
+ withComponentIDs: {
4271
+ type: "boolean",
4272
+ default: false,
4273
+ describe: "Include IDs of blocks in block fields"
4274
+ }
4209
4275
  }),
4210
4276
  // for backwards compatibility, we default to the "published" state, unlike compositions
4211
4277
  "published"
@@ -4227,6 +4293,7 @@ var EntryListModule = {
4227
4293
  limit: limit2,
4228
4294
  offset,
4229
4295
  search,
4296
+ withComponentIDs,
4230
4297
  verbose
4231
4298
  }) => {
4232
4299
  const fetch2 = nodeFetchProxy(proxy, verbose);
@@ -4239,7 +4306,8 @@ var EntryListModule = {
4239
4306
  state: convertStateOption(state),
4240
4307
  skipOverridesResolution: true,
4241
4308
  skipPatternResolution: true,
4242
- skipDataResolution: true
4309
+ skipDataResolution: true,
4310
+ withComponentIDs
4243
4311
  });
4244
4312
  emitWithFormat(res.entries, format, filename);
4245
4313
  }
@@ -4574,6 +4642,13 @@ var EntryPushModule = {
4574
4642
  }
4575
4643
  const target = createEntryEngineDataSource({ client, state, onlyEntries: true });
4576
4644
  const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
4645
+ const uniformLocales = await fetchUniformLocales({
4646
+ apiKey,
4647
+ apiHost,
4648
+ fetch: fetch2,
4649
+ projectId
4650
+ });
4651
+ const localeValidationHook = createLocaleValidationHook(uniformLocales);
4577
4652
  await syncEngine({
4578
4653
  source,
4579
4654
  target,
@@ -4581,6 +4656,12 @@ var EntryPushModule = {
4581
4656
  whatIf,
4582
4657
  allowEmptySource,
4583
4658
  log: createSyncEngineConsoleLogger({ diffMode }),
4659
+ onBeforeProcessObject: async (sourceObject) => {
4660
+ await localeValidationHook({
4661
+ _locales: sourceObject.object.entry._locales,
4662
+ displayName: sourceObject.displayName ?? sourceObject.providerId
4663
+ });
4664
+ },
4584
4665
  onBeforeCompareObjects: async (sourceObject) => {
4585
4666
  return replaceLocalUrlsWithRemoteReferences({
4586
4667
  entity: sourceObject,
@@ -4763,6 +4844,12 @@ var EntryPatternGetModule = {
4763
4844
  yargs35.positional("id", {
4764
4845
  demandOption: true,
4765
4846
  describe: "Entry pattern public ID to fetch"
4847
+ }).option({
4848
+ withComponentIDs: {
4849
+ type: "boolean",
4850
+ default: false,
4851
+ describe: "Include IDs of blocks in block fields"
4852
+ }
4766
4853
  }),
4767
4854
  "published"
4768
4855
  )
@@ -4771,7 +4858,18 @@ var EntryPatternGetModule = {
4771
4858
  )
4772
4859
  )
4773
4860
  ),
4774
- handler: async ({ apiHost, apiKey, proxy, id, format, filename, project: projectId, state, verbose }) => {
4861
+ handler: async ({
4862
+ apiHost,
4863
+ apiKey,
4864
+ proxy,
4865
+ id,
4866
+ format,
4867
+ filename,
4868
+ project: projectId,
4869
+ state,
4870
+ withComponentIDs,
4871
+ verbose
4872
+ }) => {
4775
4873
  const fetch2 = nodeFetchProxy(proxy, verbose);
4776
4874
  const client = getContentClient({ apiKey, apiHost, fetch: fetch2, projectId });
4777
4875
  const res = await client.getEntries({
@@ -4782,7 +4880,8 @@ var EntryPatternGetModule = {
4782
4880
  skipOverridesResolution: true,
4783
4881
  skipPatternResolution: true,
4784
4882
  skipDataResolution: true,
4785
- pattern: true
4883
+ pattern: true,
4884
+ withComponentIDs
4786
4885
  });
4787
4886
  if (res.entries.length !== 1) {
4788
4887
  throw new Error(`Entry pattern with ID ${id} not found`);
@@ -4797,7 +4896,22 @@ var EntryPatternListModule = {
4797
4896
  describe: "List entry patterns",
4798
4897
  builder: (yargs35) => withConfiguration(
4799
4898
  withDebugOptions(
4800
- withFormatOptions(withApiOptions(withProjectOptions(withStateOptions(yargs35, "published"))))
4899
+ withFormatOptions(
4900
+ withApiOptions(
4901
+ withProjectOptions(
4902
+ withStateOptions(
4903
+ yargs35.option({
4904
+ withComponentIDs: {
4905
+ type: "boolean",
4906
+ default: false,
4907
+ describe: "Include IDs of blocks in block fields"
4908
+ }
4909
+ }),
4910
+ "published"
4911
+ )
4912
+ )
4913
+ )
4914
+ )
4801
4915
  )
4802
4916
  ),
4803
4917
  handler: async ({
@@ -4809,6 +4923,7 @@ var EntryPatternListModule = {
4809
4923
  filename,
4810
4924
  project: projectId,
4811
4925
  state,
4926
+ withComponentIDs,
4812
4927
  verbose
4813
4928
  }) => {
4814
4929
  const fetch2 = nodeFetchProxy(proxy, verbose);
@@ -4820,7 +4935,8 @@ var EntryPatternListModule = {
4820
4935
  skipOverridesResolution: true,
4821
4936
  skipPatternResolution: true,
4822
4937
  skipDataResolution: true,
4823
- pattern: true
4938
+ pattern: true,
4939
+ withComponentIDs
4824
4940
  });
4825
4941
  emitWithFormat(res.entries, format, filename);
4826
4942
  }
@@ -4967,11 +5083,11 @@ var EntryPatternPullModule = {
4967
5083
  const packageContents = readCanvasPackage(directory, false, verbose);
4968
5084
  target = await createArraySyncEngineDataSource({
4969
5085
  name: `Package file ${directory}`,
4970
- objects: packageContents.entries ?? [],
5086
+ objects: packageContents.entryPatterns ?? [],
4971
5087
  selectIdentifier: selectEntryIdentifier,
4972
5088
  selectDisplayName: selectEntryDisplayName,
4973
5089
  onSyncComplete: async (_, synced) => {
4974
- packageContents.entries = synced;
5090
+ packageContents.entryPatterns = synced;
4975
5091
  writeCanvasPackage(directory, packageContents);
4976
5092
  }
4977
5093
  });
@@ -5069,7 +5185,7 @@ var EntryPatternPushModule = {
5069
5185
  const packageContents = readCanvasPackage(directory, true, verbose);
5070
5186
  source = await createArraySyncEngineDataSource({
5071
5187
  name: `Package file ${directory}`,
5072
- objects: packageContents.entries ?? [],
5188
+ objects: packageContents.entryPatterns ?? [],
5073
5189
  selectIdentifier: selectEntryIdentifier,
5074
5190
  selectDisplayName: selectEntryDisplayName
5075
5191
  });
@@ -5083,6 +5199,13 @@ var EntryPatternPushModule = {
5083
5199
  }
5084
5200
  const target = createEntryEngineDataSource({ client, state, onlyPatterns: true });
5085
5201
  const fileClient = getFileClient({ apiKey, apiHost, fetch: fetch2, projectId });
5202
+ const uniformLocales = await fetchUniformLocales({
5203
+ apiKey,
5204
+ apiHost,
5205
+ fetch: fetch2,
5206
+ projectId
5207
+ });
5208
+ const localeValidationHook = createLocaleValidationHook(uniformLocales);
5086
5209
  await syncEngine({
5087
5210
  source,
5088
5211
  target,
@@ -5090,6 +5213,12 @@ var EntryPatternPushModule = {
5090
5213
  whatIf,
5091
5214
  allowEmptySource,
5092
5215
  log: createSyncEngineConsoleLogger({ diffMode }),
5216
+ onBeforeProcessObject: async (sourceObject) => {
5217
+ await localeValidationHook({
5218
+ _locales: sourceObject.object.entry._locales,
5219
+ displayName: sourceObject.displayName ?? sourceObject.providerId
5220
+ });
5221
+ },
5093
5222
  onBeforeCompareObjects: async (sourceObject) => {
5094
5223
  return replaceLocalUrlsWithRemoteReferences({
5095
5224
  entity: sourceObject,
@@ -5294,9 +5423,9 @@ function createLocaleEngineDataSource({
5294
5423
  }
5295
5424
 
5296
5425
  // src/commands/canvas/commands/locale/_util.ts
5297
- import { LocaleClient } from "@uniformdev/canvas";
5426
+ import { LocaleClient as LocaleClient2 } from "@uniformdev/canvas";
5298
5427
  function getLocaleClient(options) {
5299
- return new LocaleClient({ ...options, bypassCache: true, limitPolicy: cliLimitPolicy });
5428
+ return new LocaleClient2({ ...options, bypassCache: true, limitPolicy: cliLimitPolicy });
5300
5429
  }
5301
5430
 
5302
5431
  // src/commands/canvas/commands/locale/pull.ts
@@ -8223,16 +8352,29 @@ var IntegrationEdgehancerDeployModule = {
8223
8352
  yargs35.positional("filename", {
8224
8353
  demandOption: true,
8225
8354
  describe: "ESM code file to run for the target edgehancer hook. Refer to the documentation for expected types."
8355
+ }).option("compatibilityDate", {
8356
+ type: "string",
8357
+ describe: "Date indicating targeted support in the custom edgehancer runtime. Backwards incompatible fixes to the runtime following this date will not affect this custom edgehancer. Format: YYYY-MM-DD. You can check here for more information: https://developers.cloudflare.com/workers/configuration/compatibility-dates/#setting-compatibility-date"
8226
8358
  })
8227
8359
  )
8228
8360
  )
8229
8361
  )
8230
8362
  ),
8231
- handler: async ({ apiHost, apiKey, proxy, filename, team: teamId, archetype, connectorType, hook }) => {
8363
+ handler: async ({
8364
+ apiHost,
8365
+ apiKey,
8366
+ proxy,
8367
+ filename,
8368
+ team: teamId,
8369
+ archetype,
8370
+ connectorType,
8371
+ hook,
8372
+ compatibilityDate
8373
+ }) => {
8232
8374
  const fetch2 = nodeFetchProxy(proxy);
8233
8375
  const client = new EdgehancerClient({ apiKey, apiHost, fetch: fetch2, teamId });
8234
8376
  const code = readFileSync(filename, "utf8");
8235
- await client.deploy({ archetype, code, connectorType, hook });
8377
+ await client.deploy({ archetype, code, connectorType, hook, compatibilityDate });
8236
8378
  }
8237
8379
  };
8238
8380
 
@@ -8455,7 +8597,7 @@ import { PostHog } from "posthog-node";
8455
8597
  // package.json
8456
8598
  var package_default = {
8457
8599
  name: "@uniformdev/cli",
8458
- version: "20.18.0",
8600
+ version: "20.26.2",
8459
8601
  description: "Uniform command line interface tool",
8460
8602
  license: "SEE LICENSE IN LICENSE.txt",
8461
8603
  main: "./cli.js",
@@ -9198,8 +9340,9 @@ async function newHandler({
9198
9340
  }
9199
9341
  }
9200
9342
  };
9343
+ let githubBranch = void 0;
9201
9344
  const {
9202
- starter: { githubUri, serverUrl, previewPath, installEnv, githubBranch }
9345
+ starter: { githubUri, serverUrl, previewPath, installEnv }
9203
9346
  } = await inquirer4.prompt([
9204
9347
  {
9205
9348
  type: "list",
@@ -9208,7 +9351,13 @@ async function newHandler({
9208
9351
  choices: Object.values(starters[frontendFramework])
9209
9352
  }
9210
9353
  ]);
9211
- telemetry.send("starter picked", { githubUri });
9354
+ if (process.env.UNIFORM_ALTERNATIVE_STARTER_BRANCH) {
9355
+ console.log(
9356
+ `Using alternative starter branch for repo ${githubUri}: "${process.env.UNIFORM_ALTERNATIVE_STARTER_BRANCH}"`
9357
+ );
9358
+ githubBranch = process.env.UNIFORM_ALTERNATIVE_STARTER_BRANCH;
9359
+ }
9360
+ telemetry.send("starter picked", { githubUri, githubBranch });
9212
9361
  const { projectId, targetDir } = await getOrCreateProject({
9213
9362
  client: uniformClient,
9214
9363
  createNew: true,
@@ -9316,10 +9465,15 @@ async function newMeshIntegrationHandler({
9316
9465
  ]);
9317
9466
  const name = answer.name;
9318
9467
  const { targetDir, typeSlug } = validateIntegrationName(answer.name, outputPath);
9468
+ const githubBranch = process.env.UNIFORM_ALTERNATIVE_MESH_INTEGRATION_BRANCH;
9469
+ if (githubBranch) {
9470
+ console.log(`Using alternative mesh integration branch: "${githubBranch}"`);
9471
+ }
9319
9472
  const { runNpmInstall } = await cloneStarter({
9320
9473
  githubPath: `uniformdev/examples/mesh/mesh-integration`,
9321
9474
  spin,
9322
- targetDir
9475
+ targetDir,
9476
+ githubBranch
9323
9477
  });
9324
9478
  let done = await spin("Registering integration to team...");
9325
9479
  const pathToManifest = path3.resolve(targetDir, "mesh-manifest.json");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/cli",
3
- "version": "20.7.1-alpha.63+0444977bba",
3
+ "version": "20.7.1-alpha.67+918070a68e",
4
4
  "description": "Uniform command line interface tool",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "main": "./cli.js",
@@ -27,13 +27,13 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@thi.ng/mime": "^2.2.23",
30
- "@uniformdev/assets": "20.7.1-alpha.63+0444977bba",
31
- "@uniformdev/canvas": "20.7.1-alpha.63+0444977bba",
32
- "@uniformdev/context": "20.7.1-alpha.63+0444977bba",
33
- "@uniformdev/files": "20.7.1-alpha.63+0444977bba",
34
- "@uniformdev/project-map": "20.7.1-alpha.63+0444977bba",
35
- "@uniformdev/redirect": "20.7.1-alpha.63+0444977bba",
36
- "@uniformdev/richtext": "20.7.1-alpha.63+0444977bba",
30
+ "@uniformdev/assets": "20.7.1-alpha.67+918070a68e",
31
+ "@uniformdev/canvas": "20.7.1-alpha.67+918070a68e",
32
+ "@uniformdev/context": "20.7.1-alpha.67+918070a68e",
33
+ "@uniformdev/files": "20.7.1-alpha.67+918070a68e",
34
+ "@uniformdev/project-map": "20.7.1-alpha.67+918070a68e",
35
+ "@uniformdev/redirect": "20.7.1-alpha.67+918070a68e",
36
+ "@uniformdev/richtext": "20.7.1-alpha.67+918070a68e",
37
37
  "call-bind": "^1.0.2",
38
38
  "colorette": "2.0.20",
39
39
  "cosmiconfig": "9.0.0",
@@ -79,5 +79,5 @@
79
79
  "publishConfig": {
80
80
  "access": "public"
81
81
  },
82
- "gitHead": "0444977bba4c3d40fa8da46c46ce252af216df96"
82
+ "gitHead": "918070a68e7170a76f4f1ae4ac0c94cf87441bcf"
83
83
  }