@salesforce/templates 66.13.5 → 66.13.7

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 (281) hide show
  1. package/lib/templates/project/angularextapp/CHANGELOG.md +258 -0
  2. package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/angular.json +1 -1
  3. package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/eslint-plugin-angular-graphql.js +148 -0
  4. package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/eslint.config.js +9 -1
  5. package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package-lock.json +680 -408
  6. package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package.json +2 -2
  7. package/lib/templates/project/angularextapp/package.json +1 -1
  8. package/lib/templates/project/angularextapp/scripts/org-setup-config-schema.mjs +17 -0
  9. package/lib/templates/project/angularextapp/scripts/org-setup-utils.mjs +33 -3
  10. package/lib/templates/project/angularextapp/scripts/org-setup.mjs +535 -3
  11. package/lib/templates/project/angularintapp/CHANGELOG.md +266 -0
  12. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/angular.json +1 -1
  13. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/eslint-plugin-angular-graphql.js +148 -0
  14. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/eslint.config.js +9 -1
  15. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package-lock.json +690 -418
  16. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package.json +2 -2
  17. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/features/agentforce/agentforce-embed.service.ts +6 -1
  18. package/lib/templates/project/angularintapp/package.json +1 -1
  19. package/lib/templates/project/angularintapp/scripts/org-setup-config-schema.mjs +17 -0
  20. package/lib/templates/project/angularintapp/scripts/org-setup-utils.mjs +33 -3
  21. package/lib/templates/project/angularintapp/scripts/org-setup.mjs +535 -3
  22. package/lib/templates/project/reactexternalapp/CHANGELOG.md +1409 -0
  23. package/lib/templates/project/reactexternalapp/PRD.md +38 -0
  24. package/lib/templates/project/reactexternalapp/README.md +14 -10
  25. package/lib/templates/project/reactexternalapp/_p_/_m_/_ps_/reactexternalapp_Guest_User_Api_Access.permissionset-meta.xml +25 -0
  26. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package-lock.json +953 -714
  27. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package.json +9 -7
  28. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/scripts/get-graphql-schema.mjs +8 -5
  29. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/LanguageSwitcher.tsx +116 -0
  30. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/__examples__/language-switcher-example.tsx +36 -0
  31. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/__examples__/vite-config-site-example.ts +44 -0
  32. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/buildLanguageUrl.ts +158 -0
  33. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/index.ts +28 -0
  34. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_ls_/languages.ts +46 -0
  35. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/components/SocialLogin.tsx +141 -0
  36. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Login.tsx +2 -0
  37. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +246 -0
  38. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/apiUtils.ts +56 -0
  39. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/orgApiVersionService.ts +37 -0
  40. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +116 -0
  41. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/channelResolver.ts +40 -0
  42. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +97 -0
  43. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeSessionCache.ts +134 -0
  44. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +38 -0
  45. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/hooks/useSearchableContentTypes.ts +128 -0
  46. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +54 -0
  47. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/parseResponse.ts +65 -0
  48. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +15 -0
  49. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/types.ts +66 -0
  50. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/registry.ts +38 -0
  51. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/index.ts +19 -0
  52. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/parseResponse.ts +56 -0
  53. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/queryFragment.ts +141 -0
  54. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +101 -0
  55. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/distinctValuesService.ts +84 -0
  56. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/searchService.ts +136 -0
  57. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/GlobalSearchBox.tsx +98 -0
  58. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +294 -0
  59. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/Search.tsx +203 -0
  60. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +88 -0
  61. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +187 -0
  62. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/PaginationControls.tsx +185 -0
  63. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/ScopeSelector.tsx +107 -0
  64. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SearchBar.tsx +55 -0
  65. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SortControl.tsx +62 -0
  66. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/ActiveFilters.tsx +61 -0
  67. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +125 -0
  68. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_/components → search/components/filters}/FilterContext.tsx +7 -20
  69. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/BooleanFilter.tsx +50 -0
  70. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/DateRangeFilter.tsx +160 -0
  71. package/lib/templates/project/{reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters → reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs}/FilterFieldWrapper.tsx +11 -6
  72. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/MultiSelectFilter.tsx +89 -0
  73. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/NumericRangeFilter.tsx +108 -0
  74. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/SelectFilter.tsx +46 -0
  75. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/TextFilter.tsx +52 -0
  76. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/CmsResultRow.tsx +101 -0
  77. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/DefaultResultRow.tsx +109 -0
  78. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/resolveResultRenderer.ts +49 -0
  79. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/config.json +88 -0
  80. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/constants.ts +8 -0
  81. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_ → search}/hooks/useAsyncData.ts +3 -10
  82. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useDistinctValues.ts +59 -0
  83. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +966 -0
  84. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/index.ts +115 -0
  85. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/loadConfig.ts +14 -0
  86. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/queryBuilder.ts +100 -0
  87. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/types.ts +376 -0
  88. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/debounce.ts +17 -0
  89. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/fieldUtils.ts +14 -0
  90. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +285 -0
  91. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/sortUtils.ts +34 -0
  92. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/graphqlClient.ts +24 -8
  93. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/appLayout.tsx +7 -0
  94. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/CustomerWebClientChat.tsx +74 -0
  95. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/components → components}/ObjectBreadcrumb.tsx +7 -2
  96. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ui/button.tsx +1 -1
  97. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ui/datePicker.tsx +2 -2
  98. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ui/table.tsx +9 -2
  99. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/index.ts +8 -0
  100. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +53 -18
  101. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +3 -27
  102. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/TestChatPage.tsx +26 -0
  103. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +21 -8
  104. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/types/chat.ts +36 -0
  105. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/types/globals.d.ts +23 -0
  106. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/utils/fieldUtils.ts → utils/accountFields.ts} +9 -0
  107. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/tsconfig.json +2 -2
  108. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -0
  109. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls +133 -0
  110. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls-meta.xml +5 -0
  111. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls +101 -0
  112. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls-meta.xml +5 -0
  113. package/lib/templates/project/reactexternalapp/_p_/_m_/package.xml +4 -0
  114. package/lib/templates/project/reactexternalapp/package.json +8 -2
  115. package/lib/templates/project/reactexternalapp/scripts/org-setup-config-schema.mjs +120 -0
  116. package/lib/templates/project/reactexternalapp/scripts/org-setup-dev.mjs +87 -0
  117. package/lib/templates/project/reactexternalapp/scripts/org-setup-utils.mjs +569 -0
  118. package/lib/templates/project/reactexternalapp/scripts/org-setup-xml.mjs +182 -0
  119. package/lib/templates/project/reactexternalapp/scripts/org-setup.config.json +6 -2
  120. package/lib/templates/project/reactexternalapp/scripts/org-setup.mjs +1509 -328
  121. package/lib/templates/project/reactexternalapp/scripts/validate-org-setup-config.mjs +38 -0
  122. package/lib/templates/project/reactinternalapp/CHANGELOG.md +1223 -0
  123. package/lib/templates/project/reactinternalapp/PRD.md +35 -0
  124. package/lib/templates/project/reactinternalapp/README.md +14 -10
  125. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package-lock.json +813 -538
  126. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package.json +10 -9
  127. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +246 -0
  128. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/apiUtils.ts +56 -0
  129. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/orgApiVersionService.ts +37 -0
  130. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +116 -0
  131. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/channelResolver.ts +40 -0
  132. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +97 -0
  133. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeSessionCache.ts +134 -0
  134. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +38 -0
  135. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/hooks/useSearchableContentTypes.ts +128 -0
  136. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +54 -0
  137. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/parseResponse.ts +65 -0
  138. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +15 -0
  139. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/types.ts +66 -0
  140. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/registry.ts +38 -0
  141. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/index.ts +19 -0
  142. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/parseResponse.ts +56 -0
  143. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/sobject/queryFragment.ts +141 -0
  144. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +101 -0
  145. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/distinctValuesService.ts +84 -0
  146. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/api/searchService.ts +136 -0
  147. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/GlobalSearchBox.tsx +98 -0
  148. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +294 -0
  149. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/Search.tsx +203 -0
  150. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +88 -0
  151. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +187 -0
  152. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/PaginationControls.tsx +185 -0
  153. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/ScopeSelector.tsx +107 -0
  154. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SearchBar.tsx +55 -0
  155. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/controls/SortControl.tsx +62 -0
  156. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/ActiveFilters.tsx +61 -0
  157. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +125 -0
  158. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_/components → search/components/filters}/FilterContext.tsx +7 -20
  159. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/BooleanFilter.tsx +50 -0
  160. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/DateRangeFilter.tsx +160 -0
  161. package/lib/templates/project/{reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters → reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs}/FilterFieldWrapper.tsx +11 -6
  162. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/MultiSelectFilter.tsx +89 -0
  163. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/NumericRangeFilter.tsx +108 -0
  164. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/SelectFilter.tsx +46 -0
  165. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/inputs/TextFilter.tsx +52 -0
  166. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/CmsResultRow.tsx +101 -0
  167. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/DefaultResultRow.tsx +109 -0
  168. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/results/resolveResultRenderer.ts +49 -0
  169. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/config.json +88 -0
  170. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/constants.ts +8 -0
  171. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/{_os_ → search}/hooks/useAsyncData.ts +3 -10
  172. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useDistinctValues.ts +59 -0
  173. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +966 -0
  174. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/index.ts +115 -0
  175. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/loadConfig.ts +14 -0
  176. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/queryBuilder.ts +100 -0
  177. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/types.ts +376 -0
  178. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/debounce.ts +17 -0
  179. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/fieldUtils.ts +14 -0
  180. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +285 -0
  181. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/sortUtils.ts +34 -0
  182. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/AgentforceConversationClient.tsx +16 -132
  183. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/components → components}/ObjectBreadcrumb.tsx +7 -2
  184. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/button.tsx +1 -1
  185. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/datePicker.tsx +2 -2
  186. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ui/table.tsx +9 -2
  187. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +49 -16
  188. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +3 -27
  189. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +12 -5
  190. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/{_f_/_os_/utils/fieldUtils.ts → utils/accountFields.ts} +9 -0
  191. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/tsconfig.json +2 -2
  192. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -0
  193. package/lib/templates/project/reactinternalapp/package.json +4 -2
  194. package/lib/templates/project/reactinternalapp/scripts/org-setup-config-schema.mjs +24 -0
  195. package/lib/templates/project/reactinternalapp/scripts/org-setup-dev.mjs +87 -0
  196. package/lib/templates/project/reactinternalapp/scripts/org-setup-utils.mjs +569 -0
  197. package/lib/templates/project/reactinternalapp/scripts/org-setup-xml.mjs +182 -0
  198. package/lib/templates/project/reactinternalapp/scripts/org-setup.mjs +1162 -214
  199. package/lib/templates/uiBundles/angularbasic/angular.json +1 -1
  200. package/lib/templates/uiBundles/angularbasic/eslint-plugin-angular-graphql.js +148 -0
  201. package/lib/templates/uiBundles/angularbasic/eslint.config.js +9 -1
  202. package/lib/templates/uiBundles/angularbasic/package-lock.json +680 -408
  203. package/lib/templates/uiBundles/angularbasic/package.json +2 -2
  204. package/lib/templates/uiBundles/reactbasic/package-lock.json +738 -440
  205. package/lib/utils/template-placeholders.js +14 -0
  206. package/lib/utils/template-placeholders.js.map +1 -1
  207. package/lib/utils/uiBundleTemplateUtils.d.ts +5 -1
  208. package/lib/utils/uiBundleTemplateUtils.js +7 -1
  209. package/lib/utils/uiBundleTemplateUtils.js.map +1 -1
  210. package/package.json +7 -7
  211. package/lib/templates/project/reactexternalapp/AGENT.md +0 -252
  212. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/accountSearchService.ts +0 -46
  213. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountIndustries.graphql +0 -19
  214. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountTypes.graphql +0 -19
  215. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/getAccountDetail.graphql +0 -121
  216. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/searchAccounts.graphql +0 -51
  217. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountObjectDetailPage.tsx +0 -355
  218. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +0 -304
  219. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/Home.tsx +0 -34
  220. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/api/objectSearchService.ts +0 -82
  221. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/ActiveFilters.tsx +0 -89
  222. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/PaginationControls.tsx +0 -109
  223. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SearchBar.tsx +0 -41
  224. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SortControl.tsx +0 -143
  225. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +0 -78
  226. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +0 -128
  227. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +0 -70
  228. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +0 -97
  229. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +0 -167
  230. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +0 -52
  231. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +0 -97
  232. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +0 -93
  233. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +0 -34
  234. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +0 -254
  235. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +0 -25
  236. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +0 -404
  237. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/sortUtils.ts +0 -38
  238. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +0 -46
  239. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +0 -19
  240. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +0 -19
  241. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +0 -51
  242. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/graphql-operations-types.ts +0 -11260
  243. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +0 -297
  244. package/lib/templates/project/reactexternalapp/scripts/prepare-import-unique-fields.js +0 -122
  245. package/lib/templates/project/reactinternalapp/AGENT.md +0 -252
  246. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/accountSearchService.ts +0 -46
  247. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountIndustries.graphql +0 -19
  248. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/distinctAccountTypes.graphql +0 -19
  249. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/getAccountDetail.graphql +0 -121
  250. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/api/query/searchAccounts.graphql +0 -51
  251. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountObjectDetailPage.tsx +0 -355
  252. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +0 -304
  253. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/Home.tsx +0 -34
  254. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/api/objectSearchService.ts +0 -82
  255. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/ActiveFilters.tsx +0 -89
  256. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/PaginationControls.tsx +0 -109
  257. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SearchBar.tsx +0 -41
  258. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/SortControl.tsx +0 -143
  259. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +0 -78
  260. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +0 -128
  261. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +0 -70
  262. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +0 -97
  263. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +0 -167
  264. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +0 -52
  265. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +0 -97
  266. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +0 -93
  267. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +0 -34
  268. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +0 -254
  269. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +0 -25
  270. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +0 -404
  271. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/sortUtils.ts +0 -38
  272. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +0 -46
  273. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +0 -19
  274. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +0 -19
  275. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +0 -51
  276. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/graphql-operations-types.ts +0 -11260
  277. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +0 -297
  278. package/lib/templates/project/reactinternalapp/scripts/prepare-import-unique-fields.js +0 -122
  279. /package/lib/templates/project/angularextapp/_p_/_m_/{permissionsets → _ps_}/angularextapp_Guest_User_Api_Access.permissionset-meta.xml +0 -0
  280. /package/lib/templates/project/angularintapp/_p_/_m_/{permissionsets → _ps_}/angularintapp_Access.permissionset-meta.xml +0 -0
  281. /package/lib/templates/project/reactinternalapp/_p_/_m_/{permissionsets → _ps_}/reactinternalapp_Access.permissionset-meta.xml +0 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ import CustomerWebClientChat from "../components/CustomerWebClientChat";
