@salesforce/webapp-template-feature-react-global-search-experimental 1.3.3

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 (111) hide show
  1. package/LICENSE.txt +82 -0
  2. package/README.md +415 -0
  3. package/dist/.a4drules/build-validation.md +81 -0
  4. package/dist/.a4drules/code-quality.md +150 -0
  5. package/dist/.a4drules/graphql/tools/knowledge/lds-explore-graphql-schema.md +227 -0
  6. package/dist/.a4drules/graphql/tools/knowledge/lds-generate-graphql-mutationquery.md +211 -0
  7. package/dist/.a4drules/graphql/tools/knowledge/lds-generate-graphql-readquery.md +185 -0
  8. package/dist/.a4drules/graphql/tools/knowledge/lds-guide-graphql.md +205 -0
  9. package/dist/.a4drules/graphql/tools/schemas/shared.graphqls +1150 -0
  10. package/dist/.a4drules/graphql.md +98 -0
  11. package/dist/.a4drules/images.md +13 -0
  12. package/dist/.a4drules/react.md +361 -0
  13. package/dist/.a4drules/react_image_processing.md +45 -0
  14. package/dist/.a4drules/typescript.md +224 -0
  15. package/dist/.forceignore +15 -0
  16. package/dist/.husky/pre-commit +4 -0
  17. package/dist/.prettierignore +11 -0
  18. package/dist/.prettierrc +17 -0
  19. package/dist/CHANGELOG.md +11 -0
  20. package/dist/README.md +18 -0
  21. package/dist/config/project-scratch-def.json +13 -0
  22. package/dist/force-app/main/default/webapplications/feature-react-global-search/.prettierignore +9 -0
  23. package/dist/force-app/main/default/webapplications/feature-react-global-search/.prettierrc +11 -0
  24. package/dist/force-app/main/default/webapplications/feature-react-global-search/eslint.config.js +113 -0
  25. package/dist/force-app/main/default/webapplications/feature-react-global-search/feature-react-global-search.webapplication-meta.xml +7 -0
  26. package/dist/force-app/main/default/webapplications/feature-react-global-search/index.html +13 -0
  27. package/dist/force-app/main/default/webapplications/feature-react-global-search/package.json +42 -0
  28. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/api/graphql-operations-types.ts +127 -0
  29. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/api/objectInfoService.ts +229 -0
  30. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/api/utils/query/highRevenueAccountsQuery.graphql +29 -0
  31. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/app.tsx +13 -0
  32. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/appLayout.tsx +9 -0
  33. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/icons/book.svg +3 -0
  34. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/icons/copy.svg +4 -0
  35. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/icons/rocket.svg +3 -0
  36. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/icons/star.svg +3 -0
  37. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/images/codey-1.png +0 -0
  38. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/images/codey-2.png +0 -0
  39. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/images/codey-3.png +0 -0
  40. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/assets/images/vibe-codey.svg +194 -0
  41. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/FiltersPanel.tsx +373 -0
  42. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/LoadingFallback.tsx +61 -0
  43. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/SearchResultCard.tsx +127 -0
  44. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/alerts/status-alert.tsx +45 -0
  45. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/detail/DetailFields.tsx +57 -0
  46. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/detail/DetailHeader.tsx +42 -0
  47. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/filters/FilterField.tsx +54 -0
  48. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/filters/FilterInput.tsx +55 -0
  49. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/filters/FilterSelect.tsx +72 -0
  50. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/forms/filters-form.tsx +114 -0
  51. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/forms/submit-button.tsx +47 -0
  52. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/layout/card-layout.tsx +19 -0
  53. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/search/ResultCardFields.tsx +71 -0
  54. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/search/SearchHeader.tsx +23 -0
  55. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/search/SearchPagination.tsx +162 -0
  56. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/search/SearchResultsPanel.tsx +184 -0
  57. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/shared/GlobalSearchInput.tsx +110 -0
  58. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/alert.tsx +65 -0
  59. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/button.tsx +56 -0
  60. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/card.tsx +77 -0
  61. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/field.tsx +111 -0
  62. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/index.ts +71 -0
  63. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/input.tsx +19 -0
  64. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/label.tsx +19 -0
  65. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/pagination.tsx +99 -0
  66. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/select.tsx +151 -0
  67. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/skeleton.tsx +7 -0
  68. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/spinner.tsx +21 -0
  69. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/table.tsx +114 -0
  70. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/components/ui/tabs.tsx +115 -0
  71. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/constants.ts +36 -0
  72. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/features/global-search/index.ts +65 -0
  73. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/hooks/form.tsx +208 -0
  74. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/hooks/useObjectSearchData.ts +419 -0
  75. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/hooks/useRecordDetail.ts +127 -0
  76. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/lib/utils.ts +6 -0
  77. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/pages/About.tsx +12 -0
  78. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/pages/DetailPage.tsx +128 -0
  79. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/pages/GlobalSearch.tsx +173 -0
  80. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/pages/Home.tsx +13 -0
  81. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/pages/NotFound.tsx +18 -0
  82. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/routes.tsx +50 -0
  83. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/styles/global.css +108 -0
  84. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/types/filters/filters.ts +122 -0
  85. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/types/filters/picklist.ts +32 -0
  86. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/types/objectInfo/objectInfo.ts +166 -0
  87. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/types/search/searchResults.ts +228 -0
  88. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/apiUtils.ts +125 -0
  89. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/cacheUtils.ts +76 -0
  90. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/debounce.ts +89 -0
  91. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/fieldUtils.ts +186 -0
  92. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/fieldValueExtractor.ts +67 -0
  93. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/filterUtils.ts +32 -0
  94. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/formUtils.ts +130 -0
  95. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/paginationUtils.ts +49 -0
  96. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/recordUtils.ts +75 -0
  97. package/dist/force-app/main/default/webapplications/feature-react-global-search/src/utils/sanitizationUtils.ts +49 -0
  98. package/dist/force-app/main/default/webapplications/feature-react-global-search/tsconfig.json +36 -0
  99. package/dist/force-app/main/default/webapplications/feature-react-global-search/tsconfig.node.json +13 -0
  100. package/dist/force-app/main/default/webapplications/feature-react-global-search/vite-env.d.ts +1 -0
  101. package/dist/force-app/main/default/webapplications/feature-react-global-search/vite.config.ts +82 -0
  102. package/dist/force-app/main/default/webapplications/feature-react-global-search/vitest-env.d.ts +2 -0
  103. package/dist/force-app/main/default/webapplications/feature-react-global-search/vitest.config.ts +11 -0
  104. package/dist/force-app/main/default/webapplications/feature-react-global-search/vitest.setup.ts +1 -0
  105. package/dist/force-app/main/default/webapplications/feature-react-global-search/webapplication.json +7 -0
  106. package/dist/jest.config.js +6 -0
  107. package/dist/package.json +37 -0
  108. package/dist/scripts/apex/hello.apex +10 -0
  109. package/dist/scripts/soql/account.soql +6 -0
  110. package/dist/sfdx-project.json +12 -0
  111. package/package.json +32 -0
