@salesforce/webapp-template-app-react-template-b2x-experimental 1.76.0 → 1.77.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.
- package/dist/CHANGELOG.md +16 -0
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/package.json +3 -3
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectDetailService.ts +3 -26
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectInfoGraphQLService.ts +108 -165
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/api/objectInfoService.ts +9 -113
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/components/detail/UiApiDetailForm.tsx +2 -2
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useObjectInfoBatch.ts +1 -1
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useObjectSearchData.ts +7 -228
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/hooks/useRecordDetailLayout.ts +1 -20
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/filters/picklist.ts +5 -31
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/objectInfo/objectInfo.ts +46 -163
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/types/schema.d.ts +200 -0
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/apiUtils.ts +3 -69
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/graphQLObjectInfoAdapter.ts +37 -279
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/features/global-search/utils/recordUtils.ts +4 -4
- package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/index.ts +120 -0
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.77.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.76.1...v1.77.0) (2026-03-06)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [1.76.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.76.0...v1.76.1) (2026-03-06)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @salesforce/webapp-template-base-sfdx-project-experimental
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
# [1.76.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.75.1...v1.76.0) (2026-03-06)
|
|
7
23
|
|
|
8
24
|
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"graphql:schema": "node scripts/get-graphql-schema.mjs"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@salesforce/sdk-data": "^1.
|
|
19
|
-
"@salesforce/webapp-experimental": "^1.
|
|
18
|
+
"@salesforce/sdk-data": "^1.77.0",
|
|
19
|
+
"@salesforce/webapp-experimental": "^1.77.0",
|
|
20
20
|
"@tailwindcss/vite": "^4.1.17",
|
|
21
21
|
"@tanstack/react-form": "^1.28.4",
|
|
22
22
|
"class-variance-authority": "^0.7.1",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@graphql-eslint/eslint-plugin": "^4.1.0",
|
|
41
41
|
"@graphql-tools/utils": "^11.0.0",
|
|
42
42
|
"@playwright/test": "^1.49.0",
|
|
43
|
-
"@salesforce/vite-plugin-webapp-experimental": "^1.
|
|
43
|
+
"@salesforce/vite-plugin-webapp-experimental": "^1.77.0",
|
|
44
44
|
"@testing-library/jest-dom": "^6.6.3",
|
|
45
45
|
"@testing-library/react": "^16.1.0",
|
|
46
46
|
"@testing-library/user-event": "^14.5.2",
|
|
@@ -36,17 +36,9 @@ export function extractFieldsFromLayout(
|
|
|
36
36
|
return optionalFields;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/**
|
|
40
|
-
* Fetches the Full/View layout for an object (REST). Used by detail view to render sections/rows/items.
|
|
41
|
-
*
|
|
42
|
-
* @param objectApiName - Object API name.
|
|
43
|
-
* @param recordTypeId - Record type Id (default master).
|
|
44
|
-
* @param signal - Optional abort signal.
|
|
45
|
-
*/
|
|
46
39
|
export async function getLayout(
|
|
47
40
|
objectApiName: string,
|
|
48
41
|
recordTypeId: string = DEFAULT_RECORD_TYPE_ID,
|
|
49
|
-
signal?: AbortSignal,
|
|
50
42
|
): Promise<LayoutResponse> {
|
|
51
43
|
const params = new URLSearchParams({
|
|
52
44
|
layoutType: "Full",
|
|
@@ -54,14 +46,10 @@ export async function getLayout(
|
|
|
54
46
|
recordTypeId,
|
|
55
47
|
});
|
|
56
48
|
return fetchAndValidate(
|
|
57
|
-
(
|
|
58
|
-
uiApiClient.get(`/layout/${safeEncodePath(objectApiName)}?${params.toString()}`, {
|
|
59
|
-
signal: abortSignal,
|
|
60
|
-
}),
|
|
49
|
+
() => uiApiClient.get(`/layout/${safeEncodePath(objectApiName)}?${params.toString()}`),
|
|
61
50
|
{
|
|
62
51
|
schema: LayoutResponseSchema,
|
|
63
52
|
errorContext: `layout for ${objectApiName}`,
|
|
64
|
-
signal,
|
|
65
53
|
},
|
|
66
54
|
);
|
|
67
55
|
}
|
|
@@ -86,24 +74,13 @@ function optionalFieldsToColumns(optionalFields: string[]): Column[] {
|
|
|
86
74
|
}));
|
|
87
75
|
}
|
|
88
76
|
|
|
89
|
-
/**
|
|
90
|
-
* Fetches everything needed for the detail page: layout (REST), object metadata (GraphQL), single record (GraphQL).
|
|
91
|
-
* Layout drives which fields are requested; getRecordByIdGraphQL fetches that field set by Id.
|
|
92
|
-
*
|
|
93
|
-
* @param objectApiName - Object API name.
|
|
94
|
-
* @param recordId - Record Id.
|
|
95
|
-
* @param recordTypeId - Record type (default master).
|
|
96
|
-
* @param signal - Optional abort signal.
|
|
97
|
-
* @returns { layout, record, objectMetadata } for DetailForm / UiApiDetailForm.
|
|
98
|
-
*/
|
|
99
77
|
export async function getRecordDetail(
|
|
100
78
|
objectApiName: string,
|
|
101
79
|
recordId: string,
|
|
102
80
|
recordTypeId: string = DEFAULT_RECORD_TYPE_ID,
|
|
103
|
-
signal?: AbortSignal,
|
|
104
81
|
): Promise<RecordDetailResult> {
|
|
105
|
-
const layout = await getLayout(objectApiName, recordTypeId
|
|
106
|
-
const objectMetadata = await objectInfoService.getObjectInfoBatch(objectApiName
|
|
82
|
+
const layout = await getLayout(objectApiName, recordTypeId);
|
|
83
|
+
const objectMetadata = await objectInfoService.getObjectInfoBatch(objectApiName);
|
|
107
84
|
const firstResult = objectMetadata?.results?.[0]?.result;
|
|
108
85
|
if (!firstResult) {
|
|
109
86
|
throw new Error(`Object metadata not found for ${objectApiName}`);
|
|
@@ -7,188 +7,131 @@
|
|
|
7
7
|
* @module api/objectInfoGraphQLService
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { getDataSDK } from "@salesforce/sdk-data";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
}
|
|
10
|
+
import { getDataSDK, gql } from "@salesforce/sdk-data";
|
|
11
|
+
import type {
|
|
12
|
+
GetObjectInfosQuery,
|
|
13
|
+
GetObjectInfosQueryVariables,
|
|
14
|
+
GetPicklistValuesQuery,
|
|
15
|
+
GetPicklistValuesQueryVariables,
|
|
16
|
+
ObjectInfoInput,
|
|
17
|
+
} from "../types/schema";
|
|
24
18
|
|
|
25
19
|
/**
|
|
26
20
|
* Builds objectInfos query (metadata only). Uses apiNames only — do not pass objectInfoInputs.
|
|
27
21
|
*/
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
22
|
+
const OBJECT_INFOS_QUERY = gql`
|
|
23
|
+
query GetObjectInfos($apiNames: [String!]!) {
|
|
24
|
+
uiapi {
|
|
25
|
+
objectInfos(apiNames: $apiNames) {
|
|
26
|
+
ApiName
|
|
27
|
+
label
|
|
28
|
+
labelPlural
|
|
29
|
+
nameFields
|
|
30
|
+
defaultRecordTypeId
|
|
31
|
+
keyPrefix
|
|
32
|
+
layoutable
|
|
33
|
+
queryable
|
|
34
|
+
searchable
|
|
35
|
+
updateable
|
|
36
|
+
deletable
|
|
37
|
+
createable
|
|
38
|
+
custom
|
|
39
|
+
mruEnabled
|
|
40
|
+
feedEnabled
|
|
41
|
+
fields {
|
|
42
|
+
ApiName
|
|
43
|
+
label
|
|
44
|
+
dataType
|
|
45
|
+
relationshipName
|
|
46
|
+
reference
|
|
47
|
+
compound
|
|
48
|
+
compoundFieldName
|
|
49
|
+
compoundComponentName
|
|
50
|
+
controllingFields
|
|
51
|
+
controllerName
|
|
52
|
+
referenceToInfos {
|
|
53
|
+
ApiName
|
|
54
|
+
nameFields
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
recordTypeInfos {
|
|
58
|
+
recordTypeId
|
|
59
|
+
name
|
|
60
|
+
master
|
|
61
|
+
available
|
|
62
|
+
defaultRecordTypeMapping
|
|
63
|
+
}
|
|
64
|
+
themeInfo {
|
|
65
|
+
color
|
|
66
|
+
iconUrl
|
|
67
|
+
}
|
|
68
|
+
childRelationships {
|
|
69
|
+
relationshipName
|
|
70
|
+
fieldName
|
|
71
|
+
childObjectApiName
|
|
72
|
+
}
|
|
73
|
+
dependentFields {
|
|
74
|
+
controllingField
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
86
80
|
|
|
87
81
|
/**
|
|
88
82
|
* Builds objectInfos query with picklist values (API v65.0+).
|
|
89
83
|
* Schema requires objectInfos to be called with either apiNames or objectInfoInputs, not both.
|
|
90
84
|
* This query uses objectInfoInputs only.
|
|
85
|
+
* Optimized to only fetch fields used by extractPicklistValuesFromGraphQLObjectInfo.
|
|
91
86
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
}`;
|
|
87
|
+
const PICKLIST_VALUES_QUERY = gql`
|
|
88
|
+
query GetPicklistValues($objectInfoInputs: [ObjectInfoInput!]!) {
|
|
89
|
+
uiapi {
|
|
90
|
+
objectInfos(objectInfoInputs: $objectInfoInputs) {
|
|
91
|
+
ApiName
|
|
92
|
+
fields {
|
|
93
|
+
ApiName
|
|
94
|
+
... on PicklistField {
|
|
95
|
+
picklistValuesByRecordTypeIDs {
|
|
96
|
+
recordTypeID
|
|
97
|
+
defaultValue {
|
|
98
|
+
value
|
|
99
|
+
}
|
|
100
|
+
picklistValues {
|
|
101
|
+
label
|
|
102
|
+
value
|
|
103
|
+
validFor
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
|
|
113
|
+
export async function queryForObjectInfos(apiNames: string[]): Promise<GetObjectInfosQuery> {
|
|
114
|
+
return runQuery<GetObjectInfosQuery, GetObjectInfosQueryVariables>(OBJECT_INFOS_QUERY, {
|
|
115
|
+
apiNames,
|
|
116
|
+
});
|
|
162
117
|
}
|
|
163
118
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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 };
|
|
119
|
+
export async function queryForPicklistValues(
|
|
120
|
+
objectInfoInputs: ObjectInfoInput[],
|
|
121
|
+
): Promise<GetPicklistValuesQuery> {
|
|
122
|
+
return runQuery<GetPicklistValuesQuery, GetPicklistValuesQueryVariables>(PICKLIST_VALUES_QUERY, {
|
|
123
|
+
objectInfoInputs,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async function runQuery<Q, V>(query: string, variables: V): Promise<Q> {
|
|
185
128
|
const data = await getDataSDK();
|
|
186
|
-
const response = await data.graphql?.<
|
|
129
|
+
const response = await data.graphql?.<Q, V>(query, variables);
|
|
187
130
|
|
|
188
131
|
if (response?.errors?.length) {
|
|
189
132
|
const errorMessages = response.errors.map((e) => e.message).join("; ");
|
|
190
133
|
throw new Error(`GraphQL Error: ${errorMessages}`);
|
|
191
134
|
}
|
|
192
135
|
|
|
193
|
-
return response?.data ?? ({} as
|
|
136
|
+
return response?.data ?? ({} as Q);
|
|
194
137
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
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
2
|
import type { Filter } from "../types/filters/filters";
|
|
7
3
|
import { FilterArraySchema } from "../types/filters/filters";
|
|
8
4
|
import type { PicklistValue } from "../types/filters/picklist";
|
|
9
5
|
import type { ObjectInfoBatchResponse } from "../types/objectInfo/objectInfo";
|
|
10
6
|
import { fetchAndValidate, safeEncodePath } from "../utils/apiUtils";
|
|
11
|
-
import {
|
|
7
|
+
import { queryForObjectInfos, queryForPicklistValues } from "./objectInfoGraphQLService";
|
|
12
8
|
import {
|
|
13
9
|
graphQLObjectInfosToBatchResponse,
|
|
14
10
|
extractPicklistValuesFromGraphQLObjectInfo,
|
|
@@ -18,7 +14,7 @@ import {
|
|
|
18
14
|
* Object info and search service.
|
|
19
15
|
*
|
|
20
16
|
* - getObjectInfoBatch / getPicklistValues: GraphQL (objectInfoGraphQLService).
|
|
21
|
-
* - getObjectListFilters
|
|
17
|
+
* - getObjectListFilters: REST (search-info).
|
|
22
18
|
* Hooks use this service; components do not call it directly.
|
|
23
19
|
*
|
|
24
20
|
* @module api/objectInfoService
|
|
@@ -36,18 +32,7 @@ function getObjectInfoBatchCacheKey(objectApiNames: string): string {
|
|
|
36
32
|
const objectInfoBatchCache = new Map<string, ObjectInfoBatchResponse>();
|
|
37
33
|
const objectInfoBatchInFlight = new Map<string, Promise<ObjectInfoBatchResponse>>();
|
|
38
34
|
|
|
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> {
|
|
35
|
+
export async function getObjectInfoBatch(objectApiNames: string): Promise<ObjectInfoBatchResponse> {
|
|
51
36
|
const names = objectApiNames
|
|
52
37
|
.split(",")
|
|
53
38
|
.map((s) => s.trim())
|
|
@@ -62,7 +47,7 @@ export async function getObjectInfoBatch(
|
|
|
62
47
|
if (inFlight) return inFlight;
|
|
63
48
|
const promise = (async () => {
|
|
64
49
|
try {
|
|
65
|
-
const response = await
|
|
50
|
+
const response = await queryForObjectInfos(names);
|
|
66
51
|
const nodes = response?.uiapi?.objectInfos ?? [];
|
|
67
52
|
const result = graphQLObjectInfosToBatchResponse(nodes, names);
|
|
68
53
|
objectInfoBatchCache.set(key, result);
|
|
@@ -75,24 +60,9 @@ export async function getObjectInfoBatch(
|
|
|
75
60
|
return promise;
|
|
76
61
|
}
|
|
77
62
|
|
|
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[]> {
|
|
63
|
+
export async function getObjectListFilters(objectApiName: string): Promise<Filter[]> {
|
|
91
64
|
return fetchAndValidate(
|
|
92
|
-
(
|
|
93
|
-
uiApiClient.get(`/search-info/${safeEncodePath(objectApiName)}/filters`, {
|
|
94
|
-
signal: abortSignal,
|
|
95
|
-
}),
|
|
65
|
+
() => uiApiClient.get(`/search-info/${safeEncodePath(objectApiName)}/filters`),
|
|
96
66
|
{
|
|
97
67
|
schema: FilterArraySchema,
|
|
98
68
|
errorContext: `filters for ${objectApiName}`,
|
|
@@ -100,100 +70,26 @@ export async function getObjectListFilters(
|
|
|
100
70
|
if (!data) return [];
|
|
101
71
|
return Array.isArray(data) ? data : (data as { filters?: unknown }).filters || [];
|
|
102
72
|
},
|
|
103
|
-
signal,
|
|
104
73
|
},
|
|
105
74
|
);
|
|
106
75
|
}
|
|
107
76
|
|
|
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
77
|
export async function getPicklistValues(
|
|
118
78
|
objectApiName: string,
|
|
119
79
|
fieldName: string,
|
|
120
80
|
recordTypeId: string = "012000000000000AAA",
|
|
121
|
-
signal?: AbortSignal,
|
|
122
81
|
): Promise<PicklistValue[]> {
|
|
123
|
-
const response = await
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
apiName: objectApiName,
|
|
127
|
-
fieldNames: [fieldName],
|
|
128
|
-
},
|
|
129
|
-
],
|
|
130
|
-
signal,
|
|
131
|
-
});
|
|
82
|
+
const response = await queryForPicklistValues([
|
|
83
|
+
{ apiName: objectApiName, fieldNames: [fieldName] },
|
|
84
|
+
]);
|
|
132
85
|
const nodes = response?.uiapi?.objectInfos ?? [];
|
|
133
86
|
const node = nodes[0];
|
|
134
87
|
if (!node) return [];
|
|
135
88
|
return extractPicklistValuesFromGraphQLObjectInfo(node, fieldName, recordTypeId);
|
|
136
89
|
}
|
|
137
90
|
|
|
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
91
|
export const objectInfoService = {
|
|
195
92
|
getObjectInfoBatch,
|
|
196
93
|
getObjectListFilters,
|
|
197
94
|
getPicklistValues,
|
|
198
|
-
searchResults,
|
|
199
95
|
};
|
|
@@ -75,7 +75,7 @@ export function UiApiDetailForm({
|
|
|
75
75
|
|
|
76
76
|
const objectInfo: ObjectInfo | null = useMemo(() => {
|
|
77
77
|
if (!metadata?.fields) return null;
|
|
78
|
-
const apiName =
|
|
78
|
+
const apiName = metadata.ApiName;
|
|
79
79
|
return {
|
|
80
80
|
apiName,
|
|
81
81
|
fields: Object.fromEntries(
|
|
@@ -83,7 +83,7 @@ export function UiApiDetailForm({
|
|
|
83
83
|
name,
|
|
84
84
|
{
|
|
85
85
|
compoundFieldName: f.compoundFieldName ?? undefined,
|
|
86
|
-
dataType: f.dataType,
|
|
86
|
+
dataType: f.dataType ?? "",
|
|
87
87
|
},
|
|
88
88
|
]),
|
|
89
89
|
),
|
|
@@ -44,7 +44,7 @@ export function useObjectInfoBatch(objectApiNames: string[]): UseObjectInfoBatch
|
|
|
44
44
|
.then((res) => {
|
|
45
45
|
if (isCancelled.current) return;
|
|
46
46
|
const objectInfos = names
|
|
47
|
-
.map((apiName) => res.results?.find((r) => r.result?.
|
|
47
|
+
.map((apiName) => res.results?.find((r) => r.result?.ApiName === apiName)?.result)
|
|
48
48
|
.filter((r) => r != null) as ObjectInfoResult[];
|
|
49
49
|
setState({ objectInfos, loading: false, error: null });
|
|
50
50
|
})
|