fluentui-extended 2026.2.6 → 2026.2.8

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/README.md CHANGED
@@ -349,7 +349,7 @@ The Validate button checks query structure and optionally tests against the Dyna
349
349
  ```
350
350
 
351
351
  When running inside Dynamics 365:
352
- - Detects `Xrm.WebApi` availability
352
+ - Uses native fetch to `/api/data/v9.2/` endpoints
353
353
  - Executes a test query with `$top=1&$count=true`
354
354
  - Shows record count or API error message
355
355
 
@@ -405,7 +405,7 @@ const fields: QueryBuilderField[] = [
405
405
  |------|------|---------|-------------|
406
406
  | `entityName` | `string` | - | Logical name of the entity (required) |
407
407
  | `entityDisplayName` | `string` | - | Display name shown in header |
408
- | `fields` | `QueryBuilderField[]` | - | Fields for filtering (auto-loaded from Xrm if omitted) |
408
+ | `fields` | `QueryBuilderField[]` | - | Fields for filtering (auto-loaded via Web API if omitted) |
409
409
  | `initialFetchXml` | `string` | - | FetchXML to pre-populate the query builder |
410
410
  | `initialState` | `QueryBuilderState` | - | Initial query state object |
411
411
  | `onSerializedChange` | `(result: QueryBuilderApplyResult) => void` | - | Called when query changes |
package/dist/index.d.mts CHANGED
@@ -156,7 +156,7 @@ interface QueryBuilderLookupOption {
156
156
  }
157
157
  interface QueryBuilderProps {
158
158
  entityName: string;
159
- /** Entity set name for OData queries (e.g., "accounts"). If not provided, will be fetched from Xrm metadata. */
159
+ /** Entity set name for OData queries (e.g., "accounts"). If not provided, will be fetched from the Web API. */
160
160
  entitySetName?: string;
161
161
  entityDisplayName?: string;
162
162
  fields?: QueryBuilderField[];
@@ -189,6 +189,8 @@ interface QueryBuilderProps {
189
189
  onSerializedChange?: (result: QueryBuilderApplyResult) => void;
190
190
  /** Callback for lookup field search - returns options for the lookup dropdown */
191
191
  onLookupSearch?: (fieldId: string, searchText: string) => Promise<QueryBuilderLookupOption[]> | QueryBuilderLookupOption[];
192
+ /** Callback to fetch fields for a related entity. If provided, this is used instead of the native Web API. */
193
+ onFetchEntityFields?: (entityLogicalName: string) => Promise<QueryBuilderField[]>;
192
194
  }
193
195
 
194
196
  /**
package/dist/index.d.ts CHANGED
@@ -156,7 +156,7 @@ interface QueryBuilderLookupOption {
156
156
  }
157
157
  interface QueryBuilderProps {
158
158
  entityName: string;
159
- /** Entity set name for OData queries (e.g., "accounts"). If not provided, will be fetched from Xrm metadata. */
159
+ /** Entity set name for OData queries (e.g., "accounts"). If not provided, will be fetched from the Web API. */
160
160
  entitySetName?: string;
161
161
  entityDisplayName?: string;
162
162
  fields?: QueryBuilderField[];
@@ -189,6 +189,8 @@ interface QueryBuilderProps {
189
189
  onSerializedChange?: (result: QueryBuilderApplyResult) => void;
190
190
  /** Callback for lookup field search - returns options for the lookup dropdown */
191
191
  onLookupSearch?: (fieldId: string, searchText: string) => Promise<QueryBuilderLookupOption[]> | QueryBuilderLookupOption[];
192
+ /** Callback to fetch fields for a related entity. If provided, this is used instead of the native Web API. */
193
+ onFetchEntityFields?: (entityLogicalName: string) => Promise<QueryBuilderField[]>;
192
194
  }
193
195
 
194
196
  /**
package/dist/index.js CHANGED
@@ -2452,9 +2452,13 @@ var isValueEmpty = (value) => {
2452
2452
  return String(value).trim() === "";
2453
2453
  };
2454
2454
  var dataTypeFromAttribute = (attribute) => {
2455
- const type = String(attribute?.AttributeType || attribute?.Type || "").toLowerCase();
2455
+ const typeValue = attribute?.AttributeTypeName?.Value || attribute?.AttributeType || attribute?.Type || "";
2456
+ const type = String(typeValue).toLowerCase();
2457
+ if (attribute?.Targets && Array.isArray(attribute.Targets) && attribute.Targets.length > 0) {
2458
+ return "lookup";
2459
+ }
2456
2460
  if (["picklist", "state", "status"].includes(type)) return "optionset";
2457
- if (["lookup", "customer", "owner", "partylist", "uniqueidentifier"].includes(type)) return "lookup";
2461
+ if (["lookup", "customer", "owner", "partylist", "uniqueidentifier", "lookuptype"].includes(type)) return "lookup";
2458
2462
  if (["datetime"].includes(type)) return "datetime";
2459
2463
  if (["boolean"].includes(type)) return "boolean";
2460
2464
  if (["integer", "decimal", "double", "money", "bigint", "int"].includes(type)) return "number";
@@ -2532,9 +2536,8 @@ var LookupValueInput = ({
2532
2536
  const [lookupLoading, setLookupLoading] = React3__namespace.useState(false);
2533
2537
  const [resultCount, setResultCount] = React3__namespace.useState(0);
2534
2538
  const [headerText, setHeaderText] = React3__namespace.useState("");
2535
- const searchUsingXrm = React3__namespace.useCallback(async (searchText, limit = 15) => {
2536
- const xrm = window.Xrm;
2537
- if (!xrm?.WebApi?.retrieveMultipleRecords || !targets || targets.length === 0) {
2539
+ const searchUsingWebApi = React3__namespace.useCallback(async (searchText, limit = 15) => {
2540
+ if (!targets || targets.length === 0) {
2538
2541
  return { results: [], entityDisplayName: "" };
2539
2542
  }
2540
2543
  const results = [];
@@ -2546,12 +2549,20 @@ var LookupValueInput = ({
2546
2549
  }
2547
2550
  try {
2548
2551
  const nameAttr = target.primaryNameAttribute;
2549
- let options = `?$select=${nameAttr}&$top=${limit}`;
2552
+ let queryOptions = `$select=${nameAttr}&$top=${limit}`;
2550
2553
  if (searchText) {
2551
- options += `&$filter=contains(${nameAttr},'${searchText.replace(/'/g, "''")}')`;
2554
+ queryOptions += `&$filter=contains(${nameAttr},'${searchText.replace(/'/g, "''")}')`;
2552
2555
  }
