@salesforce/templates 66.14.0 → 66.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/lib/generators/lightningOutGenerator.d.ts +7 -0
  2. package/lib/generators/lightningOutGenerator.js +122 -0
  3. package/lib/generators/lightningOutGenerator.js.map +1 -0
  4. package/lib/generators/uiEmbeddingGenerator.js +6 -6
  5. package/lib/generators/uiEmbeddingGenerator.js.map +1 -1
  6. package/lib/i18n/i18n.d.ts +12 -2
  7. package/lib/i18n/i18n.js +12 -2
  8. package/lib/i18n/i18n.js.map +1 -1
  9. package/lib/index.d.ts +1 -0
  10. package/lib/index.js +1 -0
  11. package/lib/index.js.map +1 -1
  12. package/lib/templates/lightningout/default/corsWhitelistOrigin.xml +4 -0
  13. package/lib/templates/lightningout/default/externalClientApplication.xml +7 -0
  14. package/lib/templates/lightningout/default/extlClntAppGlobalOauthSettings.xml +7 -0
  15. package/lib/templates/lightningout/default/extlClntAppOauthSettings.xml +6 -0
  16. package/lib/templates/lightningout/default/lightningOutApp.xml +20 -0
  17. package/lib/templates/lightningout/default/myDomainSettings.xml +4 -0
  18. package/lib/templates/lightningout/default/securitySettings.xml +6 -0
  19. package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package-lock.json +608 -506
  20. package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package-lock.json +611 -509
  21. package/lib/templates/project/reactexternalapp/CHANGELOG.md +437 -0
  22. package/lib/templates/project/reactexternalapp/README.md +2 -0
  23. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package-lock.json +694 -447
  24. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package.json +6 -4
  25. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/patches/aria-hidden+1.2.6.patch +45 -0
  26. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Login.tsx +3 -2
  27. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Register.tsx +3 -2
  28. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +9 -6
  29. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +14 -3
  30. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +7 -5
  31. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +1 -0
  32. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +17 -1
  33. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +2 -0
  34. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +16 -4
  35. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +1 -0
  36. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +27 -4
  37. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +12 -7
  38. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +14 -4
  39. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/appLayout.tsx +42 -7
  40. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ObjectBreadcrumb.tsx +1 -5
  41. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +34 -47
  42. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +3 -2
  43. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/utils/accountFields.ts +1 -14
  44. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -1
  45. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleAuthUtils_Test.cls +141 -0
  46. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleAuthUtils_Test.cls-meta.xml +5 -0
  47. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls +23 -11
  48. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls +80 -0
  49. package/lib/templates/project/reactexternalapp/package.json +1 -1
  50. package/lib/templates/project/reactexternalapp/scripts/org-setup-config-schema.mjs +14 -2
  51. package/lib/templates/project/reactexternalapp/scripts/org-setup-dev.mjs +27 -0
  52. package/lib/templates/project/reactexternalapp/scripts/org-setup-url.mjs +108 -0
  53. package/lib/templates/project/reactexternalapp/scripts/org-setup-xml.mjs +96 -0
  54. package/lib/templates/project/reactexternalapp/scripts/org-setup.mjs +195 -3
  55. package/lib/templates/project/reactinternalapp/CHANGELOG.md +533 -0
  56. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package-lock.json +695 -448
  57. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package.json +7 -5
  58. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/patches/aria-hidden+1.2.6.patch +45 -0
  59. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +9 -6
  60. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +14 -3
  61. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +7 -5
  62. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +1 -0
  63. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +17 -1
  64. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +2 -0
  65. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +16 -4
  66. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +1 -0
  67. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +27 -4
  68. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +7 -1
  69. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +12 -7
  70. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +24 -5
  71. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/appLayout.tsx +41 -7
  72. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ObjectBreadcrumb.tsx +1 -5
  73. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +40 -50
  74. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +7 -2
  75. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/utils/accountFields.ts +1 -14
  76. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -1
  77. package/lib/templates/project/reactinternalapp/package.json +1 -1
  78. package/lib/templates/project/reactinternalapp/scripts/org-setup-config-schema.mjs +14 -2
  79. package/lib/templates/project/reactinternalapp/scripts/org-setup-dev.mjs +27 -0
  80. package/lib/templates/project/reactinternalapp/scripts/org-setup-url.mjs +108 -0
  81. package/lib/templates/project/reactinternalapp/scripts/org-setup-xml.mjs +96 -0
  82. package/lib/templates/project/reactinternalapp/scripts/org-setup.mjs +195 -3
  83. package/lib/templates/uiBundles/angularbasic/package-lock.json +608 -506
  84. package/lib/templates/uiBundles/reactbasic/package-lock.json +691 -444
  85. package/lib/templates/uiBundles/reactbasic/package.json +6 -4
  86. package/lib/templates/uiBundles/reactbasic/patches/aria-hidden+1.2.6.patch +45 -0
  87. package/lib/templates/uiembedding/default/default.html +1 -1
  88. package/lib/utils/lightningOut.d.ts +42 -0
  89. package/lib/utils/lightningOut.js +119 -0
  90. package/lib/utils/lightningOut.js.map +1 -0
  91. package/lib/utils/template-placeholders.d.ts +1 -1
  92. package/lib/utils/template-placeholders.js +3 -1
  93. package/lib/utils/template-placeholders.js.map +1 -1
  94. package/lib/utils/types.d.ts +29 -7
  95. package/lib/utils/types.js +8 -5
  96. package/lib/utils/types.js.map +1 -1
  97. package/package.json +5 -5
  98. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +0 -246
  99. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/__examples__/html-middleware-site-example.ts +0 -0
  100. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/__examples__/language-switcher-example.ts +0 -0
  101. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/build-language-url.ts +0 -0
  102. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/index.ts +0 -0
  103. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/language-switcher.html +0 -0
  104. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/language-switcher.ts +0 -0
  105. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/language-switcher → _f_/_ls_}/languages.ts +0 -0
  106. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/api/object-search.service.ts +0 -0
  107. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.html +0 -0
  108. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.ts +0 -0
  109. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.html +0 -0
  110. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.ts +0 -0
  111. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.html +0 -0
  112. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.ts +0 -0
  113. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.html +0 -0
  114. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.ts +0 -0
  115. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.html +0 -0
  116. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.ts +0 -0
  117. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.html +0 -0
  118. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.ts +0 -0
  119. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.html +0 -0
  120. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.ts +0 -0
  121. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.html +0 -0
  122. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.ts +0 -0
  123. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.html +0 -0
  124. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.ts +0 -0
  125. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.html +0 -0
  126. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.ts +0 -0
  127. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/object-search-state.service.ts +0 -0
  128. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.html +0 -0
  129. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.ts +0 -0
  130. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.html +0 -0
  131. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.ts +0 -0
  132. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.html +0 -0
  133. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.ts +0 -0
  134. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/debounce.ts +0 -0
  135. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/field-utils.ts +0 -0
  136. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/filter-utils.ts +0 -0
  137. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/index.ts +0 -0
  138. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/sort-utils.ts +0 -0
  139. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth/auth.guard.ts +0 -0
  140. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth/auth.service.ts +0 -0
  141. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-form/auth-form.html +0 -0
  142. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-form/auth-form.ts +0 -0
  143. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-layout/auth-layout.html +0 -0
  144. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-layout/auth-layout.ts +0 -0
  145. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/card-layout/card-layout.html +0 -0
  146. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/card-layout/card-layout.ts +0 -0
  147. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/config/authentication.config.ts +0 -0
  148. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/footer-link/footer-link.html +0 -0
  149. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/footer-link/footer-link.ts +0 -0
  150. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/menu/auth-menu/auth-menu.html +0 -0
  151. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/menu/auth-menu/auth-menu.ts +0 -0
  152. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/reactive-form-page.base.ts +0 -0
  153. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/session/session.html +0 -0
  154. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/session/session.ts +0 -0
  155. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/status-alert/status-alert.html +0 -0
  156. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/status-alert/status-alert.ts +0 -0
  157. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/submit-button/submit-button.html +0 -0
  158. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/submit-button/submit-button.ts +0 -0
  159. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/auth-helpers.ts +0 -0
  160. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/auth-validators.ts +0 -0
  161. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/helpers.ts +0 -0
  162. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/session-time-servlet.ts +0 -0
  163. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/session-timeout.config.ts +0 -0
  164. /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/session-timeout.service.ts +0 -0
  165. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/api/object-search.service.ts +0 -0
  166. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.html +0 -0
  167. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.ts +0 -0
  168. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.html +0 -0
  169. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.ts +0 -0
  170. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.html +0 -0
  171. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.ts +0 -0
  172. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.html +0 -0
  173. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.ts +0 -0
  174. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.html +0 -0
  175. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.ts +0 -0
  176. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.html +0 -0
  177. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.ts +0 -0
  178. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.html +0 -0
  179. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.ts +0 -0
  180. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.html +0 -0
  181. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.ts +0 -0
  182. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.html +0 -0
  183. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.ts +0 -0
  184. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.html +0 -0
  185. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.ts +0 -0
  186. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/object-search-state.service.ts +0 -0
  187. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.html +0 -0
  188. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.ts +0 -0
  189. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.html +0 -0
  190. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.ts +0 -0
  191. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.html +0 -0
  192. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.ts +0 -0
  193. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/debounce.ts +0 -0
  194. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/field-utils.ts +0 -0
  195. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/filter-utils.ts +0 -0
  196. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/index.ts +0 -0
  197. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/sort-utils.ts +0 -0
  198. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/agentforce/agentforce-embed.service.ts +0 -0
  199. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/agentforce/conversation.html +0 -0
  200. /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/agentforce/conversation.ts +0 -0