8
+
9
+ export default function TestChatPage() {
10
+ return (
11
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
12
+ <div className="text-center">
13
+ <h1 className="text-4xl font-bold text-gray-900 mb-4">Chat</h1>
14
+ <p className="text-lg text-gray-600 mb-8">
15
+ Welcome to your Customer Web Client chat application.
16
+ </p>
17
+ </div>
18
+ <CustomerWebClientChat
19
+ orgId="<ORG_ID_15_OR_18_CHAR_00D...>"
20
+ deploymentName="<EMBEDDED_SERVICE_DEPLOYMENT_NAME>"
21
+ siteURL="<SITE_URL>"
22
+ scrt2URL="<SCRT2_URL>"
23
+ />
24
+ </div>
25
+ );
26
+ }
@@ -9,9 +9,10 @@ import Profile from "./features/authentication/pages/Profile";
9
9
  import ChangePassword from "./features/authentication/pages/ChangePassword";
10
10
  import PrivateRoute from "./features/authentication/layouts/privateRouteLayout";
11
11
  import { ROUTES } from "./features/authentication/authenticationConfig";
12
- import AccountSearch from "./pages/AccountSearch";
13
- import AccountObjectDetail from "./pages/AccountObjectDetailPage";
12
+ import { Search as GlobalSearch, config } from "./features/search";
13
+ import TestChatPage from "./pages/TestChatPage";
14
14
  import AuthAppLayout from "./features/authentication/layouts/AuthAppLayout";