2553
- const response = await xrm.WebApi.retrieveMultipleRecords(target.entitySetName, options);
2554
- const records = response.value || response.entities || [];
2556
+ const response = await fetch(`/api/data/v9.2/${target.entitySetName}?${queryOptions}`, {
2557
+ headers: {
2558
+ "OData-MaxVersion": "4.0",
2559
+ "OData-Version": "4.0",
2560
+ "Accept": "application/json"
2561
+ }
2562
+ });
2563
+ if (!response.ok) continue;
2564
+ const data = await response.json();
2565
+ const records = data.value || [];
2555
2566
  for (const record of records) {
2556
2567
  const idField = `${target.entityLogicalName}id`;
2557
2568
  const id = record[idField] || record.id || "";
@@ -2570,12 +2581,11 @@ var LookupValueInput = ({
2570
2581
  }, [targets]);
2571
2582
  React3__namespace.useEffect(() => {
2572
2583
  const loadInitialRecords = async () => {
2573
- const xrm = window.Xrm;
2574
2584
  const hasValidTargets2 = targets && targets.length > 0 && targets.some((t) => t.entitySetName && t.primaryNameAttribute);
2575
- if (!disabled && hasValidTargets2 && xrm?.WebApi?.retrieveMultipleRecords && !onLookupSearch) {
2585
+ if (!disabled && hasValidTargets2 && !onLookupSearch) {
2576
2586
  setLookupLoading(true);
2577
2587
  try {
2578
- const searchResult = await searchUsingXrm("", 5);
2588
+ const searchResult = await searchUsingWebApi("", 5);
2579
2589
  setLookupOptions(searchResult.results);
2580
2590
  setResultCount(searchResult.results.length);
2581
2591
  setHeaderText(searchResult.entityDisplayName);
@@ -2585,7 +2595,7 @@ var LookupValueInput = ({
2585
2595
  }
2586
2596
  };
2587
2597
  loadInitialRecords();
2588
- }, [targets, disabled, onLookupSearch, searchUsingXrm]);
2598
+ }, [targets, disabled, onLookupSearch, searchUsingWebApi]);
2589
2599
  const handleSearchChange = React3__namespace.useCallback(
2590
2600
  async (searchText) => {
2591
2601
  setLookupLoading(true);
@@ -2601,7 +2611,7 @@ var LookupValueInput = ({
2601
2611
  }));
2602
2612
  entityName = targets?.[0]?.displayName || "";
2603
2613
  } else {
2604
- const searchResult = await searchUsingXrm(searchText);
2614
+ const searchResult = await searchUsingWebApi(searchText);
2605
2615
  results = searchResult.results;
2606
2616
  entityName = searchResult.entityDisplayName;
2607
2617
  }
@@ -2612,7 +2622,7 @@ var LookupValueInput = ({
2612
2622
  setLookupLoading(false);
2613
2623
  }
2614
2624
  },
2615
- [fieldId, onLookupSearch, searchUsingXrm, targets]
2625
+ [fieldId, onLookupSearch, searchUsingWebApi, targets]
2616
2626
  );
2617
2627
  const handleOptionSelect = React3__namespace.useCallback(
2618
2628
  (option) => {
@@ -2727,67 +2737,118 @@ var QueryBuilder = (props) => {
2727
2737
  }
2728
2738
  setLoading(true);
2729
2739
  try {
2730
- const xrm = window.Xrm;
2731
- if (xrm?.Utility?.getEntityMetadata) {
2732
- const metadata = await xrm.Utility.getEntityMetadata(props.entityName);
2733
- if (metadata?.EntitySetName && !disposed) {
2734
- setEntitySetName(metadata.EntitySetName);
2740
+ const entityResponse = await fetch(
2741
+ `/api/data/v9.2/EntityDefinitions(LogicalName='${props.entityName}')?$select=EntitySetName,DisplayName,PrimaryNameAttribute`,
2742
+ {
2743
+ headers: {
2744
+ "OData-MaxVersion": "4.0",
2745
+ "OData-Version": "4.0",
2746
+ "Accept": "application/json"
2747
+ }
2735
2748
  }
2736
- const attributesCollection = metadata?.Attributes?._collection || metadata?.Attributes || {};
2737
- const attributesArray = Array.isArray(attributesCollection) ? attributesCollection : Object.keys(attributesCollection).map((key) => attributesCollection[key]);
2738
- const targetEntityNames = /* @__PURE__ */ new Set();
2739
- for (const attribute of attributesArray) {
2740
- if (Array.isArray(attribute?.Targets)) {
2741
- for (const target of attribute.Targets) {
2742
- const entityName = typeof target === "string" ? target : target?.entityLogicalName;
2743
- if (entityName) targetEntityNames.add(entityName);
2744
- }
2749
+ );
2750
+ if (!entityResponse.ok) {
2751
+ console.warn("[QueryBuilder] Failed to fetch entity metadata");
2752
+ return;
2753
+ }
2754
+ const entityMetadata = await entityResponse.json();
2755
+ if (entityMetadata?.EntitySetName && !disposed) {
2756
+ setEntitySetName(entityMetadata.EntitySetName);
2757
+ }
2758
+ const attributesResponse = await fetch(
2759
+ `/api/data/v9.2/EntityDefinitions(LogicalName='${props.entityName}')/Attributes?$select=LogicalName,SchemaName,DisplayName,AttributeType,AttributeTypeName`,
2760
+ {
2761
+ headers: {
2762
+ "OData-MaxVersion": "4.0",
2763
+ "OData-Version": "4.0",
2764
+ "Accept": "application/json"
2765
+ }
2766
+ }
2767
+ );
2768
+ if (!attributesResponse.ok) {
2769
+ console.warn("[QueryBuilder] Failed to fetch entity attributes");
2770
+ return;
2771
+ }
2772
+ const attributesData = await attributesResponse.json();
2773
+ const attributesArray = attributesData.value || [];
2774
+ const lookupResponse = await fetch(
2775
+ `/api/data/v9.2/EntityDefinitions(LogicalName='${props.entityName}')/Attributes/Microsoft.Dynamics.CRM.LookupAttributeMetadata?$select=LogicalName,SchemaName,DisplayName,AttributeType,AttributeTypeName,Targets`,
2776
+ {
2777
+ headers: {
2778
+ "OData-MaxVersion": "4.0",
2779
+ "OData-Version": "4.0",
2780
+ "Accept": "application/json"
2745
2781
  }
2746
2782
  }
2747
- const targetMetadataCache = {};
2748
- for (const targetEntityName of targetEntityNames) {
2749
- try {
2750
- const targetMeta = await xrm.Utility.getEntityMetadata(targetEntityName);
2783
+ );
2784
+ const lookupData = lookupResponse.ok ? await lookupResponse.json() : { value: [] };
2785
+ const lookupAttributes = lookupData.value || [];
2786
+ const lookupMap = new Map(lookupAttributes.map((attr) => [attr.LogicalName, attr]));
2787
+ const mergedAttributes = attributesArray.map((attr) => {
2788
+ const lookupAttr = lookupMap.get(attr.LogicalName);
2789
+ if (lookupAttr?.Targets) {
2790
+ return { ...attr, Targets: lookupAttr.Targets };
2791
+ }
2792
+ return attr;
2793
+ });
2794
+ const targetEntityNames = /* @__PURE__ */ new Set();
2795
+ for (const attribute of mergedAttributes) {
2796
+ if (Array.isArray(attribute?.Targets)) {
2797
+ for (const target of attribute.Targets) {
2798
+ const entityName = typeof target === "string" ? target : target?.entityLogicalName;
2799
+ if (entityName) targetEntityNames.add(entityName);
2800
+ }
2801
+ }
2802
+ }
2803
+ const targetMetadataCache = {};
2804
+ for (const targetEntityName of targetEntityNames) {
2805
+ try {
2806
+ const targetResponse = await fetch(
2807
+ `/api/data/v9.2/EntityDefinitions(LogicalName='${targetEntityName}')?$select=EntitySetName,DisplayName,PrimaryNameAttribute`,
2808
+ {
2809
+ headers: {
2810
+ "OData-MaxVersion": "4.0",
2811
+ "OData-Version": "4.0",
2812
+ "Accept": "application/json"
2813
+ }
2814
+ }
2815
+ );
2816
+ if (targetResponse.ok) {
2817
+ const targetMeta = await targetResponse.json();
2751
2818
  targetMetadataCache[targetEntityName] = {
2752
2819
  entitySetName: targetMeta?.EntitySetName,
2753
2820
  displayName: targetMeta?.DisplayName?.UserLocalizedLabel?.Label || targetMeta?.LogicalName,
2754
2821
  primaryNameAttribute: targetMeta?.PrimaryNameAttribute
2755
2822
  };
2756
- } catch (targetErr) {
2757
- console.warn(`[QueryBuilder] Could not fetch metadata for target entity "${targetEntityName}":`, targetErr);
2758
2823
  }
2824
+ } catch (targetErr) {
2825
+ console.warn(`[QueryBuilder] Could not fetch metadata for target entity "${targetEntityName}":`, targetErr);
2759
2826
  }
2760
- const resolvedFields = attributesArray.filter((attribute) => attribute?.LogicalName && attribute?.IsValidForAdvancedFind !== false).map((attribute) => {
2761
- const dataType = dataTypeFromAttribute(attribute);
2762
- const optionSet = attribute?.OptionSet?.Options;
2763
- const options = dataType === "optionset" && Array.isArray(optionSet) ? optionSet.map((option) => ({
2764
- label: option?.Label?.UserLocalizedLabel?.Label || option?.Label || String(option?.Value),
2765
- value: option?.Value
2766
- })).filter((option) => option.value !== void 0 && option.value !== null) : void 0;
2767
- const targets = dataType === "lookup" && Array.isArray(attribute.Targets) ? attribute.Targets.map((target) => {
2768
- const entityLogicalName = typeof target === "string" ? target : target?.entityLogicalName || target;
2769
- const cached = targetMetadataCache[entityLogicalName] || {};
2770
- return {
2771
- entityLogicalName,
2772
- entitySetName: target?.entitySetName || cached.entitySetName,
2773
- displayName: target?.displayName || cached.displayName,
2774
- primaryNameAttribute: target?.primaryNameAttribute || cached.primaryNameAttribute
2775
- };
2776
- }) : void 0;
2777
- const displayName = attribute.DisplayName;
2778
- const label = typeof displayName === "string" ? displayName : displayName?.UserLocalizedLabel?.Label || attribute.SchemaName || attribute.LogicalName;
2827
+ }
2828
+ const resolvedFields = mergedAttributes.filter((attribute) => attribute?.LogicalName && attribute?.IsValidForAdvancedFind !== false).map((attribute) => {
2829
+ const dataType = dataTypeFromAttribute(attribute);
2830
+ const targets = dataType === "lookup" && Array.isArray(attribute.Targets) ? attribute.Targets.map((target) => {
2831
+ const entityLogicalName = typeof target === "string" ? target : target?.entityLogicalName || target;
2832
+ const cached = targetMetadataCache[entityLogicalName] || {};
2779
2833
  return {
2780
- id: attribute.LogicalName,
2781
- label,
2782
- schemaName: attribute.SchemaName,
2783
- dataType,
2784
- options,
2785
- targets
2834
+ entityLogicalName,
2835
+ entitySetName: target?.entitySetName || cached.entitySetName,
2836
+ displayName: target?.displayName || cached.displayName,
2837
+ primaryNameAttribute: target?.primaryNameAttribute || cached.primaryNameAttribute
2786
2838
  };
2787
- }).sort((left, right) => String(left.label).localeCompare(String(right.label), void 0, { sensitivity: "base" }));
2788
- if (!disposed && resolvedFields.length > 0) {
2789
- setAvailableFields(resolvedFields);
2790
- }
2839
+ }) : void 0;
2840
+ const displayName = attribute.DisplayName;
2841
+ const label = typeof displayName === "string" ? displayName : displayName?.UserLocalizedLabel?.Label || attribute.SchemaName || attribute.LogicalName;
2842
+ return {
2843
+ id: attribute.LogicalName,
2844
+ label,
2845
+ schemaName: attribute.SchemaName,
2846
+ dataType,
2847
+ targets
2848
+ };
2849
+ }).sort((left, right) => String(left.label).localeCompare(String(right.label), void 0, { sensitivity: "base" }));
2850
+ if (!disposed && resolvedFields.length > 0) {
2851
+ setAvailableFields(resolvedFields);
2791
2852
  }
2792
2853
  } catch (error) {
2793
2854
  console.error("[QueryBuilder] Error loading fields:", error);
@@ -2873,45 +2934,48 @@ var QueryBuilder = (props) => {
2873
2934
  const loadRelatedEntityFields = React3__namespace.useCallback(
2874
2935
  async (groupId, conditionId, targetEntity) => {
2875
2936
  try {
2876
- const xrm = window.Xrm;
2877
- if (!xrm?.Utility?.getEntityMetadata) {
2878
- console.warn("[QueryBuilder] Xrm.Utility.getEntityMetadata not available, cannot load related entity fields");
2879
- return;
2880
- }
2881
- const metadata = await xrm.Utility.getEntityMetadata(targetEntity);
2882
- if (!metadata) {
2883
- console.warn("[QueryBuilder] No metadata returned for entity:", targetEntity);
2884
- return;
2885
- }
2886
- const attributesCollection = metadata?.Attributes?._collection || metadata?.Attributes || {};
2887
- const attributesArray = Array.isArray(attributesCollection) ? attributesCollection : Object.keys(attributesCollection).map((key) => attributesCollection[key]);
2888
- if (attributesArray.length === 0) {
2889
- console.warn("[QueryBuilder] No attributes found in metadata for entity:", targetEntity);
2890
- return;
2937
+ let resolvedFields = [];
2938
+ if (props.onFetchEntityFields) {
2939
+ resolvedFields = await props.onFetchEntityFields(targetEntity);
2940
+ } else {
2941
+ const response = await fetch(
2942
+ `/api/data/v9.2/EntityDefinitions(LogicalName='${targetEntity}')/Attributes?$select=LogicalName,SchemaName,DisplayName,AttributeType,AttributeTypeName`,
2943
+ {
2944
+ headers: {
2945
+ "OData-MaxVersion": "4.0",
2946
+ "OData-Version": "4.0",
2947
+ "Accept": "application/json"
2948
+ }
2949
+ }
2950
+ );
2951
+ if (!response.ok) {
2952
+ console.warn("[QueryBuilder] Failed to fetch entity metadata:", response.status, response.statusText);
2953
+ return;
2954
+ }
2955
+ const data = await response.json();
2956
+ const attributesArray = data.value || [];
2957
+ if (attributesArray.length === 0) {
2958
+ console.warn("[QueryBuilder] No attributes found for entity:", targetEntity);
2959
+ return;
2960
+ }
2961
+ resolvedFields = attributesArray.filter((attr) => {
2962
+ if (!attr?.LogicalName) return false;
2963
+ const attrType = attr.AttributeType || attr.AttributeTypeName?.Value;
2964
+ if (attrType === "Virtual" || attrType === "CalendarRules") return false;
2965
+ if (attrType === "Uniqueidentifier" && !attr.LogicalName.endsWith("id")) return false;
2966
+ return true;
2967
+ }).map((attr) => {
2968
+ const dataType = dataTypeFromAttribute(attr);
2969
+ const displayName = attr.DisplayName;
2970
+ const label = typeof displayName === "string" ? displayName : displayName?.UserLocalizedLabel?.Label || attr.SchemaName || attr.LogicalName;
2971
+ return {
2972
+ id: attr.LogicalName,
2973
+ label,
2974
+ schemaName: attr.SchemaName,
2975
+ dataType
2976
+ };
2977
+ }).sort((a, b) => String(a.label).localeCompare(String(b.label), void 0, { sensitivity: "base" }));
2891
2978
  }
2892
- const resolvedFields = attributesArray.filter((attr) => {
2893
- if (!attr?.LogicalName) return false;
2894
- const attrType = attr.AttributeType || attr.AttributeTypeName?.Value;
2895
- if (attrType === "Virtual" || attrType === "CalendarRules") return false;
2896
- if (attrType === "Uniqueidentifier" && !attr.LogicalName.endsWith("id")) return false;
2897
- return true;
2898
- }).map((attr) => {
2899
- const dataType = dataTypeFromAttribute(attr);
2900
- const optionSet = attr?.OptionSet?.Options;
2901
- const options = dataType === "optionset" && Array.isArray(optionSet) ? optionSet.map((opt) => ({
2902
- label: opt?.Label?.UserLocalizedLabel?.Label || opt?.Label || String(opt?.Value),
2903
- value: opt?.Value
2904
- })).filter((opt) => opt.value !== void 0 && opt.value !== null) : void 0;
2905
- const displayName = attr.DisplayName;
2906
- const label = typeof displayName === "string" ? displayName : displayName?.UserLocalizedLabel?.Label || attr.SchemaName || attr.LogicalName;
2907
- return {
2908
- id: attr.LogicalName,
2909
- label,
2910
- schemaName: attr.SchemaName,
2911
- dataType,
2912
- options
2913
- };
2914
- }).sort((a, b) => String(a.label).localeCompare(String(b.label), void 0, { sensitivity: "base" }));
2915
2979
  if (resolvedFields.length > 0) {
2916
2980
  const defaultCondition = createCondition(resolvedFields[0]);
2917
2981
  updateGroup(groupId, (group) => ({
@@ -2931,7 +2995,7 @@ var QueryBuilder = (props) => {
2931
2995
  console.error("[QueryBuilder] Error loading related entity fields:", error);
2932
2996
  }
2933
2997
  },
2934
- [updateGroup]
2998
+ [props.onFetchEntityFields, updateGroup]
2935
2999
  );
2936
3000
  const addNestedCondition = React3__namespace.useCallback(
2937
3001
  (groupId, conditionId, nestedFields) => {
@@ -3054,24 +3118,8 @@ var QueryBuilder = (props) => {
3054
3118
  if (!validationResult) return /* @__PURE__ */ new Set();
3055
3119
  return new Set(validationResult.errors.map((e) => e.conditionId).filter(Boolean));
3056
3120
  }, [validationResult]);
3057
- const isXrmAvailable = React3__namespace.useMemo(() => {
3058
- try {
3059
- return typeof window.Xrm?.WebApi?.retrieveMultipleRecords === "function";
3060
- } catch {
3061
- return false;
3062
- }
3063
- }, []);
3064
3121
  const onValidate = React3__namespace.useCallback(async () => {
3065
3122
  const result = validateQueryBuilderState(builderState, availableFields);
3066
- if (!isXrmAvailable) {
3067
- result.apiValidation = {
3068
- available: false,
3069
- tested: false
3070
- };
3071
- setValidationResult(result);
3072
- setValidationDialogOpen(true);
3073
- return;
3074
- }
3075
3123
  if (!result.isValid) {
3076
3124
  result.apiValidation = {
3077
3125
  available: true,
@@ -3085,18 +3133,29 @@ var QueryBuilder = (props) => {
3085
3133
  setValidationResult(result);
3086
3134
  setValidationDialogOpen(true);
3087
3135
  try {
3088
- const Xrm = window.Xrm;
3089
3136
  const { odataFilter } = serializeQueryBuilderState(builderState, availableFields, props.entityName, entitySetName);
3090
- const options = odataFilter ? `?$filter=${odataFilter}&$top=1&$count=true` : "?$top=1&$count=true";
3091
3137
  const entitySetForApi = entitySetName || props.entityName;
3092
- const response = await Xrm.WebApi.retrieveMultipleRecords(entitySetForApi, options);
3138
+ const queryOptions = odataFilter ? `$filter=${odataFilter}&$top=1&$count=true` : "$top=1&$count=true";
3139
+ const response = await fetch(`/api/data/v9.2/${entitySetForApi}?${queryOptions}`, {
3140
+ headers: {
3141
+ "OData-MaxVersion": "4.0",
3142
+ "OData-Version": "4.0",
3143
+ "Accept": "application/json",
3144
+ "Prefer": 'odata.include-annotations="*"'
3145
+ }
3146
+ });
3147
+ if (!response.ok) {
3148
+ const errorText = await response.text();
3149
+ throw new Error(errorText || `HTTP ${response.status}`);
3150
+ }
3151
+ const data = await response.json();
3093
3152
  setValidationResult({
3094
3153
  ...result,
3095
3154
  apiValidation: {
3096
3155
  available: true,
3097
3156
  tested: true,
3098
3157
  success: true,
3099
- recordCount: response["@odata.count"] ?? response.entities?.length ?? 0
3158
+ recordCount: data["@odata.count"] ?? data.value?.length ?? 0
3100
3159
  }
3101
3160
  });
3102
3161
  } catch (err) {
@@ -3112,7 +3171,7 @@ var QueryBuilder = (props) => {
3112
3171
  } finally {
3113
3172
  setApiValidating(false);
3114
3173
  }
3115
- }, [builderState, availableFields, entitySetName, isXrmAvailable, props.entityName]);
3174
+ }, [builderState, availableFields, entitySetName, props.entityName]);
3116
3175
  const onOpenUploadDialog = React3__namespace.useCallback(() => {
3117
3176
  setUploadXmlText("");
3118
3177
  setUploadError(null);