package/LICENSE.txt ADDED
@@ -0,0 +1,82 @@
1
+ Terms of Use
2
+
3
+ Copyright 2026 Salesforce, Inc. All rights reserved.
4
+
5
+ These Terms of Use govern the download, installation, and/or use of this
6
+ software provided by Salesforce, Inc. ("Salesforce") (the "Software"), were
7
+ last updated on April 15, 2025, and constitute a legally binding
8
+ agreement between you and Salesforce. If you do not agree to these Terms of
9
+ Use, do not install or use the Software.
10
+
11
+ Salesforce grants you a worldwide, non-exclusive, no-charge, royalty-free
12
+ copyright license to reproduce, prepare derivative works of, publicly
13
+ display, publicly perform, sublicense, and distribute the Software and
14
+ derivative works subject to these Terms. These Terms shall be included in
15
+ all copies or substantial portions of the Software.
16
+
17
+ Subject to the limited rights expressly granted hereunder, Salesforce
18
+ reserves all rights, title, and interest in and to all intellectual
19
+ property subsisting in the Software. No rights are granted to you hereunder
20
+ other than as expressly set forth herein. Users residing in countries on
21
+ the United States Office of Foreign Assets Control sanction list, or which
22
+ are otherwise subject to a US export embargo, may not use the Software.
23
+
24
+ Implementation of the Software may require development work, for which you
25
+ are responsible. The Software may contain bugs, errors and
26
+ incompatibilities and is made available on an AS IS basis without support,
27
+ updates, or service level commitments.
28
+
29
+ Salesforce reserves the right at any time to modify, suspend, or
30
+ discontinue, the Software (or any part thereof) with or without notice. You
31
+ agree that Salesforce shall not be liable to you or to any third party for
32
+ any modification, suspension, or discontinuance.
33
+
34
+ You agree to defend Salesforce against any claim, demand, suit or
35
+ proceeding made or brought against Salesforce by a third party arising out
36
+ of or accruing from (a) your use of the Software, and (b) any application
37
+ you develop with the Software that infringes any copyright, trademark,
38
+ trade secret, trade dress, patent, or other intellectual property right of
39
+ any person or defames any person or violates their rights of publicity or
40
+ privacy (each a "Claim Against Salesforce"), and will indemnify Salesforce
41
+ from any damages, attorney fees, and costs finally awarded against
42
+ Salesforce as a result of, or for any amounts paid by Salesforce under a
43
+ settlement approved by you in writing of, a Claim Against Salesforce,
44
+ provided Salesforce (x) promptly gives you written notice of the Claim
45
+ Against Salesforce, (y) gives you sole control of the defense and
46
+ settlement of the Claim Against Salesforce (except that you may not settle
47
+ any Claim Against Salesforce unless it unconditionally releases Salesforce
48
+ of all liability), and (z) gives you all reasonable assistance, at your
49
+ expense.
50
+
51
+ WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE SOFTWARE IS NOT
52
+ SUPPORTED AND IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
53
+ IMPLIED. IN NO EVENT SHALL SALESFORCE HAVE ANY LIABILITY FOR ANY DAMAGES,
54
+ INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL, INCIDENTAL,
55
+ PUNITIVE, OR CONSEQUENTIAL DAMAGES, OR DAMAGES BASED ON LOST PROFITS, DATA,
56
+ OR USE, IN CONNECTION WITH THE SOFTWARE, HOWEVER CAUSED AND WHETHER IN
57
+ CONTRACT, TORT, OR UNDER ANY OTHER THEORY OF LIABILITY, WHETHER OR NOT YOU
58
+ HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
59
+
60
+ These Terms of Use shall be governed exclusively by the internal laws of
61
+ the State of California, without regard to its conflicts of laws
62
+ rules. Each party hereby consents to the exclusive jurisdiction of the
63
+ state and federal courts located in San Francisco County, California to
64
+ adjudicate any dispute arising out of or relating to these Terms of Use and
65
+ the download, installation, and/or use of the Software. Except as expressly
66
+ stated herein, these Terms of Use constitute the entire agreement between
67
+ the parties, and supersede all prior and contemporaneous agreements,
68
+ proposals, or representations, written or oral, concerning their subject
69
+ matter. No modification, amendment, or waiver of any provision of these
70
+ Terms of Use shall be effective unless it is by an update to these Terms of
71
+ Use that Salesforce makes available, or is in writing and signed by the
72
+ party against whom the modification, amendment, or waiver is to be
73
+ asserted.
74
+
75
+ Data Privacy: Salesforce may collect, process, and store device,
76
+ system, and other information related to your use of the Software. This
77
+ information includes, but is not limited to, IP address, user metrics, and
78
+ other data ("Usage Data"). Salesforce may use Usage Data for analytics,
79
+ product development, and marketing purposes. You acknowledge that files
80
+ generated in conjunction with the Software may contain sensitive or
81
+ confidential data, and you are solely responsible for anonymizing and
82
+ protecting such data.
package/README.md ADDED
@@ -0,0 +1,415 @@
1
+ # Feature: Global Search
2
+
3
+ This feature provides API services and utilities for implementing global search functionality in Salesforce Web Applications. It includes:
4
+
5
+ - **API Service Layer** - Type-safe API client for Salesforce search endpoints
6
+ - **Type Definitions** - Complete TypeScript types with Zod schema validation
7
+ - **Utility Functions** - Helper functions for debouncing and data extraction
8
+ - **Custom Hooks** - React hooks for managing search data and API calls
9
+
10
+ ## Features
11
+
12
+ - **Multi-Object Search API** - Search across multiple Salesforce objects simultaneously
13
+ - **Object Metadata API** - Fetch object information, column definitions, and filter definitions
14
+ - **Picklist Values API** - Retrieve picklist values for dynamic filter options
15
+ - **Type Safety** - Full TypeScript support with Zod schema validation
16
+ - **Race Condition Protection** - AbortSignal support to cancel stale requests
17
+ - **Error Handling** - Consistent error handling across all API calls
18
+
19
+ ## Architecture
20
+
21
+ ### API Service Layer
22
+
23
+ The feature includes a state-agnostic service layer (`objectInfoService`) that provides pure functions for API interactions. All API calls:
24
+
25
+ - Use `fetchAndValidate` utility for consistent error handling
26
+ - Support `AbortSignal` for request cancellation
27
+ - Validate responses with Zod schemas
28
+ - Provide type-safe return values
29
+
30
+ ### API Flow Diagram
31
+
32
+ The following flowchart explains the API architecture and how each API is consumed:
33
+
34
+ ```mermaid
35
+ flowchart TD
36
+ Start([Application Initialization]) --> BatchAPI[getObjectInfoBatch API]
37
+ BatchAPI -->|Comma-separated Object Names| ObjectMetadata[Object Metadata]
38
+ ObjectMetadata --> LoadObjectData[Load Data for Each Object]
39
+
40
+ %% Parallel API Calls for Each Object
41
+ LoadObjectData --> ParallelAPIs{Parallel API Calls per Object}
42
+
43
+ %% List Info API
44
+ ParallelAPIs --> ListInfoAPI[getObjectListInfo API]
45
+ ListInfoAPI -->|Object Name + __SearchResult| Columns[Column Definitions]
46
+
47
+ %% Filters API
48
+ ParallelAPIs --> FiltersAPI[getObjectListFilters API]
49
+ FiltersAPI -->|Object Name| Filters[Filter Definitions]
50
+
51
+ %% Search Results API
52
+ ParallelAPIs --> SearchAPI[searchResults API]
53
+ SearchAPI -->|Query + Object Name + Pagination| SearchRecords[Search Records]
54
+
55
+ %% Picklist Values Flow
56
+ Filters --> PicklistCheck{Has Picklist Fields?}
57
+ PicklistCheck -->|Yes| PicklistAPI[getPicklistValues API]
58
+ PicklistAPI -->|Object Name + Field Name| PicklistValues[Picklist Options]
59
+ PicklistCheck -->|No| SkipPicklist[Skip Picklist Fetch]
60
+
61
+ %% User Interactions - API Calls
62
+ UserQuery([User Search Query]) --> Debounce[Debounce 500ms]
63
+ Debounce --> SearchAPI
64
+
65
+ FilterChange([Filter Change]) --> SearchAPI
66
+ PageChange([Pagination Change]) --> SearchAPI
67
+ PageSizeChange([Page Size Change]) --> SearchAPI
68
+
69
+ %% Error Handling
70
+ BatchAPI -.->|Error| ErrorHandler[Error Handler]
71
+ ListInfoAPI -.->|Error| ErrorHandler
72
+ FiltersAPI -.->|Error| ErrorHandler
73
+ SearchAPI -.->|Error| ErrorHandler
74
+ PicklistAPI -.->|Error| ErrorHandler
75
+ ErrorHandler --> HandleError[Handle Error Gracefully]
76
+
77
+ %% Race Condition Protection
78
+ SearchAPI -.->|AbortSignal| CancelOld[Cancel Old Request]
79
+ CancelOld --> PreventStale[Prevent Stale Data]
80
+
81
+ style BatchAPI fill:#e1f5ff
82
+ style ListInfoAPI fill:#e1f5ff
83
+ style FiltersAPI fill:#e1f5ff
84
+ style SearchAPI fill:#e1f5ff
85
+ style PicklistAPI fill:#e1f5ff
86
+ style ErrorHandler fill:#ffe1e1
87
+ style CancelOld fill:#fff4e1
88
+ ```
89
+
90
+ ## API Reference
91
+
92
+ ### 1. `getObjectInfoBatch(objectApiNames, signal?)`
93
+
94
+ **Purpose**: Fetches object metadata for multiple Salesforce objects in a single request.
95
+
96
+ **When to Use**:
97
+
98
+ - Initial page load to get object labels and basic metadata
99
+ - Needed to create tabs for each object type
100
+ - Provides object plural labels for tab display
101
+
102
+ **Parameters**:
103
+
104
+ - `objectApiNames`: Comma-separated list (e.g., `"Account,Property__c"`)
105
+ - `signal?`: Optional AbortSignal for cancellation
106
+
107
+ **Returns**: `ObjectInfoBatchResponse` containing metadata for all requested objects
108
+
109
+ **Example**:
110
+
111
+ ```typescript
112
+ const objectInfo = await getObjectInfoBatch("Account,Property__c");
113
+ // Returns: { objects: [{ apiName: 'Account', label: 'Accounts', ... }, ...] }
114
+ ```
115
+
116
+ **API Endpoint**: `GET /object-info/batch/{objectApiNames}`
117
+
118
+ ---
119
+
120
+ ### 2. `getObjectListInfo(objectApiName, listViewApiName, signal?)`
121
+
122
+ **Purpose**: Fetches column definitions for search results.
123
+
124
+ **When to Use**:
125
+
126
+ - When loading data for an object to determine which columns are available
127
+ - Provides column metadata (field API names, labels, sortability)
128
+ - Used to understand the structure of search results
129
+
130
+ **Parameters**:
131
+
132
+ - `objectApiName`: The object API name (e.g., `"Account"`)
133
+ - `listViewApiName`: Always `"__SearchResult"` for search results
134
+ - `signal?`: Optional AbortSignal for cancellation
135
+
136
+ **Returns**: Array of `Column` objects with field information
137
+
138
+ **Example**:
139
+
140
+ ```typescript
141
+ const columns = await getObjectListInfo("Account", "__SearchResult");
142
+ // Returns: [{ fieldApiName: 'Name', label: 'Account Name', sortable: true, ... }, ...]
143
+ ```
144
+
145
+ **API Endpoint**: `GET /list-info/{objectApiName}/{listViewApiName}`
146
+
147
+ ---
148
+
149
+ ### 3. `getObjectListFilters(objectApiName, signal?)`
150
+
151
+ **Purpose**: Fetches filter definitions for a specific object.
152
+
153
+ **When to Use**:
154
+
155
+ - When loading data for an object to determine available filters
156
+ - Provides filter metadata (field types, operators, default values, affordances)
157
+ - Used to understand what filters can be applied to search results
158
+
159
+ **Parameters**:
160
+
161
+ - `objectApiName`: The object API name (e.g., `"Account"`)
162
+ - `signal?`: Optional AbortSignal for cancellation
163
+
164
+ **Returns**: Array of `Filter` objects with filter definitions
165
+
166
+ **Example**:
167
+
168
+ ```typescript
169
+ const filters = await getObjectListFilters("Account");
170
+ // Returns: [{ targetFieldPath: 'Name', operator: 'contains', ... }, ...]
171
+ ```
172
+
173
+ **API Endpoint**: `GET /search-info/{objectApiName}/filters`
174
+
175
+ ---
176
+
177
+ ### 4. `getPicklistValues(objectApiName, fieldName, recordTypeId?, signal?)`
178
+
179
+ **Purpose**: Fetches available picklist values for a specific field.
180
+
181
+ **When to Use**:
182
+
183
+ - When a filter has `affordance: 'select'` (indicating a picklist field)
184
+ - Needed to get the list of valid values for a picklist filter
185
+ - Called for each picklist field in the filters array returned by `getObjectListFilters`
186
+
187
+ **Parameters**:
188
+
189
+ - `objectApiName`: The object API name (e.g., `"Account"`)
190
+ - `fieldName`: The field API name (e.g., `"Type"`)
191
+ - `recordTypeId?`: Optional record type ID (defaults to master record type)
192
+ - `signal?`: Optional AbortSignal for cancellation
193
+
194
+ **Returns**: Array of `PicklistValue` objects with label and value
195
+
196
+ **Example**:
197
+
198
+ ```typescript
199
+ const picklistValues = await getPicklistValues("Account", "Type");
200
+ // Returns: [{ label: 'Customer', value: 'Customer' }, { label: 'Partner', value: 'Partner' }, ...]
201
+ ```
202
+
203
+ **API Endpoint**: `GET /object-info/{objectApiName}/picklist-values/{recordTypeId}/{fieldName}`
204
+
205
+ ---
206
+
207
+ ### 5. `searchResults(query, objectApiName, params?, signal?)`
208
+
209
+ **Purpose**: Performs keyword search on a specific object and returns matching records.
210
+
211
+ **When to Use**:
212
+
213
+ - When executing a search query for a specific object
214
+ - When filters are applied (query should include filter criteria)
215
+ - When pagination changes (use `pageToken` parameter)
216
+ - When page size changes (use `pageSize` parameter)
217
+ - Returns the actual search results with field values
218
+
219
+ **Parameters**:
220
+
221
+ - `query`: The search query string
222
+ - `objectApiName`: The object API name to search (e.g., `"Account"`)
223
+ - `params?`: Optional pagination parameters (`pageSize`, `pageToken`)
224
+ - `signal?`: Optional AbortSignal for cancellation (critical for race condition prevention)
225
+
226
+ **Returns**: Array of `SearchResultRecord` objects with field values
227
+
228
+ **Example**:
229
+
230
+ ```typescript
231
+ const results = await searchResults("Acme", "Account", { pageSize: 25, pageToken: "0" });
232
+ // Returns: [{ id: '001...', fields: { Name: 'Acme Corp', ... }, ... }, ...]
233
+ ```
234
+
235
+ **API Endpoint**: `POST /search/results/keyword?q={query}&objectApiName={objectApiName}`
236
+
237
+ **Request Body**:
238
+
239
+ ```json
240
+ {
241
+ "pageSize": 25,
242
+ "pageToken": "0"
243
+ }
244
+ ```
245
+
246
+ ---
247
+
248
+ ## API Consumption Flow
249
+
250
+ ### Initialization
251
+
252
+ 1. **`getObjectInfoBatch`** is called with all object names from `OBJECT_API_NAMES`
253
+ - Returns object metadata (labels, plural labels, etc.)
254
+ - Use this to understand which objects are available for search
255
+
256
+ 2. **For each object** (can be done in parallel):
257
+ - **`getObjectListInfo`** - Gets column definitions for search results
258
+ - **`getObjectListFilters`** - Gets filter definitions
259
+ - **`searchResults`** - Gets initial search results (if query is provided)
260
+
261
+ 3. **For each picklist filter** (can be done in parallel):
262
+ - **`getPicklistValues`** - Gets available values for picklist fields
263
+
264
+ ### Search Execution
265
+
266
+ 1. **Initial Search**:
267
+ - Call **`searchResults`** with the search query and object API name
268
+ - Include pagination parameters (`pageSize`, `pageToken`)
269
+
270
+ 2. **Filter Application**:
271
+ - Apply filters to the search query
272
+ - Call **`searchResults`** with updated query/filters
273
+ - Reset pagination to page 1 (use `pageToken: '0'`)
274
+
275
+ 3. **Pagination**:
276
+ - Use `pageToken` from previous response for next page
277
+ - Call **`searchResults`** with new `pageToken`
278
+
279
+ 4. **Page Size Change**:
280
+ - Call **`searchResults`** with new `pageSize`
281
+ - Reset to page 1 (use `pageToken: '0'`)
282
+
283
+ ### Race Condition Prevention
284
+
285
+ All API calls support `AbortSignal` to prevent stale data:
286
+
287
+ - When a new search is triggered, cancel the previous request using `AbortSignal`
288
+ - When switching between objects, cancel previous object requests
289
+ - When component unmounts, cancel all pending requests
290
+
291
+ This ensures applications always work with the most recent data and avoid race conditions.
292
+
293
+ ## Setup
294
+
295
+ ### Prerequisites
296
+
297
+ 1. **Salesforce CLI (`sf`)** - Must be installed and authenticated to a Salesforce org
298
+ 2. **@salesforce/webapps packages** - Required for API proxy functionality (see linking instructions below)
299
+
300
+ ### Linking @salesforce/webapps (Required until packages are published)
301
+
302
+ Since `@salesforce/webapps` and `@salesforce/vite-plugin-webapps` are not yet published to npm, you need to link them locally:
303
+
304
+ ```bash
305
+ # Step 1: In the webapps repo - register packages with npm's link registry
306
+ cd /path/to/webapps/packages/webapps && npm link
307
+ cd /path/to/webapps/packages/vite-plugin-webapps && npm link
308
+
309
+ # Step 2: In this repo - link the packages
310
+ cd /path/to/webapps-templates/packages/feature/feature-react-global-search
311
+ npm link @salesforce/webapps
312
+ npm link @salesforce/vite-plugin-webapps
313
+ ```
314
+
315
+ ### Building and Running
316
+
317
+ ```bash
318
+ # Build the feature (applies patches from template to dist)
319
+ npm run build
320
+
321
+ # Start the development server
322
+ npm run dev
323
+ ```
324
+
325
+ The `npm run build` command will:
326
+
327
+ 1. Apply feature patches to create the dist directory
328
+ 2. Remove the package-lock.json (to avoid resolution conflicts)
329
+ 3. Re-link the @salesforce/webapps packages
330
+
331
+ ## Configuration
332
+
333
+ ### Setting Searchable Objects
334
+
335
+ Configure which Salesforce objects to search by editing `src/constants.ts`:
336
+
337
+ ```typescript
338
+ export const OBJECT_API_NAMES = ["Account", "Property__c"] as const;
339
+ ```
340
+
341
+ This configuration determines which objects will be included when calling `getObjectInfoBatch` and when executing searches.
342
+
343
+ ## Usage
344
+
345
+ ### Using the API Service
346
+
347
+ Import the service and use the available methods:
348
+
349
+ ```typescript
350
+ import { objectInfoService } from "@/api/objectInfoService";
351
+
352
+ // Get object metadata
353
+ const objectInfo = await objectInfoService.getObjectInfoBatch("Account,Property__c");
354
+
355
+ // Get column definitions
356
+ const columns = await objectInfoService.getObjectListInfo("Account", "__SearchResult");
357
+
358
+ // Get filter definitions
359
+ const filters = await objectInfoService.getObjectListFilters("Account");
360
+
361
+ // Get picklist values
362
+ const picklistValues = await objectInfoService.getPicklistValues("Account", "Type");
363
+
364
+ // Execute search
365
+ const results = await objectInfoService.searchResults("Acme", "Account", {
366
+ pageSize: 25,
367
+ pageToken: "0",
368
+ });
369
+ ```
370
+
371
+ ### Using the Custom Hook
372
+
373
+ The `useObjectSearchData` hook manages API calls and data fetching:
374
+
375
+ ```typescript
376
+ import { useObjectSearchData } from "@/hooks/useObjectSearchData";
377
+
378
+ const { tabs, loading, error, tabData, filtersData } = useObjectSearchData({
379
+ filteredObjectApiNames: ["Account", "Property__c"],
380
+ activeTab: "Account",
381
+ searchQuery: "Acme",
382
+ searchPageSize: 25,
383
+ searchPageToken: "0",
384
+ });
385
+ ```
386
+
387
+ ## Type Safety
388
+
389
+ All API responses are validated using Zod schemas, ensuring:
390
+
391
+ - Type safety at compile time
392
+ - Runtime validation of API responses
393
+ - Better error messages when API contracts change
394
+ - Protection against malformed data
395
+
396
+ Type definitions are derived from Zod schemas using `z.infer`, ensuring consistency between validation and TypeScript types.
397
+
398
+ ## Error Handling
399
+
400
+ The `fetchAndValidate` utility provides consistent error handling:
401
+
402
+ - Network errors are caught and re-thrown with context
403
+ - HTTP errors (non-200 status) are caught and reported
404
+ - Zod validation errors are caught and reported (without logging sensitive details)
405
+ - AbortErrors are properly propagated (not treated as regular errors)
406
+
407
+ All errors are handled gracefully in the UI, preventing page refreshes and providing user-friendly error messages.
408
+
409
+ ## Dependencies
410
+
411
+ This feature depends on:
412
+
413
+ - **feature-shadcn** - For all UI components (Button, Input, Select, Table, Pagination, etc.)
414
+ - **@salesforce/webapps** - For API client and Salesforce integration
415
+ - **zod** - For runtime validation and type inference
@@ -0,0 +1,81 @@
1
+ # AI Rule: Build Validation
2
+
3
+ Build validation for successful deployments with minimal friction.
4
+
5
+ ## Targets
6
+ - `force-app/main/default/webapplications/*/**/*`
7
+ - `**/*.{js,ts,jsx,tsx}`
8
+
9
+ ## MANDATORY: Build Success
10
+
11
+ **Before completing any coding session:**
12
+ ```bash
13
+ npm run build # MUST succeed with no errors
14
+ ```
15
+
16
+ ## Quick Quality Checks
17
+ ```bash
18
+ npm run format:check # Auto-fixable
19
+ npm run lint # Most issues auto-fixable
20
+ tsc -b # Catches major issues
21
+ ```
22
+
23
+ ## Requirements
24
+
25
+ **Must Pass:**
26
+ - `npm run build` completes successfully
27
+ - No TypeScript compilation errors
28
+ - No critical ESLint errors
29
+
30
+ **Can Be Warnings:**
31
+ - ESLint warnings
32
+ - Prettier formatting issues
33
+ - Minor TypeScript warnings
34
+
35
+ ## Auto-Fix Commands
36
+ ```bash
37
+ npm run fix-all # Fix formatting + linting
38
+ npm run format # Fix Prettier issues
39
+ npm run lint:fix # Fix ESLint issues
40
+ ```
41
+
42
+ ## Workflow
43
+
44
+ **During Development:**
45
+ 1. Write code with AI assistance
46
+ 2. Save frequently (auto-format on save)
47
+ 3. Check periodically: `npm run lint` (optional)
48
+
49
+ **Before Completion:**
50
+ 1. Run `npm run build`
51
+ 2. If fails: Run `npm run fix-all`, fix TypeScript errors, retry build
52
+
53
+ ## Error Priority
54
+
55
+ **Fix Immediately:**
56
+ - TypeScript compilation errors
57
+ - Import/export errors
58
+ - Syntax errors
59
+
60
+ **Fix When Convenient:**
61
+ - ESLint warnings
62
+ - Prettier formatting
63
+ - Unused variables
64
+
65
+ ## Hard Requirements
66
+ - Build must complete without errors
67
+ - No broken imports
68
+ - Basic TypeScript type safety
69
+
70
+ ## Key Commands
71
+ ```bash
72
+ npm run dev # Start development
73
+ npm run build # Check deployment readiness
74
+ npm run fix-all # Fix common issues
75
+ ```
76
+
77
+ ## Troubleshooting Import Errors
78
+ ```bash
79
+ npm install # Check missing dependencies
80
+ # Verify file exists, case sensitivity, export/import match
81
+ ```