15
+ import AccountObjectDetail from "./pages/AccountObjectDetailPage";
15
16
 
16
17
  export const routes: RouteObject[] = [
17
18
  {
@@ -23,10 +24,6 @@ export const routes: RouteObject[] = [
23
24
  element: <Home />,
24
25
  handle: { showInNavigation: true, label: "Home" }
25
26
  },
26
- {
27
- path: '*',
28
- element: <NotFound />
29
- },
30
27
  {
31
28
  path: ROUTES.LOGIN.PATH,
32
29
  element: <Login />,
@@ -62,13 +59,29 @@ export const routes: RouteObject[] = [
62
59
  }
63
60
  ]
64
61
  },
62
+ {
63
+ path: "search",
64
+ element: (
65
+ <GlobalSearch
66
+ config={config}
67
+ title="Search"
68
+ searchPlaceholder="Search accounts, contacts, opportunities, and content..."
69
+ />
70
+ ),
71
+ handle: { showInNavigation: true, label: "Search" }
72
+ },
73
+ {
74
+ path: "test-chat",
75
+ element: <TestChatPage />,
76
+ handle: { showInNavigation: true, label: "Test Chat" }
77
+ },
65
78
  {
66
79
  path: "accounts/:recordId",
67
80
  element: <AccountObjectDetail />
68
81
  },
69
82
  {
70
- path: "accounts",
71
- element: <AccountSearch />
83
+ path: '*',
84
+ element: <NotFound />
72
85
  }
73
86
  ]