@@ -6,7 +6,7 @@ import GET_ACCOUNT_DETAIL from "../api/account/query/getAccountDetail.graphql?ra
6
6
  import { Alert, AlertTitle, AlertDescription } from "../components/ui/alert";
7
7
  import { Button } from "../components/ui/button";
8
8
  import { Card, CardContent } from "../components/ui/card";
9
- import { fieldValue, getAddressFieldLines, formatDateTimeField } from "../utils/accountFields";
9
+ import { fieldValue, getAddressFieldLines } from "../utils/accountFields";
10
10
  import {
11
11
  Collapsible,
12
12
  CollapsibleTrigger,
@@ -15,13 +15,8 @@ import {
15
15
  import { Separator } from "../components/ui/separator";
16
16
  import { Skeleton } from "../components/ui/skeleton";
17
17
  import { useAsyncData } from "../hooks/useAsyncData";
18
- import { ObjectBreadcrumb } from "../components/ObjectBreadcrumb";
19
18
 
20
- /**
21
- * A uiapi scalar field as returned with `@optional { value displayValue }`.
22
- * Typed locally so this page no longer depends on the generated
23
- * `graphql-operations-types` that shipped with feature-react-object-search.
24
- */
19
+ /** A uiapi scalar field as returned with `@optional { value displayValue }`. Typed locally to avoid a generated-types dependency. */
25
20
  type FieldValue = { value?: unknown; displayValue?: string | null } | null;
26
21
  type NameHolder = { Name?: FieldValue } | null;
27
22
 
@@ -88,23 +83,17 @@ export default function AccountObjectDetail() {
88
83
  error,
89
84
  } = useAsyncData(() => fetchAccountDetail(recordId!), [recordId]);
90
85
 
91
- return (
92
- <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
93
- <ObjectBreadcrumb
94
- listPath="/accounts"
95
- listLabel="Accounts"
96
- loading={loading}
97
- recordName={
98
- account
99
- ? (fieldValue(account.Name) ?? "")
100
- : error
101
- ? "Error"
102
- : loading
103
- ? undefined
104
- : "Not Found"
105
- }
106
- />
86
+ const pageTitle = account
87
+ ? `${fieldValue(account.Name) ?? "Account"} | MyApp`
88
+ : error
89
+ ? "Error | MyApp"
90
+ : loading
91
+ ? "Loading Account | MyApp"
92
+ : "Account Not Found | MyApp";
107
93
 
94
+ return (
95
+ <main className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
96
+ <title>{pageTitle}</title>
108
97
  {/* Loading state */}
109
98
  {loading && <AccountDetailSkeleton />}
110
99
 
@@ -116,7 +105,7 @@ export default function AccountObjectDetail() {
116
105
 
117
106
  {/* Content */}
118
107
  {account && <AccountDetailContent account={account} />}
119
- </div>
108
+ </main>
120
109
  );
121
110
  }
122
111
 
@@ -137,17 +126,8 @@ function AccountDetailContent({ account }: { account: AccountNode }) {
137
126
  country: fieldValue(account.ShippingCountry),
138
127
  });
139
128
 
140
- const dateTimeOptions = { dateStyle: "medium", timeStyle: "short" } as const;
141
- const createdDate = formatDateTimeField(
142
- fieldValue(account.CreatedDate),
143
- undefined,
144
- dateTimeOptions,
145
- );
146
- const lastModifiedDate = formatDateTimeField(
147
- fieldValue(account.LastModifiedDate),
148
- undefined,
149
- dateTimeOptions,
150
- );
129
+ const createdDate = fieldValue(account.CreatedDate);
130
+ const lastModifiedDate = fieldValue(account.LastModifiedDate);
151
131
 
152
132
  return (
153
133
  <>
@@ -258,10 +238,16 @@ function Section({ title, children }: { title: string; children: React.ReactNode
258
238
  const [open, setOpen] = useState(true);
259
239
  return (
260
240
  <Collapsible open={open} onOpenChange={setOpen}>
261
- <CollapsibleTrigger className="flex items-center gap-2 cursor-pointer text-lg font-semibold py-2">
262
- {open ? <ChevronDown className="size-5" /> : <ChevronRight className="size-5" />}
263
- {title}
264
- </CollapsibleTrigger>
241
+ <h2>
242
+ <CollapsibleTrigger className="flex items-center gap-2 cursor-pointer text-lg font-semibold py-2">
243
+ {open ? (
244
+ <ChevronDown aria-hidden="true" className="size-5" />
245
+ ) : (
246
+ <ChevronRight aria-hidden="true" className="size-5" />
247
+ )}
248
+ {title}
249
+ </CollapsibleTrigger>
250
+ </h2>
265
251
  <CollapsibleContent>
266
252
  <div className="mt-2 space-y-4">{children}</div>
267
253
  </CollapsibleContent>
@@ -273,9 +259,9 @@ function AccountDetailError({ onBack }: { onBack: () => void }) {
273
259
  return (
274
260
  <>
275
261
  <Alert variant="destructive" role="alert">
276
- <AlertCircle />
262
+ <AlertCircle aria-hidden="true" />
277
263
  <AlertTitle>
278
- <h2>Failed to load account</h2>
264
+ <h1>Failed to load account</h1>
279
265
  </AlertTitle>
280
266
  <AlertDescription>
281
267
  Something went wrong while loading this account. Please try again later.
@@ -283,7 +269,7 @@ function AccountDetailError({ onBack }: { onBack: () => void }) {
283
269
  </Alert>
284
270
  <div className="mt-4 flex gap-3">
285
271
  <Button variant="outline" onClick={onBack}>
286
- ← Back
272
+ <span aria-hidden="true">←</span> Back
287
273
  </Button>
288
274
  <Button variant="outline" onClick={() => window.location.reload()}>
289
275
  Retry
@@ -297,13 +283,13 @@ function AccountDetailNotFound({ onBack }: { onBack: () => void }) {
297
283
  return (
298
284
  <Card>
299
285
  <CardContent className="flex flex-col items-center justify-center py-16 text-center">
300
- <FileQuestion className="size-12 text-muted-foreground mb-4" />
301
- <h2 className="text-lg font-semibold mb-1">Account not found</h2>
286
+ <FileQuestion aria-hidden="true" className="size-12 text-muted-foreground mb-4" />
287
+ <h1 className="text-lg font-semibold mb-1">Account not found</h1>
302
288
  <p className="text-sm text-muted-foreground mb-6">
303
289
  The account you're looking for doesn't exist or may have been deleted.
304
290
  </p>
305
291
  <Button variant="outline" onClick={onBack}>
306
- ← Go back
292
+ <span aria-hidden="true">←</span> Go back
307
293
  </Button>
308
294
  </CardContent>
309
295
  </Card>
@@ -312,7 +298,8 @@ function AccountDetailNotFound({ onBack }: { onBack: () => void }) {
312
298
 
313
299
  function AccountDetailSkeleton() {
314
300
  return (
315
- <>
301
+ <div role="status" aria-live="polite">
302
+ <span className="sr-only">Loading account…</span>
316
303
  <Skeleton className="h-8 w-56 mb-4" />
317
304
 
318
305
  <Card>
@@ -361,7 +348,7 @@ function AccountDetailSkeleton() {
361
348
  </div>
362
349
  </CardContent>
363
350
  </Card>
364
- </>
351
+ </div>
365
352
  );
366
353
  }
367
354
 
@@ -2,9 +2,10 @@ import { GlobalSearchBox } from "../features/search";
2
2
 
3
3
  export default function HomePage() {
4
4
  return (
5
- <div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
5
+ <main className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
6
+ <title>Home | MyApp</title>
6
7
  <h1 className="text-2xl font-bold mb-6">Home</h1>
7
8
  <GlobalSearchBox placeholder="Search accounts, contacts, opportunities..." />
8
- </div>
9
+ </main>
9
10
  );
10
11
  }
@@ -1,8 +1,4 @@
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
- */
1
+ /** Field helpers for reading uiapi GraphQL response nodes: values arrive as `{ value, displayValue }` objects, so callers need one place to unwrap them. */
6
2
 
7
3
  /** Picks the user-facing string for a `{ value, displayValue }` field. */
8
4
  export function fieldValue(
@@ -27,12 +23,3 @@ export function getAddressFieldLines(address: {
27
23
  if (lines.length === 0) return null;
28
24
  return lines;
29
25
  }
30
-
31
- /** Formats an ISO datetime string with `toLocaleString`, or null if absent. */
32
- export function formatDateTimeField(
33
- value?: string | null,
34
- ...args: Parameters<Date["toLocaleString"]>
35
- ) {
36
- if (!value) return null;
37
- return new Date(value).toLocaleString(...args);
38
- }
@@ -1 +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"}
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__/MergedSearchResults.test.tsx","./src/features/search/components/__tests__/Search.test.tsx","./src/features/search/components/__tests__/SourceSection.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/features/search/utils/__tests__/filterUtils.test.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","./src/utils/__tests__/accountFields.test.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,141 @@
1
+ /**
2
+ * Test class for UIBundleAuthUtils.
3
+ *
4
+ * Focuses on getSanitizedStartUrl, the shared open-redirect (CWE-601) guard
5
+ * used by UIBundleLogin, UIBundleRegistration and UIBundleSocialLoginConfig.
6
+ * Every rejection path and the safe-path prefixing
7
+ * behavior are asserted deterministically with an explicit path prefix.
8
+ */
9
+ @isTest
10
+ private class UIBundleAuthUtils_Test {
11
+
12
+ // Explicit, non-null community path prefix so behavior is deterministic
13
+ // (Site.getPathPrefix() is null/blank in a plain unit-test context).
14
+ private static final String PREFIX = '/community';
15
+
16
+ // ---- Safe / allowed inputs ----------------------------------------------
17
+
18
+ @isTest
19
+ static void allowsSafeRelativePath() {
20
+ System.assertEquals(
21
+ '/community/dashboard',
22
+ UIBundleAuthUtils.getSanitizedStartUrl('/dashboard', PREFIX),
23
+ 'A safe community-relative path should be prefixed and preserved'
24
+ );
25
+ }
26
+
27
+ @isTest
28
+ static void allowsNestedRelativePath() {
29
+ System.assertEquals(
30
+ '/community/safe/relative/path',
31
+ UIBundleAuthUtils.getSanitizedStartUrl('/safe/relative/path', PREFIX),
32
+ 'A nested relative path should be prefixed and preserved'
33
+ );
34
+ }
35
+
36
+ @isTest
37
+ static void blankAndRootFallBackToDefault() {
38
+ System.assertEquals(PREFIX, UIBundleAuthUtils.getSanitizedStartUrl(null, PREFIX), 'null -> default');
39
+ System.assertEquals(PREFIX, UIBundleAuthUtils.getSanitizedStartUrl('', PREFIX), 'empty -> default');
40
+ System.assertEquals(PREFIX, UIBundleAuthUtils.getSanitizedStartUrl(' ', PREFIX), 'whitespace -> default');
41
+ System.assertEquals(PREFIX, UIBundleAuthUtils.getSanitizedStartUrl('/', PREFIX), '"/" -> default');
42
+ }
43
+
44
+ // ---- Rejected / malicious inputs (all fall back to the default) ----------
45
+
46
+ @isTest
47
+ static void rejectsAbsoluteHttpUrl() {
48
+ System.assertEquals(
49
+ PREFIX,
50
+ UIBundleAuthUtils.getSanitizedStartUrl('https://evil-attacker.com', PREFIX),
51
+ 'Absolute http(s) URL must be rejected'
52
+ );
53
+ }
54
+
55
+ @isTest
56
+ static void rejectsProtocolRelativeUrl() {
57
+ System.assertEquals(
58
+ PREFIX,
59
+ UIBundleAuthUtils.getSanitizedStartUrl('//evil-attacker.com', PREFIX),
60
+ 'Protocol-relative URL must be rejected'
61
+ );
62
+ }
63
+
64
+ @isTest
65
+ static void rejectsAmbiguousScheme() {
66
+ System.assertEquals(
67
+ PREFIX,
68
+ UIBundleAuthUtils.getSanitizedStartUrl('https:evil-attacker.com', PREFIX),
69
+ 'Malformed/ambiguous scheme must be rejected'
70
+ );
71
+ }
72
+
73
+ @isTest
74
+ static void rejectsBackslashVariant() {
75
+ System.assertEquals(
76
+ PREFIX,
77
+ UIBundleAuthUtils.getSanitizedStartUrl('/\\evil-attacker.com', PREFIX),
78
+ 'Backslash normalization trick must be rejected'
79
+ );
80
+ }
81
+
82
+ @isTest
83
+ static void rejectsAtSign() {
84
+ System.assertEquals(
85
+ PREFIX,
86
+ UIBundleAuthUtils.getSanitizedStartUrl('/x@evil-attacker.com', PREFIX),
87
+ 'User-info "@" must be rejected'
88
+ );
89
+ }
90
+
91
+ @isTest
92
+ static void rejectsColon() {
93
+ System.assertEquals(
94
+ PREFIX,
95
+ UIBundleAuthUtils.getSanitizedStartUrl('/path:8080', PREFIX),
96
+ 'Colon (port/scheme manipulation) must be rejected'
97
+ );
98
+ }
99
+
100
+ @isTest
101
+ static void rejectsEncodedProtocolRelativeBypass() {
102
+ // %2f%2f decodes to // — the decode step must catch this.
103
+ System.assertEquals(
104
+ PREFIX,
105
+ UIBundleAuthUtils.getSanitizedStartUrl('%2f%2fevil-attacker.com', PREFIX),
106
+ 'URL-encoded protocol-relative bypass must be rejected'
107
+ );
108
+ }
109
+
110
+ @isTest
111
+ static void rejectsControlCharacters() {
112
+ String withNewline = '/foo' + String.fromCharArray(new List<Integer>{ 10 }) + 'bar';
113
+ System.assertEquals(
114
+ PREFIX,
115
+ UIBundleAuthUtils.getSanitizedStartUrl(withNewline, PREFIX),
116
+ 'Embedded control characters must be rejected'
117
+ );
118
+ }
119
+
120
+ // ---- Supporting API coverage --------------------------------------------
121
+
122
+ @isTest
123
+ static void authExceptionCarriesStatusAndMessages() {
124
+ UIBundleAuthUtils.AuthException single = new UIBundleAuthUtils.AuthException(400, 'bad request');
125
+ System.assertEquals(400, single.statusCode, 'statusCode should round-trip');
126
+ System.assertEquals(1, single.messages.size(), 'single-message constructor');
127
+
128
+ UIBundleAuthUtils.AuthException multi =
129
+ new UIBundleAuthUtils.AuthException(500, new List<String>{ 'a', 'b' });
130
+ System.assertEquals(500, multi.statusCode, 'statusCode should round-trip');
131
+ System.assertEquals(2, multi.messages.size(), 'multi-message constructor');
132
+ }
133
+
134
+ @isTest
135
+ static void debugLogCompletesWithoutError() {
136
+ Test.startTest();
137
+ UIBundleAuthUtils.debugLog(new IllegalArgumentException('boom'), LoggingLevel.ERROR);
138
+ Test.stopTest();
139
+ System.assert(true, 'debugLog should complete without throwing');
140
+ }
141
+ }
@@ -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>
@@ -22,17 +22,9 @@ global with sharing class UIBundleSocialLoginConfig {
22
22
  @HttpGet
23
23
  global static SocialLoginConfigResponse getConfig() {
24
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
- }
25
+ // Resolve the post-authentication redirect path, sanitized against
26
+ // open-redirect attacks (CWE-601). See resolveStartUrl.
27
+ String startUrl = resolveStartUrl();
36
28
 
37
29
  String communityUrl = Site.getBaseUrl();
38
30
  Auth.AuthConfiguration authConfig = new Auth.AuthConfiguration(communityUrl, startUrl);
@@ -89,6 +81,26 @@ global with sharing class UIBundleSocialLoginConfig {
89
81
  }
90
82
  }
91
83
 
84
+ /**
85
+ * Resolves the post-authentication redirect path from the request and
86
+ * sanitizes it to prevent open-redirect attacks (CWE-601).
87
+ *
88
+ * Delegates to the shared UIBundleAuthUtils.getSanitizedStartUrl — the same
89
+ * validation used by UIBundleLogin and UIBundleRegistration — which
90
+ * URL-decodes the value (catching encoded bypasses such as %2f%2f) and then
91
+ * rejects absolute, protocol-relative ("//"), backslash, "@", ":" and
92
+ * control-character inputs, falling back to the community path prefix. Only
93
+ * safe, community-relative paths survive, prefixed with Site.getPathPrefix()
94
+ * so the redirect lands on this community rather than the org default.
95
+ */
96
+ @TestVisible
97
+ private static String resolveStartUrl() {
98
+ return UIBundleAuthUtils.getSanitizedStartUrl(
99
+ RestContext.request.params.get('startURL'),
100
+ Site.getPathPrefix()
101
+ );
102
+ }
103
+
92
104
  global class SocialLoginConfigResponse {
93
105
  global List<AuthProviderInfo> authProviders;
94
106
  global List<SamlProviderInfo> samlProviders;
@@ -98,4 +98,84 @@ private class UIBundleSocialLoginConfig_Test {
98
98
 
99
99
  Test.stopTest();
100
100
  }
101
+
102
+ // ---- Open-redirect sanitization (CWE-601) -------------------------------
103
+ // resolveStartUrl() is the boundary where the endpoint sanitizes the
104
+ // caller-supplied startURL before it is embedded in the SSO redirect URL.
105
+ // These tests assert malicious values never survive that boundary and that
106
+ // legitimate relative paths do.
107
+
108
+ @isTest
109
+ static void resolveStartUrlRejectsAbsoluteUrl() {
110
+ assertNotReflected('https://evil-attacker.com');
111
+ }
112
+
113
+ @isTest
114
+ static void resolveStartUrlRejectsProtocolRelativeUrl() {
115
+ assertNotReflected('//evil-attacker.com');
116
+ }
117
+
118
+ @isTest
119
+ static void resolveStartUrlRejectsBackslashVariant() {
120
+ assertNotReflected('/\\evil-attacker.com');
121
+ }
122
+
123
+ @isTest
124
+ static void resolveStartUrlRejectsEncodedBypass() {
125
+ assertNotReflected('%2f%2fevil-attacker.com');
126
+ }
127
+
128
+ @isTest
129
+ static void resolveStartUrlAllowsRelativePath() {
130
+ setRequest('/dashboard');
131
+ String resolved = UIBundleSocialLoginConfig.resolveStartUrl();
132
+ System.assertNotEquals(null, resolved, 'A valid relative path should resolve to a non-null value');
133
+ System.assert(
134
+ resolved.endsWith('/dashboard'),
135
+ 'A valid relative path must be preserved (optionally prefixed): ' + resolved
136
+ );
137
+ System.assert(!resolved.startsWith('http'), 'Result must not be absolute: ' + resolved);
138
+ }
139
+
140
+ @isTest
141
+ static void getConfigWithMaliciousStartUrlReturnsGracefulEmpty() {
142
+ // End-to-end: a malicious startURL must not crash the endpoint; without
143
+ // a real site context it returns the graceful empty response (unchanged).
144
+ setRequest('https://evil-attacker.com');
145
+
146
+ Test.startTest();
147
+ UIBundleSocialLoginConfig.SocialLoginConfigResponse result =
148
+ UIBundleSocialLoginConfig.getConfig();
149
+ Test.stopTest();
150
+
151
+ System.assertNotEquals(null, result, 'Response should not be null');
152
+ System.assertEquals(0, result.authProviders.size(), 'No providers without site context');
153
+ System.assertEquals(0, result.samlProviders.size(), 'No SAML providers without site context');
154
+ System.assertEquals(null, result.autoRedirectUrl, 'No auto-redirect without providers');
155
+ }
156
+
157
+ // ---- helpers ------------------------------------------------------------
158
+
159
+ /** Asserts a malicious startURL value is not reflected by resolveStartUrl(). */
160
+ private static void assertNotReflected(String maliciousStartUrl) {
161
+ setRequest(maliciousStartUrl);
162
+ String resolved = UIBundleSocialLoginConfig.resolveStartUrl();
163
+ String safe = resolved == null ? '' : resolved;
164
+ System.assert(!safe.contains('evil-attacker'), 'Malicious host must not be reflected: ' + safe);
165
+ System.assert(!safe.startsWith('http'), 'Result must not be an absolute URL: ' + safe);
166
+ System.assert(!safe.startsWith('//'), 'Result must not be protocol-relative: ' + safe);
167
+ System.assert(!safe.contains('\\'), 'Result must not contain a backslash: ' + safe);
168
+ }
169
+
170
+ /** Builds a GET RestContext with the given startURL param (null => param omitted). */
171
+ private static void setRequest(String startUrlValue) {
172
+ RestRequest req = new RestRequest();
173
+ req.requestURI = '/services/apexrest/auth/social-login-config';
174
+ req.httpMethod = 'GET';
175
+ if (startUrlValue != null) {
176
+ req.params.put('startURL', startUrlValue);
177
+ }
178
+ RestContext.request = req;
179
+ RestContext.response = new RestResponse();
180
+ }
101
181
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "11.64.0",
3
+ "version": "12.4.5",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
@@ -72,13 +72,25 @@ export const ConfigSchema = z
72
72
  // Required because React (Site Container) sites hide SSO config in Admin UI.
73
73
  authProviderNames: z.array(z.string().min(1)).min(1),
74
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.
75
+ // Required because getCurrentUser() calls UI API GraphQL (uiapi.currentUser)
76
+ // which needs API access (PermissionsApiEnabled) that the community profile lacks.
77
77
  // Typically the app's "*_Guest_User_Api_Access" permset.
78
78
  communityUserPermset: z.string().min(1).optional(),
79
79
  })
80
80
  .strict()
81
81
  .optional(),
82
+ // URL members are redirected to after logging out, written to the site's
83
+ // <logoutUrl> network metadata (a post-deploy step). Steers logout back to THIS
84
+ // site so members aren't dropped on the org default-site login (which, in an
85
+ // org hosting multiple sites, can be a different community). Prefer a
86
+ // site-relative path (e.g. "/myapp/"): it is domain-independent, so the same
87
+ // shipped value is valid on every org. The platform REQUIRES an absolute logout
88
+ // URL, so org-setup resolves a relative path against the site's Experience Cloud
89
+ // origin (discovered from the org at deploy time) before writing it; an
90
+ // already-absolute value is used as-is. Kept a permissive non-empty string (not
91
+ // z.string().url()) so relative paths are valid; character-safety for raw XML
92
+ // interpolation is enforced at write time.
93
+ logoutUrl: z.string().min(1).optional(),
82
94
  })
83
95
  .strict();
84
96
 
@@ -60,6 +60,31 @@ Options:
60
60
  return { targetOrg, uiBundleName };
61
61
  }
62
62
 
63
+ /**
64
+ * Print a heads-up about auth surfaces that only work on the deployed Experience
65
+ * site. In local preview, `sdk.fetch` is proxied to the org outside the site's
66
+ * guest/community context, so social login and password/MFA login cannot be
67
+ * exercised on localhost. This mirrors the "Local preview limitations" sections
68
+ * in the feature-react-authentication / feature-react-mfa READMEs — surfaced here
69
+ * so it is seen even when the READMEs are not.
70
+ */
71
+ function printLocalPreviewWarning() {
72
+ console.log(
73
+ [
74
+ '',
75
+ '⚠️ Local preview limitation — some auth surfaces only work on the DEPLOYED site',
76
+ ' Local preview proxies sdk.fetch to the org outside the Experience site guest',
77
+ ' context (Site.getBaseUrl() is blank, no site session), so on localhost:',
78
+ ' • Social Login buttons do not render (/auth/social-login-config returns no providers)',
79
+ ' • Password / MFA login fails with "Your login attempt has failed…" (Site.login() cannot',
80
+ ' establish the site session)',
81
+ ' This is expected, not a misconfiguration. Test social login and MFA on the published',
82
+ ' site login page: https://<domain>.site.com/<site-path>/login',
83
+ '',
84
+ ].join('\n'),
85
+ );
86
+ }
87
+
63
88
  async function main() {
64
89
  const parsed = parseArgs();
65
90
 
@@ -76,6 +101,8 @@ async function main() {
76
101
  });
77
102
  run('GraphQL codegen', 'npm', ['run', 'graphql:codegen'], { cwd: uiBundleDir });
78
103
 
104
+ printLocalPreviewWarning();
105
+
79
106
  console.log('\n--- Launching dev server (Ctrl+C to stop) ---\n');
80
107
  const devResult = run('Dev server', 'npm', ['run', 'dev'], { cwd: uiBundleDir, optional: true });
81
108
  process.exit(devResult.status ?? 0);