@salesforce/webapp-template-app-react-sample-b2x-experimental 1.68.1 → 1.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/CHANGELOG.md +8 -0
  2. package/dist/force-app/main/default/data/Lease__c.json +13 -0
  3. package/dist/force-app/main/default/webapplications/appreactsampleb2x/package.json +13 -8
  4. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/applicationApi.ts +78 -0
  5. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/graphqlClient.ts +17 -0
  6. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/index.ts +19 -0
  7. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/leadApi.ts +69 -0
  8. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/maintenanceRequestApi.ts +177 -0
  9. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/objectDetailService.ts +125 -0
  10. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/objectInfoGraphQLService.ts +194 -0
  11. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/objectInfoService.ts +199 -0
  12. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/propertyDetailGraphQL.ts +497 -0
  13. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/propertyListingGraphQL.ts +190 -0
  14. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/api/recordListGraphQLService.ts +365 -0
  15. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/appLayout.tsx +20 -30
  16. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/FiltersPanel.tsx +375 -0
  17. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/LoadingFallback.tsx +61 -0
  18. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/PropertyListingCard.tsx +164 -0
  19. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/PropertyMap.tsx +113 -0
  20. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/SearchResultCard.tsx +131 -0
  21. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/alerts/status-alert.tsx +45 -0
  22. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/DetailFields.tsx +55 -0
  23. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/DetailForm.tsx +146 -0
  24. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/DetailHeader.tsx +34 -0
  25. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/DetailLayoutSections.tsx +80 -0
  26. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/Section.tsx +108 -0
  27. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/SectionRow.tsx +20 -0
  28. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/UiApiDetailForm.tsx +140 -0
  29. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/FieldValueDisplay.tsx +73 -0
  30. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/FormattedAddress.tsx +29 -0
  31. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/FormattedEmail.tsx +17 -0
  32. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/FormattedPhone.tsx +24 -0
  33. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/FormattedText.tsx +11 -0
  34. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/FormattedUrl.tsx +29 -0
  35. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/detail/formatted/index.ts +6 -0
  36. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/filters/FilterField.tsx +54 -0
  37. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/filters/FilterInput.tsx +55 -0
  38. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/filters/FilterSelect.tsx +72 -0
  39. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/forms/filters-form.tsx +114 -0
  40. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/forms/submit-button.tsx +47 -0
  41. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/layout/card-layout.tsx +19 -0
  42. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/search/ResultCardFields.tsx +71 -0
  43. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/search/SearchHeader.tsx +31 -0
  44. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/search/SearchPagination.tsx +144 -0
  45. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/search/SearchResultsPanel.tsx +197 -0
  46. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/components/shared/GlobalSearchInput.tsx +114 -0
  47. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/constants.ts +39 -0
  48. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/features/global-search/index.ts +33 -0
  49. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/form.tsx +204 -0
  50. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/index.ts +22 -0
  51. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useGeocode.ts +35 -0
  52. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useMaintenanceRequests.ts +39 -0
  53. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useObjectInfoBatch.ts +65 -0
  54. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useObjectSearchData.ts +395 -0
  55. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyAddresses.ts +36 -0
  56. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyDetail.ts +99 -0
  57. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyListingSearch.ts +75 -0
  58. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyMapMarkers.ts +100 -0
  59. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/usePropertyPrimaryImages.ts +51 -0
  60. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useRecordDetailLayout.ts +156 -0
  61. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useRecordListGraphQL.ts +135 -0
  62. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/hooks/useWeather.ts +173 -0
  63. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Application.tsx +263 -76
  64. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Contact.tsx +158 -0
  65. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Dashboard.tsx +137 -65
  66. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/DetailPage.tsx +109 -0
  67. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/GlobalSearch.tsx +229 -0
  68. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Home.tsx +469 -21
  69. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/Maintenance.tsx +244 -95
  70. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertyDetails.tsx +211 -39
  71. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertyListings.tsx +26 -10
  72. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertySearch.tsx +165 -0
  73. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/pages/PropertySearchPlaceholder.tsx +49 -0
  74. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-01.jpg +0 -0
  75. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-02.jpg +0 -0
  76. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-03.jpg +0 -0
  77. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-04.jpg +0 -0
  78. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-05.jpg +0 -0
  79. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-06.jpg +0 -0
  80. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-07.jpg +0 -0
  81. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-08.jpg +0 -0
  82. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-09.jpg +0 -0
  83. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-10.jpg +0 -0
  84. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-11.jpg +0 -0
  85. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-12.jpg +0 -0
  86. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-13.jpg +0 -0
  87. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-14.jpg +0 -0
  88. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-15.jpg +0 -0
  89. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-16.jpg +0 -0
  90. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-17.jpg +0 -0
  91. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-18.jpg +0 -0
  92. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-19.jpg +0 -0
  93. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-20.jpg +0 -0
  94. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-21.jpg +0 -0
  95. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-22.jpg +0 -0
  96. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-23.jpg +0 -0
  97. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-24.jpg +0 -0
  98. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/public/property-25.jpg +0 -0
  99. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/routes.tsx +32 -6
  100. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/styles/global.css +23 -63
  101. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/filters/filters.ts +120 -0
  102. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/filters/picklist.ts +32 -0
  103. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/index.ts +4 -0
  104. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/leaflet.d.ts +17 -0
  105. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/objectInfo/objectInfo.ts +166 -0
  106. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/recordDetail/recordDetail.ts +61 -0
  107. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/types/search/searchResults.ts +229 -0
  108. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/apiUtils.ts +125 -0
  109. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/cacheUtils.ts +76 -0
  110. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/debounce.ts +89 -0
  111. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/fieldUtils.ts +354 -0
  112. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/fieldValueExtractor.ts +67 -0
  113. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/filterUtils.ts +32 -0
  114. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/formDataTransformUtils.ts +260 -0
  115. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/formUtils.ts +142 -0
  116. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/geocode.ts +65 -0
  117. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/graphQLNodeFieldUtils.ts +186 -0
  118. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/graphQLObjectInfoAdapter.ts +319 -0
  119. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/graphQLRecordAdapter.ts +90 -0
  120. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/index.ts +59 -0
  121. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/layoutTransformUtils.ts +236 -0
  122. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/linkUtils.ts +14 -0
  123. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/paginationUtils.ts +49 -0
  124. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/recordUtils.ts +159 -0
  125. package/dist/force-app/main/default/webapplications/appreactsampleb2x/src/utils/sanitizationUtils.ts +49 -0
  126. package/dist/package.json +1 -1
  127. package/package.json +2 -2
  128. package/dist/force-app/main/default/classes/MaintenanceRequestListAction.cls +0 -111
  129. package/dist/force-app/main/default/classes/MaintenanceRequestListAction.cls-meta.xml +0 -6
  130. package/dist/force-app/main/default/classes/MaintenanceRequestUpdatePriorityAction.cls +0 -93
  131. package/dist/force-app/main/default/classes/MaintenanceRequestUpdatePriorityAction.cls-meta.xml +0 -6
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Object metadata GraphQL service (uiapi.objectInfos).
3
+ *
4
+ * Single endpoint for object describe and picklist values. Used by objectInfoService
5
+ * to implement getObjectInfoBatch and getPicklistValues. Not used directly by UI.
6
+ *
7
+ * @module api/objectInfoGraphQLService
8
+ */
9
+
10
+ import { getDataSDK } from "@salesforce/sdk-data";
11
+
12
+ /** GraphQL objectInfoInputs for requesting picklist values (API v65.0+). Only apiName and fieldNames are sent; record type filtering is done from the response. */
13
+ export interface ObjectInfoInput {
14
+ apiName: string;
15
+ fieldNames?: string[] | null;
16
+ }
17
+
18
+ /** Raw GraphQL response shape for uiapi.objectInfos (flexible for schema casing). */
19
+ export interface ObjectInfosGraphQLResponse {
20
+ uiapi?: {
21
+ objectInfos?: Array<Record<string, unknown>>;
22
+ };
23
+ }
24
+
25
+ /**
26
+ * Builds objectInfos query (metadata only). Uses apiNames only — do not pass objectInfoInputs.
27
+ */
28
+ function buildObjectInfosQuery(): string {
29
+ return `query GetObjectInfos($apiNames: [String!]!) {
30
+ uiapi {
31
+ objectInfos(apiNames: $apiNames) {
32
+ ApiName
33
+ label
34
+ labelPlural
35
+ nameFields
36
+ defaultRecordTypeId
37
+ keyPrefix
38
+ layoutable
39
+ queryable
40
+ searchable
41
+ updateable
42
+ deletable
43
+ createable
44
+ custom
45
+ mruEnabled
46
+ feedEnabled
47
+ fields {
48
+ ApiName
49
+ label
50
+ dataType
51
+ relationshipName
52
+ reference
53
+ compound
54
+ compoundFieldName
55
+ compoundComponentName
56
+ controllingFields
57
+ controllerName
58
+ referenceToInfos {
59
+ ApiName
60
+ nameFields
61
+ }
62
+ }
63
+ recordTypeInfos {
64
+ recordTypeId
65
+ name
66
+ master
67
+ available
68
+ defaultRecordTypeMapping
69
+ }
70
+ themeInfo {
71
+ color
72
+ iconUrl
73
+ }
74
+ childRelationships {
75
+ relationshipName
76
+ fieldName
77
+ childObjectApiName
78
+ }
79
+ dependentFields {
80
+ controllingField
81
+ }
82
+ }
83
+ }
84
+ }`;
85
+ }
86
+
87
+ /**
88
+ * Builds objectInfos query with picklist values (API v65.0+).
89
+ * Schema requires objectInfos to be called with either apiNames or objectInfoInputs, not both.
90
+ * This query uses objectInfoInputs only.
91
+ */
92
+ function buildObjectInfosWithPicklistsQuery(): string {
93
+ return `query GetPicklistValues($objectInfoInputs: [ObjectInfoInput!]!) {
94
+ uiapi {
95
+ objectInfos(objectInfoInputs: $objectInfoInputs) {
96
+ ApiName
97
+ label
98
+ labelPlural
99
+ nameFields
100
+ defaultRecordTypeId
101
+ keyPrefix
102
+ layoutable
103
+ queryable
104
+ searchable
105
+ updateable
106
+ deletable
107
+ createable
108
+ custom
109
+ mruEnabled
110
+ feedEnabled
111
+ fields {
112
+ ApiName
113
+ label
114
+ dataType
115
+ relationshipName
116
+ reference
117
+ compound
118
+ compoundFieldName
119
+ compoundComponentName
120
+ controllingFields
121
+ controllerName
122
+ referenceToInfos {
123
+ ApiName
124
+ nameFields
125
+ }
126
+ ... on PicklistField {
127
+ picklistValuesByRecordTypeIDs {
128
+ recordTypeID
129
+ defaultValue {
130
+ value
131
+ }
132
+ picklistValues {
133
+ label
134
+ value
135
+ validFor
136
+ }
137
+ }
138
+ }
139
+ }
140
+ recordTypeInfos {
141
+ recordTypeId
142
+ name
143
+ master
144
+ available
145
+ defaultRecordTypeMapping
146
+ }
147
+ themeInfo {
148
+ color
149
+ iconUrl
150
+ }
151
+ childRelationships {
152
+ relationshipName
153
+ fieldName
154
+ childObjectApiName
155
+ }
156
+ dependentFields {
157
+ controllingField
158
+ }
159
+ }
160
+ }
161
+ }`;
162
+ }
163
+
164
+ /**
165
+ * Fetches object metadata for the given objects via GraphQL.
166
+ *
167
+ * @param apiNames - Object API names (e.g. ["Account", "Contact"]).
168
+ * @param options.objectInfoInputs - When set, picklist values for specified fields are included (API v65.0+).
169
+ * @param options.signal - Optional abort signal.
170
+ * @returns Raw uiapi.objectInfos response (adapt to REST shape via graphQLObjectInfosToBatchResponse).
171
+ */
172
+ export async function getObjectInfosGraphQL(
173
+ apiNames: string[],
174
+ options?: {
175
+ objectInfoInputs?: ObjectInfoInput[] | null;
176
+ signal?: AbortSignal;
177
+ },
178
+ ): Promise<ObjectInfosGraphQLResponse> {
179
+ const names = apiNames.length ? apiNames : [];
180
+ const hasInputs = options?.objectInfoInputs != null && options.objectInfoInputs.length > 0;
181
+ const query = hasInputs ? buildObjectInfosWithPicklistsQuery() : buildObjectInfosQuery();
182
+ const variables: Record<string, unknown> = hasInputs
183
+ ? { objectInfoInputs: options!.objectInfoInputs }
184
+ : { apiNames: names };
185
+ const data = await getDataSDK();
186
+ const response = await data.graphql?.<ObjectInfosGraphQLResponse>(query, variables);
187
+
188
+ if (response?.errors?.length) {
189
+ const errorMessages = response.errors.map((e) => e.message).join("; ");
190
+ throw new Error(`GraphQL Error: ${errorMessages}`);
191
+ }
192
+
193
+ return response?.data ?? ({} as ObjectInfosGraphQLResponse);
194
+ }
@@ -0,0 +1,199 @@
1
+ import { uiApiClient } from "@salesforce/webapp-experimental/api";
2
+ import { z } from "zod";
3
+ import type { SearchResultsResponse, KeywordSearchResult } from "../types/search/searchResults";
4
+ import { SearchResultsResponseSchema } from "../types/search/searchResults";
5
+ import { FilterCriteriaArraySchema } from "../types/filters/filters";
6
+ import type { Filter } from "../types/filters/filters";
7
+ import { FilterArraySchema } from "../types/filters/filters";
8
+ import type { PicklistValue } from "../types/filters/picklist";
9
+ import type { ObjectInfoBatchResponse } from "../types/objectInfo/objectInfo";
10
+ import { fetchAndValidate, safeEncodePath } from "../utils/apiUtils";
11
+ import { getObjectInfosGraphQL } from "./objectInfoGraphQLService";
12
+ import {
13
+ graphQLObjectInfosToBatchResponse,
14
+ extractPicklistValuesFromGraphQLObjectInfo,
15
+ } from "../utils/graphQLObjectInfoAdapter";
16
+
17
+ /**
18
+ * Object info and search service.
19
+ *
20
+ * - getObjectInfoBatch / getPicklistValues: GraphQL (objectInfoGraphQLService).
21
+ * - getObjectListFilters, searchResults: REST (search-info, search/results).
22
+ * Hooks use this service; components do not call it directly.
23
+ *
24
+ * @module api/objectInfoService
25
+ */
26
+
27
+ /** Cache key: sorted, comma-joined object API names. */
28
+ function getObjectInfoBatchCacheKey(objectApiNames: string): string {
29
+ const names = objectApiNames
30
+ .split(",")
31
+ .map((s) => s.trim())
32
+ .filter(Boolean);
33
+ return [...names].sort().join(",");
34
+ }
35
+
36
+ const objectInfoBatchCache = new Map<string, ObjectInfoBatchResponse>();
37
+ const objectInfoBatchInFlight = new Map<string, Promise<ObjectInfoBatchResponse>>();
38
+
39
+ /**
40
+ * Fetches batch object information for the specified objects via GraphQL (uiapi.objectInfos).
41
+ * Results are cached by object set so List, Home, and Detail views share one request.
42
+ *
43
+ * @param objectApiNames - Comma-separated list of object API names (e.g., "Account,AccountBrand")
44
+ * @param signal - Optional AbortSignal to cancel the request
45
+ * @returns Promise resolving to the object info batch response (REST-compatible shape)
46
+ */
47
+ export async function getObjectInfoBatch(
48
+ objectApiNames: string,
49
+ signal?: AbortSignal,
50
+ ): Promise<ObjectInfoBatchResponse> {
51
+ const names = objectApiNames
52
+ .split(",")
53
+ .map((s) => s.trim())
54
+ .filter(Boolean);
55
+ if (names.length === 0) {
56
+ return { results: [] };
57
+ }
58
+ const key = getObjectInfoBatchCacheKey(objectApiNames);
59
+ const cached = objectInfoBatchCache.get(key);
60
+ if (cached) return Promise.resolve(cached);
61
+ const inFlight = objectInfoBatchInFlight.get(key);
62
+ if (inFlight) return inFlight;
63
+ const promise = (async () => {
64
+ try {
65
+ const response = await getObjectInfosGraphQL(names, { signal });
66
+ const nodes = response?.uiapi?.objectInfos ?? [];
67
+ const result = graphQLObjectInfosToBatchResponse(nodes, names);
68
+ objectInfoBatchCache.set(key, result);
69
+ return result;
70
+ } finally {
71
+ objectInfoBatchInFlight.delete(key);
72
+ }
73
+ })();
74
+ objectInfoBatchInFlight.set(key, promise);
75
+ return promise;
76
+ }
77
+
78
+ /**
79
+ * Fetches list filters for a specific object.
80
+ * Salesforce Search supports "Search Filters" (refinements) which are configured per object.
81
+ * This API returns the available filters (e.g., "Close Date", "Stage") that the user
82
+ * can use to narrow down the search results.
83
+ * @param objectApiName - The API name of the object (e.g., "Account")
84
+ * @param signal - Optional AbortSignal to cancel the request
85
+ * @returns Promise resolving to the search filters array
86
+ */
87
+ export async function getObjectListFilters(
88
+ objectApiName: string,
89
+ signal?: AbortSignal,
90
+ ): Promise<Filter[]> {
91
+ return fetchAndValidate(
92
+ (abortSignal) =>
93
+ uiApiClient.get(`/search-info/${safeEncodePath(objectApiName)}/filters`, {
94
+ signal: abortSignal,
95
+ }),
96
+ {
97
+ schema: FilterArraySchema,
98
+ errorContext: `filters for ${objectApiName}`,
99
+ extractData: (data: unknown) => {
100
+ if (!data) return [];
101
+ return Array.isArray(data) ? data : (data as { filters?: unknown }).filters || [];
102
+ },
103
+ signal,
104
+ },
105
+ );
106
+ }
107
+
108
+ /**
109
+ * Fetches picklist values for a specific field via GraphQL (uiapi.objectInfos with objectInfoInputs).
110
+ *
111
+ * @param objectApiName - The API name of the object (e.g., "Account")
112
+ * @param fieldName - The API name of the field (e.g., "Type")
113
+ * @param recordTypeId - Optional record type ID (defaults to "012000000000000AAA" which is the default/master record type)
114
+ * @param signal - Optional AbortSignal to cancel the request
115
+ * @returns Promise resolving to an array of picklist values
116
+ */
117
+ export async function getPicklistValues(
118
+ objectApiName: string,
119
+ fieldName: string,
120
+ recordTypeId: string = "012000000000000AAA",
121
+ signal?: AbortSignal,
122
+ ): Promise<PicklistValue[]> {
123
+ const response = await getObjectInfosGraphQL([objectApiName], {
124
+ objectInfoInputs: [
125
+ {
126
+ apiName: objectApiName,
127
+ fieldNames: [fieldName],
128
+ },
129
+ ],
130
+ signal,
131
+ });
132
+ const nodes = response?.uiapi?.objectInfos ?? [];
133
+ const node = nodes[0];
134
+ if (!node) return [];
135
+ return extractPicklistValuesFromGraphQLObjectInfo(node, fieldName, recordTypeId);
136
+ }
137
+
138
+ // Zod Schema for Search Parameters
139
+ const SearchParamsSchema = z.object({
140
+ filters: FilterCriteriaArraySchema.optional(),
141
+ pageSize: z.number().optional(),
142
+ pageToken: z.string().optional(),
143
+ sortBy: z.string().optional(),
144
+ });
145
+
146
+ /**
147
+ * Search parameters for keyword search
148
+ */
149
+ export type SearchParams = z.infer<typeof SearchParamsSchema>;
150
+
151
+ /**
152
+ * Performs a keyword search on a specific object.
153
+ * Returns records that match the text query along with pagination information.
154
+ *
155
+ * @param query - The search query string
156
+ * @param objectApiName - The API name of the object to search (e.g., "Account")
157
+ * @param params - Optional search parameters (pageSize, pageToken, filters, sortBy)
158
+ * @param signal - Optional AbortSignal to cancel the request
159
+ * @returns Promise resolving to the keyword search result with records and pagination tokens
160
+ */
161
+ export async function searchResults(
162
+ query: string,
163
+ objectApiName: string,
164
+ params?: SearchParams,
165
+ signal?: AbortSignal,
166
+ ): Promise<KeywordSearchResult> {
167
+ const searchParams = new URLSearchParams({
168
+ q: query,
169
+ objectApiName: objectApiName,
170
+ });
171
+
172
+ const body = {
173
+ filters: params?.filters ?? [],
174
+ pageSize: params?.pageSize ?? 50,
175
+ pageToken: params?.pageToken ?? "0",
176
+ sortBy: params?.sortBy ?? "",
177
+ };
178
+
179
+ const response = await fetchAndValidate<SearchResultsResponse>(
180
+ (abortSignal) =>
181
+ uiApiClient.post(`/search/results/keyword?${searchParams.toString()}`, body, {
182
+ signal: abortSignal,
183
+ }),
184
+ {
185
+ schema: SearchResultsResponseSchema,
186
+ errorContext: `search results for ${objectApiName} with query "${query}"`,
187
+ signal,
188
+ },
189
+ );
190
+
191
+ return response.keywordSearchResult;
192
+ }
193
+
194
+ export const objectInfoService = {
195
+ getObjectInfoBatch,
196
+ getObjectListFilters,
197
+ getPicklistValues,
198
+ searchResults,
199
+ };