74
87
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ /** Shape of the Embedded Messaging bootstrap global injected by the site's bootstrap.js. */
8
+ export interface WindowWithCwcProperties extends Window {
9
+ embeddedservice_bootstrap?: {
10
+ settings: {
11
+ language: string;
12
+ devMode?: boolean;
13
+ };
14
+ init: (
15
+ orgId: string,
16
+ deploymentName: string,
17
+ siteURL: string,
18
+ options: { scrt2URL: string },
19
+ ) => void;
20
+ };
21
+ }
22
+
23
+ export interface CustomerWebClientChatProps {
24
+ /** The organization id (15- or 18-char Salesforce id starting with `00D`). */
25
+ orgId: string;
26
+ /** The Embedded Service deployment / channel name the agent is connected to. */
27
+ deploymentName: string;
28
+ /** The ESW site URL. Usually contains `ESW` and the deployment name. */
29
+ siteURL: string;
30
+ /** The SCRT2 (Service Cloud Real-Time) chat service URL. Usually contains `scrt`. */
31
+ scrt2URL: string;
32
+ /** Optional chat language. Defaults to `"en"`. */
33
+ language?: string;
34
+ /** Optional. Enables Embedded Messaging dev mode. Defaults to `false`. */
35
+ devMode?: boolean;
36
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Copyright (c) 2026, Salesforce, Inc.,
3
+ * All rights reserved.
4
+ * For full license text, see the LICENSE.txt file
5
+ */
6
+
7
+ /**
8
+ * Ambient augmentation of the runtime environment on {@link globalThis.SFDC_ENV}.
9
+ *
10
+ * The platform's `SfdcEnv` (see `@salesforce/platform-sdk`) does not yet declare
11
+ * a `language` field. The language switcher reads the active language from it, so
12
+ * we augment the interface with an optional `language` here. Because declared
13
+ * interfaces merge, this only ADDS `language` — it does not redeclare `basePath`
14
+ * or the other platform-owned fields.
15
+ *
16
+ * Expected value: the page locale in hyphenated form, e.g. `"en-US"` — the
17
+ * platform converts the underscore locale code (`en_US`) to dashes before
18
+ * injecting it into `SFDC_ENV`.
19
+ */
20
+ interface SfdcEnv {
21
+ /** Current page language in hyphenated form, e.g. "en-US". */
22
+ language?: string;
23
+ }
@@ -1,3 +1,10 @@
1
+ /**
2
+ * Field helpers for reading uiapi GraphQL response nodes on the Account
3
+ * detail page. Previously imported from feature-react-object-search; inlined
4
+ * here so the app no longer depends on that feature.
5
+ */
6
+
7
+ /** Picks the user-facing string for a `{ value, displayValue }` field. */
1
8
  export function fieldValue(
2
9
  field: { displayValue?: string | null; value?: unknown } | null | undefined,
3
10
  ): string | null {
@@ -6,6 +13,7 @@ export function fieldValue(
6
13
  return null;
7
14
  }
8
15
 
16
+ /** Builds the display lines for a Salesforce compound address, or null if empty. */
9
17
  export function getAddressFieldLines(address: {
10
18
  street?: string | null;
11
19
  city?: string | null;
@@ -20,6 +28,7 @@ export function getAddressFieldLines(address: {
20
28
  return lines;
21
29
  }
22
30
 
31
+ /** Formats an ISO datetime string with `toLocaleString`, or null if absent. */
23
32
  export function formatDateTimeField(
24
33
  value?: string | null,
25
34
  ...args: Parameters<Date["toLocaleString"]>
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "ES2020",
3
+ "target": "ES2022",
4
4
  "useDefineForClassFields": true,
5
- "lib": ["ES2020", "DOM", "DOM.Iterable"],
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
6
  "module": "ESNext",
7
7
  "skipLibCheck": true,
8
8
 
@@ -0,0 +1 @@
1
+ {"root":["./src/app.tsx","./src/appLayout.tsx","./src/index.ts","./src/navigationMenu.tsx","./src/router-utils.tsx","./src/routes.tsx","./src/api/graphqlClient.ts","./src/components/CustomerWebClientChat.tsx","./src/components/ObjectBreadcrumb.tsx","./src/components/alerts/status-alert.tsx","./src/components/layouts/card-layout.tsx","./src/components/ui/alert.tsx","./src/components/ui/avatar.tsx","./src/components/ui/badge.tsx","./src/components/ui/breadcrumb.tsx","./src/components/ui/button.tsx","./src/components/ui/calendar.tsx","./src/components/ui/card.tsx","./src/components/ui/checkbox.tsx","./src/components/ui/collapsible.tsx","./src/components/ui/datePicker.tsx","./src/components/ui/dialog.tsx","./src/components/ui/dropdown-menu.tsx","./src/components/ui/field.tsx","./src/components/ui/index.ts","./src/components/ui/input.tsx","./src/components/ui/label.tsx","./src/components/ui/pagination.tsx","./src/components/ui/popover.tsx","./src/components/ui/select.tsx","./src/components/ui/separator.tsx","./src/components/ui/skeleton.tsx","./src/components/ui/sonner.tsx","./src/components/ui/spinner.tsx","./src/components/ui/table.tsx","./src/components/ui/tabs.tsx","./src/features/authentication/authHelpers.ts","./src/features/authentication/authenticationConfig.ts","./src/features/authentication/api/userProfileApi.ts","./src/features/authentication/components/SocialLogin.tsx","./src/features/authentication/context/AuthContext.tsx","./src/features/authentication/footers/footer-link.tsx","./src/features/authentication/forms/auth-form.tsx","./src/features/authentication/forms/submit-button.tsx","./src/features/authentication/hooks/form.tsx","./src/features/authentication/hooks/useCountdownTimer.ts","./src/features/authentication/hooks/useRetryWithBackoff.ts","./src/features/authentication/layout/centered-page-layout.tsx","./src/features/authentication/layouts/AuthAppLayout.tsx","./src/features/authentication/layouts/privateRouteLayout.tsx","./src/features/authentication/menu/AuthMenu.tsx","./src/features/authentication/pages/ChangePassword.tsx","./src/features/authentication/pages/ForgotPassword.tsx","./src/features/authentication/pages/Login.tsx","./src/features/authentication/pages/Profile.tsx","./src/features/authentication/pages/Register.tsx","./src/features/authentication/pages/ResetPassword.tsx","./src/features/authentication/sessionTimeout/SessionTimeoutValidator.tsx","./src/features/authentication/sessionTimeout/sessionTimeService.ts","./src/features/authentication/sessionTimeout/sessionTimeoutConfig.ts","./src/features/authentication/utils/helpers.ts","./src/features/language-switcher/LanguageSwitcher.tsx","./src/features/language-switcher/buildLanguageUrl.ts","./src/features/language-switcher/index.ts","./src/features/language-switcher/languages.ts","./src/features/language-switcher/__examples__/language-switcher-example.tsx","./src/features/language-switcher/__examples__/vite-config-site-example.ts","./src/features/search/constants.ts","./src/features/search/index.ts","./src/features/search/loadConfig.ts","./src/features/search/queryBuilder.ts","./src/features/search/types.ts","./src/features/search/__tests__/queryBuilder.test.ts","./src/features/search/adapters/registry.ts","./src/features/search/adapters/types.ts","./src/features/search/adapters/cms/channelResolver.ts","./src/features/search/adapters/cms/cmsQueryFragment.ts","./src/features/search/adapters/cms/contentTypeSessionCache.ts","./src/features/search/adapters/cms/contentTypeUtils.ts","./src/features/search/adapters/cms/index.ts","./src/features/search/adapters/cms/parseResponse.ts","./src/features/search/adapters/cms/searchChannel.ts","./src/features/search/adapters/cms/types.ts","./src/features/search/adapters/cms/__tests__/channelResolver.test.ts","./src/features/search/adapters/cms/__tests__/cmsQueryFragment.test.ts","./src/features/search/adapters/cms/__tests__/contentTypeSessionCache.test.ts","./src/features/search/adapters/cms/__tests__/contentTypeUtils.test.ts","./src/features/search/adapters/cms/__tests__/orgApiVersionService.test.ts","./src/features/search/adapters/cms/__tests__/parseResponse.test.ts","./src/features/search/adapters/cms/__tests__/searchChannel.test.ts","./src/features/search/adapters/cms/__tests__/searchableContentTypesService.test.ts","./src/features/search/adapters/cms/api/apiUtils.ts","./src/features/search/adapters/cms/api/orgApiVersionService.ts","./src/features/search/adapters/cms/api/searchableContentTypesService.ts","./src/features/search/adapters/cms/hooks/useSearchableContentTypes.ts","./src/features/search/adapters/sobject/index.ts","./src/features/search/adapters/sobject/parseResponse.ts","./src/features/search/adapters/sobject/queryFragment.ts","./src/features/search/api/distinctValuesService.ts","./src/features/search/api/searchService.ts","./src/features/search/api/__tests__/searchService.test.ts","./src/features/search/components/GlobalSearchBox.tsx","./src/features/search/components/MergedSearchResults.tsx","./src/features/search/components/Search.tsx","./src/features/search/components/SearchResults.tsx","./src/features/search/components/SourceSection.tsx","./src/features/search/components/__tests__/Search.test.tsx","./src/features/search/components/controls/PaginationControls.tsx","./src/features/search/components/controls/ScopeSelector.tsx","./src/features/search/components/controls/SearchBar.tsx","./src/features/search/components/controls/SortControl.tsx","./src/features/search/components/filters/ActiveFilters.tsx","./src/features/search/components/filters/DefaultFilterPanel.tsx","./src/features/search/components/filters/FilterContext.tsx","./src/features/search/components/filters/inputs/BooleanFilter.tsx","./src/features/search/components/filters/inputs/DateRangeFilter.tsx","./src/features/search/components/filters/inputs/FilterFieldWrapper.tsx","./src/features/search/components/filters/inputs/MultiSelectFilter.tsx","./src/features/search/components/filters/inputs/NumericRangeFilter.tsx","./src/features/search/components/filters/inputs/SelectFilter.tsx","./src/features/search/components/filters/inputs/TextFilter.tsx","./src/features/search/components/results/CmsResultRow.tsx","./src/features/search/components/results/DefaultResultRow.tsx","./src/features/search/components/results/resolveResultRenderer.ts","./src/features/search/components/results/__tests__/CmsResultRow.test.tsx","./src/features/search/components/results/__tests__/resolveResultRenderer.test.ts","./src/features/search/hooks/useAsyncData.ts","./src/features/search/hooks/useDistinctValues.ts","./src/features/search/hooks/useSearch.ts","./src/features/search/utils/debounce.ts","./src/features/search/utils/fieldUtils.ts","./src/features/search/utils/filterUtils.ts","./src/features/search/utils/sortUtils.ts","./src/hooks/useAsyncData.ts","./src/lib/utils.ts","./src/pages/AccountObjectDetailPage.tsx","./src/pages/Home.tsx","./src/pages/NotFound.tsx","./src/pages/TestChatPage.tsx","./src/types/chat.ts","./src/types/globals.d.ts","./src/utils/accountFields.ts","./e2e/app.spec.ts","./vite-env.d.ts","./vitest-env.d.ts","./vitest.setup.ts","../../../../../../../../../sdk/platform-sdk/types/env.d.ts"],"version":"5.9.3"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * REST endpoint for Social Login configuration on React Experience Cloud sites.
3
+ *
4
+ * Endpoint: GET /services/apexrest/auth/social-login-config?startURL=/
5
+ *
6
+ * This replicates the behavior of the OOTB community_login/socialLogin LWC:
7
+ * - applauncher.SocialLoginController.getAuthProviders()
8
+ * - applauncher.SocialLoginController.getSamlProviders()
9
+ * - applauncher.SocialLoginController.getCommunityDomainSsoUrl()
10
+ * - applauncher.SocialLoginController.getSamlSsoUrl()
11
+ * - applauncher.SocialLoginController.handleIdp()
12
+ *
13
+ * The OOTB LWC does not render on React (Site Container) sites due to a platform
14
+ * restriction (isSiteContainer check in node-loginsettings.ftl).
15
+ * This endpoint enables a custom React component to achieve the same functionality.
16
+ *
17
+ * @see https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_class_Auth_AuthConfiguration.htm
18
+ */
19
+ @RestResource(urlMapping='/auth/social-login-config')
20
+ global with sharing class UIBundleSocialLoginConfig {
21
+
22
+ @HttpGet
23
+ global static SocialLoginConfigResponse getConfig() {
24
+ try {
25
+ String startUrl = RestContext.request.params.get('startURL');
26
+ if (String.isBlank(startUrl)) {
27
+ startUrl = '/';
28
+ }
29
+
30
+ // Ensure startURL includes the community path prefix so post-auth
31
+ // redirect lands on the correct community (not the org default).
32
+ String pathPrefix = Site.getPathPrefix();
33
+ if (String.isNotBlank(pathPrefix) && !startUrl.startsWith(pathPrefix)) {
34
+ startUrl = pathPrefix + startUrl;
35
+ }
36
+
37
+ String communityUrl = Site.getBaseUrl();
38
+ Auth.AuthConfiguration authConfig = new Auth.AuthConfiguration(communityUrl, startUrl);
39
+
40
+ List<AuthProviderInfo> authProviders = new List<AuthProviderInfo>();
41
+ List<SamlProviderInfo> samlProviders = new List<SamlProviderInfo>();
42
+ String autoRedirectUrl = null;
43
+
44
+ // Fetch OAuth Auth Providers (Google, Facebook, etc.)
45
+ List<AuthProvider> rawAuthProviders = authConfig.getAuthProviders();
46
+ for (AuthProvider ap : rawAuthProviders) {
47
+ String ssoUrl = Auth.AuthConfiguration.getAuthProviderSsoDomainUrl(
48
+ communityUrl, startUrl, ap.DeveloperName
49
+ );
50
+ authProviders.add(new AuthProviderInfo(
51
+ ap.DeveloperName,
52
+ ap.FriendlyName,
53
+ ap.IconUrl,
54
+ ssoUrl
55
+ ));
56
+ }
57
+
58
+ // Fetch SAML SSO Providers
59
+ List<SamlSsoConfig> rawSamlProviders = authConfig.getSamlProviders();
60
+ for (SamlSsoConfig saml : rawSamlProviders) {
61
+ String ssoUrl = Auth.AuthConfiguration.getSamlSsoUrl(
62
+ communityUrl, startUrl, saml.Id
63
+ );
64
+ samlProviders.add(new SamlProviderInfo(
65
+ saml.Id,
66
+ saml.MasterLabel,
67
+ ssoUrl
68
+ ));
69
+ }
70
+
71
+ // handleIdp behavior: auto-redirect if exactly one IDP and no username/password login
72
+ Integer totalProviders = rawAuthProviders.size() + rawSamlProviders.size();
73
+ if (totalProviders == 1 && !authConfig.getUsernamePasswordEnabled()) {
74
+ if (!authProviders.isEmpty()) {
75
+ autoRedirectUrl = authProviders[0].ssoUrl;
76
+ } else if (!samlProviders.isEmpty()) {
77
+ autoRedirectUrl = samlProviders[0].ssoUrl;
78
+ }
79
+ }
80
+
81
+ return new SocialLoginConfigResponse(authProviders, samlProviders, autoRedirectUrl);
82
+ } catch (Exception ex) {
83
+ System.debug(LoggingLevel.ERROR, 'UIBundleSocialLoginConfig error: ' + ex.getMessage());
84
+ return new SocialLoginConfigResponse(
85
+ new List<AuthProviderInfo>(),
86
+ new List<SamlProviderInfo>(),
87
+ null
88
+ );
89
+ }
90
+ }
91
+
92
+ global class SocialLoginConfigResponse {
93
+ global List<AuthProviderInfo> authProviders;
94
+ global List<SamlProviderInfo> samlProviders;
95
+ global String autoRedirectUrl;
96
+
97
+ global SocialLoginConfigResponse(
98
+ List<AuthProviderInfo> authProviders,
99
+ List<SamlProviderInfo> samlProviders,
100
+ String autoRedirectUrl
101
+ ) {
102
+ this.authProviders = authProviders;
103
+ this.samlProviders = samlProviders;
104
+ this.autoRedirectUrl = autoRedirectUrl;
105
+ }
106
+ }
107
+
108
+ global class AuthProviderInfo {
109
+ global String developerName;
110
+ global String friendlyName;
111
+ global String iconUrl;
112
+ global String ssoUrl;
113
+
114
+ global AuthProviderInfo(String developerName, String friendlyName, String iconUrl, String ssoUrl) {
115
+ this.developerName = developerName;
116
+ this.friendlyName = friendlyName;
117
+ this.iconUrl = iconUrl;
118
+ this.ssoUrl = ssoUrl;
119
+ }
120
+ }
121
+
122
+ global class SamlProviderInfo {
123
+ global String id;
124
+ global String masterLabel;
125
+ global String ssoUrl;
126
+
127
+ global SamlProviderInfo(String id, String masterLabel, String ssoUrl) {
128
+ this.id = id;
129
+ this.masterLabel = masterLabel;
130
+ this.ssoUrl = ssoUrl;
131
+ }
132
+ }
133
+ }
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <apiVersion>67.0</apiVersion>
4
+ <status>Active</status>
5
+ </ApexClass>
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Test class for UIBundleSocialLoginConfig REST endpoint.
3
+ *
4
+ * Auth.AuthConfiguration requires a valid community URL so these tests
5
+ * exercise the error-handling path and verify the response wrapper structure.
6
+ * Integration-level testing of actual Auth Provider/SAML discovery happens
7
+ * in the target org via the React component E2E flow.
8
+ */
9
+ @isTest
10
+ private class UIBundleSocialLoginConfig_Test {
11
+
12
+ /**
13
+ * Test that the endpoint returns an empty config when no community context
14
+ * is available (covers the catch block graceful fallback).
15
+ */
16
+ @isTest
17
+ static void testGetConfigNoSiteContext() {
18
+ RestRequest req = new RestRequest();
19
+ req.requestURI = '/services/apexrest/auth/social-login-config';
20
+ req.httpMethod = 'GET';
21
+ req.params.put('startURL', '/');
22
+ RestContext.request = req;
23
+ RestContext.response = new RestResponse();
24
+
25
+ Test.startTest();
26
+ UIBundleSocialLoginConfig.SocialLoginConfigResponse result =
27
+ UIBundleSocialLoginConfig.getConfig();
28
+ Test.stopTest();
29
+
30
+ // Should return empty lists (graceful fallback), not null
31
+ System.assertNotEquals(null, result, 'Response should not be null');
32
+ System.assertNotEquals(null, result.authProviders, 'authProviders list should not be null');
33
+ System.assertNotEquals(null, result.samlProviders, 'samlProviders list should not be null');
34
+ System.assertEquals(0, result.authProviders.size(), 'authProviders should be empty without community context');
35
+ System.assertEquals(0, result.samlProviders.size(), 'samlProviders should be empty without community context');
36
+ System.assertEquals(null, result.autoRedirectUrl, 'autoRedirectUrl should be null without providers');
37
+ }
38
+
39
+ /**
40
+ * Test that the endpoint handles a missing startURL parameter gracefully
41
+ * (defaults to "/").
42
+ */
43
+ @isTest
44
+ static void testGetConfigNoStartUrl() {
45
+ RestRequest req = new RestRequest();
46
+ req.requestURI = '/services/apexrest/auth/social-login-config';
47
+ req.httpMethod = 'GET';
48
+ // Intentionally not setting startURL param
49
+ RestContext.request = req;
50
+ RestContext.response = new RestResponse();
51
+
52
+ Test.startTest();
53
+ UIBundleSocialLoginConfig.SocialLoginConfigResponse result =
54
+ UIBundleSocialLoginConfig.getConfig();
55
+ Test.stopTest();
56
+
57
+ System.assertNotEquals(null, result, 'Response should not be null even without startURL');
58
+ System.assertNotEquals(null, result.authProviders, 'authProviders should not be null');
59
+ System.assertNotEquals(null, result.samlProviders, 'samlProviders should not be null');
60
+ }
61
+
62
+ /**
63
+ * Test the inner class constructors for code coverage.
64
+ */
65
+ @isTest
66
+ static void testInnerClassConstructors() {
67
+ Test.startTest();
68
+
69
+ UIBundleSocialLoginConfig.AuthProviderInfo authInfo =
70
+ new UIBundleSocialLoginConfig.AuthProviderInfo(
71
+ 'TestProvider', 'Test Provider', 'https://example.com/icon.png', 'https://example.com/sso'
72
+ );
73
+ System.assertEquals('TestProvider', authInfo.developerName);
74
+ System.assertEquals('Test Provider', authInfo.friendlyName);
75
+ System.assertEquals('https://example.com/icon.png', authInfo.iconUrl);
76
+ System.assertEquals('https://example.com/sso', authInfo.ssoUrl);
77
+
78
+ UIBundleSocialLoginConfig.SamlProviderInfo samlInfo =
79
+ new UIBundleSocialLoginConfig.SamlProviderInfo(
80
+ '001000000000001', 'Test SAML', 'https://example.com/saml/sso'
81
+ );
82
+ System.assertEquals('001000000000001', samlInfo.id);
83
+ System.assertEquals('Test SAML', samlInfo.masterLabel);
84
+ System.assertEquals('https://example.com/saml/sso', samlInfo.ssoUrl);
85
+
86
+ List<UIBundleSocialLoginConfig.AuthProviderInfo> authList =
87
+ new List<UIBundleSocialLoginConfig.AuthProviderInfo>{ authInfo };
88
+ List<UIBundleSocialLoginConfig.SamlProviderInfo> samlList =
89
+ new List<UIBundleSocialLoginConfig.SamlProviderInfo>{ samlInfo };
90
+
91
+ UIBundleSocialLoginConfig.SocialLoginConfigResponse resp =
92
+ new UIBundleSocialLoginConfig.SocialLoginConfigResponse(
93
+ authList, samlList, 'https://example.com/redirect'
94
+ );
95
+ System.assertEquals(1, resp.authProviders.size());
96
+ System.assertEquals(1, resp.samlProviders.size());
97
+ System.assertEquals('https://example.com/redirect', resp.autoRedirectUrl);
98
+
99
+ Test.stopTest();
100
+ }
101
+ }
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <apiVersion>67.0</apiVersion>
4
+ <status>Active</status>
5
+ </ApexClass>
@@ -16,5 +16,9 @@
16
16
  <members>reactexternalapp</members>
17
17
  <name>Network</name>
18
18
  </types>
19
+ <types>
20
+ <members>reactexternalapp_Guest_User_Api_Access</members>
21
+ <name>PermissionSet</name>
22
+ </types>
19
23
  <version>67.0</version>
20
24
  </Package>
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "10.12.2",
3
+ "version": "11.57.2",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
@@ -11,6 +11,7 @@
11
11
  "build": "echo 'No build required for base-sfdx-project'",
12
12
  "clean": "echo 'No clean required for base-sfdx-project'",
13
13
  "lint": "eslint --no-error-on-unmatched-pattern **/{aura,lwc}/**/*.js",
14
+ "validate:org-setup-config": "node scripts/validate-org-setup-config.mjs",
14
15
  "test": "npm run test:unit",
15
16
  "test:coverage": "npm run test",
16
17
  "test:unit": "sfdx-lwc-jest -- --passWithNoTests",
@@ -20,7 +21,12 @@
20
21
  "prettier": "prettier --write \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
21
22
  "prettier:verify": "prettier --check \"**/*.{cls,cmp,component,css,html,js,json,md,page,trigger,xml,yaml,yml}\"",
22
23
  "precommit": "lint-staged",
23
- "setup": "node scripts/org-setup.mjs"
24
+ "setup": "node scripts/org-setup.mjs",
25
+ "dev:preview": "node scripts/org-setup-dev.mjs"
26
+ },
27
+ "dependencies": {
28
+ "fast-xml-parser": "^5.9.3",
29
+ "zod": "^3.24.1"
24
30
  },
25
31
  "devDependencies": {
26
32
  "@lwc/eslint-plugin-lwc": "^3.3.0",
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Shared schema + validator for org-setup.config.json (W-23043729).
3
+ *
4
+ * Authored ONCE, used at TWO moments:
5
+ * (a) build / CI time — `scripts/validate-org-setup-config.mjs` validates every
6
+ * org-setup.config.json this repo ships, failing the build on any violation.
7
+ * (b) setup runtime — `org-setup.mjs` calls `validateConfig` once in main(),
8
+ * before any step runs, to catch the developer's local post-scaffold edits.
9
+ *
10
+ * `validateConfig` is pure: it parses + validates and RETURNS a result. Each call
11
+ * site owns its own print/exit, so the build gate can report every bad file and
12
+ * the runtime can exit immediately — and the validator stays unit-testable.
13
+ *
14
+ * The zod schema uses `.strict()` at every level so unknown keys (e.g. the
15
+ * `permsetAssignment` singular typo) are rejected rather than silently ignored.
16
+ */
17
+
18
+ import { z } from 'zod';
19
+
20
+ /** Closed set of assignee values — no arbitrary usernames. */
21
+ const Assignee = z.enum(['currentUser', 'guestUser', 'skip']);
22
+
23
+ // No siteName: for guestUser the site is derived from the single
24
+ // networks/<siteName>.network-meta.xml the app ships (see spec §5.2).
25
+ const Assignment = z
26
+ .object({
27
+ assignee: Assignee,
28
+ })
29
+ .strict();
30
+
31
+ export const ConfigSchema = z
32
+ .object({
33
+ permsetAssignments: z
34
+ .object({
35
+ // guestUser is valid here — siteName is derived, not per-assignment.
36
+ defaultAssignee: Assignee.default('skip'),
37
+ assignments: z.record(z.string(), Assignment).default({}),
38
+ })
39
+ .strict()
40
+ .optional(),
41
+ role: z
42
+ .object({
43
+ assignee: z.literal('currentUser'), // only value the role code honors
44
+ roleName: z.string().min(1),
45
+ })
46
+ .strict()
47
+ .optional(),
48
+ selfRegistration: z
49
+ .object({
50
+ // No siteName: the site is derived from the single
51
+ // networks/<siteName>.network-meta.xml the app ships (see spec §5.2),
52
+ // exactly like the guestUser permset path.
53
+ //
54
+ // selfRegProfile also drives the M1 license pre-check (W-23043735):
55
+ // setup derives the required UserLicense from this profile
56
+ // (Profile.UserLicense, matched on the stable LicenseDefinitionKey) and
57
+ // warns + skips self-registration when the org lacks it or has no seats.
58
+ // No separate license field is declared — the requirement can't drift
59
+ // from the profile the flow actually assigns.
60
+ selfRegProfile: z.string().min(1),
61
+ accountName: z.string().min(1),
62
+ })
63
+ .strict()
64
+ .optional(),
65
+ socialLogin: z
66
+ .object({
67
+ // Profile to add to NetworkMemberGroup so SSO-registered users can access
68
+ // the community (e.g. "Customer Community User"). Also enables the
69
+ // "Allow standard external profiles" org setting.
70
+ communityMemberProfile: z.string().min(1),
71
+ // DeveloperName of AuthProvider (OAuth) or SamlSsoConfig (SAML) records to link to the site's AuthConfig.
72
+ // Required because React (Site Container) sites hide SSO config in Admin UI.
73
+ authProviderNames: z.array(z.string().min(1)).min(1),
74
+ // Permission set to assign to community users created via SSO.
75
+ // Required because getCurrentUser() calls /chatter/users/me which needs
76
+ // API access (PermissionsApiEnabled) that the community profile lacks.
77
+ // Typically the app's "*_Guest_User_Api_Access" permset.
78
+ communityUserPermset: z.string().min(1).optional(),
79
+ })
80
+ .strict()
81
+ .optional(),
82
+ })
83
+ .strict();
84
+
85
+ /**
86
+ * Render a single zod issue as a "path: message" line. Empty path (a root-level
87
+ * problem) renders as "<root>: message".
88
+ */
89
+ function formatIssue(issue) {
90
+ const path = issue.path.length > 0 ? issue.path.join('.') : '<root>';
91
+ return `${path}: ${issue.message}`;
92
+ }
93
+
94
+ /**
95
+ * Parse + validate a raw org-setup.config.json string.
96
+ *
97
+ * @param {string} rawText raw file contents (not yet JSON-parsed)
98
+ * @param {string} [configPath] path used only for error messages
99
+ * @returns {{ ok: true, data: object } | { ok: false, errors: string[] }}
100
+ * On success, `data` is the parsed + defaulted config. On failure, `errors`
101
+ * is a non-empty list of human-readable messages (JSON parse error or zod
102
+ * issues). The caller decides whether to print/exit.
103
+ */
104
+ export function validateConfig(rawText, configPath) {
105
+ const where = configPath ? ` (${configPath})` : '';
106
+
107
+ let parsed;
108
+ try {
109
+ parsed = JSON.parse(rawText);
110
+ } catch (err) {
111
+ return { ok: false, errors: [`malformed JSON${where}: ${err.message}`] };
112
+ }
113
+
114
+ const result = ConfigSchema.safeParse(parsed);
115
+ if (!result.success) {
116
+ return { ok: false, errors: result.error.issues.map(formatIssue) };
117
+ }
118
+
119
+ return { ok: true, data: result.data };
120
+ }