@salesforce/templates 66.6.2 → 66.7.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 (205) hide show
  1. package/lib/generators/projectGenerator.js +4 -4
  2. package/lib/generators/projectGenerator.js.map +1 -1
  3. package/lib/generators/{webApplicationGenerator.d.ts → uiBundleGenerator.d.ts} +2 -2
  4. package/lib/generators/{webApplicationGenerator.js → uiBundleGenerator.js} +23 -22
  5. package/lib/generators/uiBundleGenerator.js.map +1 -0
  6. package/lib/i18n/i18n.d.ts +1 -1
  7. package/lib/i18n/i18n.js +1 -1
  8. package/lib/i18n/i18n.js.map +1 -1
  9. package/lib/templates/project/reactexternalapp/AGENT.md +152 -46
  10. package/lib/templates/project/reactexternalapp/CHANGELOG.md +366 -208
  11. package/lib/templates/project/reactexternalapp/README.md +16 -16
  12. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/CHANGELOG.md +1 -1
  13. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/README.md +1 -1
  14. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/eslint.config.js +13 -2
  15. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package.json +3 -3
  16. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/reactexternalapp.uibundle-meta.xml +8 -0
  17. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/scripts/get-graphql-schema.mjs +1 -1
  18. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +15 -6
  19. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/FilterContext.tsx +13 -3
  20. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +9 -5
  21. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +15 -8
  22. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +8 -7
  23. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/FilterFieldWrapper.tsx +33 -0
  24. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +4 -5
  25. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +118 -40
  26. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +24 -11
  27. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +9 -5
  28. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +29 -12
  29. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +34 -0
  30. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +10 -5
  31. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +4 -1
  32. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +24 -1
  33. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/context/AuthContext.tsx +2 -2
  34. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/hooks/useCountdownTimer.ts +1 -1
  35. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Profile.tsx +3 -3
  36. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Register.tsx +1 -1
  37. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/sessionTimeout/SessionTimeoutValidator.tsx +12 -18
  38. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +46 -0
  39. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +19 -0
  40. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +19 -0
  41. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/getAccountDetail.graphql +121 -0
  42. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +51 -0
  43. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +361 -0
  44. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +305 -0
  45. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +33 -11
  46. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +3 -3
  47. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/vite.config.ts +1 -1
  48. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppAuthUtils.cls → UIBundleAuthUtils.cls} +1 -1
  49. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppChangePassword.cls → UIBundleChangePassword.cls} +2 -2
  50. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppForgotPassword.cls → UIBundleForgotPassword.cls} +2 -2
  51. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppLogin.cls → UIBundleLogin.cls} +6 -6
  52. package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppRegistration.cls → UIBundleRegistration.cls} +10 -10
  53. package/lib/templates/project/reactexternalapp/_p_/_m_/networks/{reactexternalapp.network → reactexternalapp.network-meta.xml} +2 -2
  54. package/lib/templates/project/reactexternalapp/package.json +2 -2
  55. package/lib/templates/project/reactexternalapp/scripts/graphql-search.sh +4 -4
  56. package/lib/templates/project/reactexternalapp/scripts/setup-cli.mjs +51 -51
  57. package/lib/templates/project/reactexternalapp/scripts/sf-project-setup.mjs +16 -16
  58. package/lib/templates/project/reactinternalapp/AGENT.md +152 -46
  59. package/lib/templates/project/reactinternalapp/CHANGELOG.md +366 -208
  60. package/lib/templates/project/reactinternalapp/README.md +12 -12
  61. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/CHANGELOG.md +1 -1
  62. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/README.md +1 -1
  63. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/eslint.config.js +13 -2
  64. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package.json +4 -4
  65. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/reactinternalapp.uibundle-meta.xml +7 -0
  66. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/scripts/get-graphql-schema.mjs +1 -1
  67. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +15 -6
  68. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/FilterContext.tsx +13 -3
  69. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +9 -5
  70. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +15 -8
  71. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +8 -7
  72. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/FilterFieldWrapper.tsx +33 -0
  73. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +4 -5
  74. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +118 -40
  75. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +24 -11
  76. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +9 -5
  77. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +29 -12
  78. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +34 -0
  79. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +10 -5
  80. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +4 -1
  81. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +24 -1
  82. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +46 -0
  83. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +19 -0
  84. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +19 -0
  85. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/getAccountDetail.graphql +121 -0
  86. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +51 -0
  87. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/AgentforceConversationClient.tsx +5 -2
  88. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +361 -0
  89. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +305 -0
  90. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +33 -11
  91. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +12 -1
  92. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/types/conversation.ts +2 -0
  93. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/vite.config.ts +1 -1
  94. package/lib/templates/project/reactinternalapp/package.json +2 -2
  95. package/lib/templates/project/reactinternalapp/scripts/graphql-search.sh +4 -4
  96. package/lib/templates/project/reactinternalapp/scripts/setup-cli.mjs +51 -51
  97. package/lib/templates/project/reactinternalapp/scripts/sf-project-setup.mjs +16 -16
  98. package/lib/templates/{webapplication → uiBundles}/reactbasic/CHANGELOG.md +1 -1
  99. package/lib/templates/{webapplication → uiBundles}/reactbasic/README.md +10 -10
  100. package/lib/templates/{webapplication/reactbasic/_webapplication.webapplication-meta.xml → uiBundles/reactbasic/_uibundle.uibundle-meta.xml} +3 -3
  101. package/lib/templates/{webapplication → uiBundles}/reactbasic/eslint.config.js +13 -2
  102. package/lib/templates/{webapplication → uiBundles}/reactbasic/package.json +3 -3
  103. package/lib/templates/{webapplication → uiBundles}/reactbasic/scripts/get-graphql-schema.mjs +1 -1
  104. package/lib/templates/{webapplication → uiBundles}/reactbasic/vite.config.ts +1 -1
  105. package/lib/templates/uiBundles/webappbasic/README.md +15 -0
  106. package/lib/templates/{webapplication/webappbasic/_webapplication.webapplication-meta.xml → uiBundles/webappbasic/_uibundle.uibundle-meta.xml} +3 -3
  107. package/lib/tsconfig.tsbuildinfo +1 -1
  108. package/lib/utils/constants.d.ts +1 -0
  109. package/lib/utils/constants.js +2 -1
  110. package/lib/utils/constants.js.map +1 -1
  111. package/lib/utils/template-placeholders.d.ts +1 -1
  112. package/lib/utils/template-placeholders.js +11 -4
  113. package/lib/utils/template-placeholders.js.map +1 -1
  114. package/lib/utils/types.d.ts +5 -5
  115. package/lib/utils/types.js +3 -3
  116. package/lib/utils/types.js.map +1 -1
  117. package/lib/utils/{webappTemplateUtils.d.ts → uiBundleTemplateUtils.d.ts} +7 -5
  118. package/lib/utils/{webappTemplateUtils.js → uiBundleTemplateUtils.js} +15 -12
  119. package/lib/utils/uiBundleTemplateUtils.js.map +1 -0
  120. package/package.json +5 -5
  121. package/lib/generators/webApplicationGenerator.js.map +0 -1
  122. package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/reactexternalapp.webapplication-meta.xml +0 -7
  123. package/lib/templates/project/reactexternalapp/_r_/webapp-data.md +0 -353
  124. package/lib/templates/project/reactexternalapp/_r_/webapp-ui.md +0 -16
  125. package/lib/templates/project/reactexternalapp/package-lock.json +0 -9995
  126. package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/reactinternalapp.webapplication-meta.xml +0 -7
  127. package/lib/templates/project/reactinternalapp/_r_/webapp-data.md +0 -353
  128. package/lib/templates/project/reactinternalapp/_r_/webapp-ui.md +0 -16
  129. package/lib/templates/project/reactinternalapp/package-lock.json +0 -9995
  130. package/lib/templates/webapplication/reactbasic/e2e/app.spec.ts +0 -17
  131. package/lib/templates/webapplication/webappbasic/README.md +0 -15
  132. package/lib/utils/webappTemplateUtils.js.map +0 -1
  133. /package/lib/templates/project/reactexternalapp/_p_/_m_/_d_/_s_/{_a1_ → reactexternalapp1}/reactexternalapp1.digitalExperience-meta.xml +0 -0
  134. /package/lib/templates/project/reactexternalapp/_p_/_m_/_d_/_s_/{_a1_ → reactexternalapp1}/sfdc_cms__site/reactexternalapp1/_meta.json +0 -0
  135. /package/lib/templates/project/reactexternalapp/_p_/_m_/_d_/_s_/{_a1_ → reactexternalapp1}/sfdc_cms__site/reactexternalapp1/content.json +0 -0
  136. /package/lib/templates/project/reactexternalapp/_p_/_m_/{digitalExperienceConfigs/reactexternalapp1.digitalExperienceConfig → _dc_/reactexternalapp1.digitalExperienceConfig-meta.xml} +0 -0
  137. /package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/{webapplication.json → ui-bundle.json} +0 -0
  138. /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppAuthUtils.cls-meta.xml → UIBundleAuthUtils.cls-meta.xml} +0 -0
  139. /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppChangePassword.cls-meta.xml → UIBundleChangePassword.cls-meta.xml} +0 -0
  140. /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppForgotPassword.cls-meta.xml → UIBundleForgotPassword.cls-meta.xml} +0 -0
  141. /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppLogin.cls-meta.xml → UIBundleLogin.cls-meta.xml} +0 -0
  142. /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppRegistration.cls-meta.xml → UIBundleRegistration.cls-meta.xml} +0 -0
  143. /package/lib/templates/project/reactexternalapp/_p_/_m_/sites/{reactexternalapp.site → reactexternalapp.site-meta.xml} +0 -0
  144. /package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/{webapplication.json → ui-bundle.json} +0 -0
  145. /package/lib/templates/{webapplication → uiBundles}/reactbasic/.forceignore +0 -0
  146. /package/lib/templates/{webapplication → uiBundles}/reactbasic/.graphqlrc.yml +0 -0
  147. /package/lib/templates/{webapplication → uiBundles}/reactbasic/.prettierignore +0 -0
  148. /package/lib/templates/{webapplication → uiBundles}/reactbasic/.prettierrc +0 -0
  149. /package/lib/templates/{webapplication → uiBundles}/reactbasic/codegen.yml +0 -0
  150. /package/lib/templates/{webapplication → uiBundles}/reactbasic/components.json +0 -0
  151. /package/lib/templates/{webapplication → uiBundles}/reactbasic/index.html +0 -0
  152. /package/lib/templates/{webapplication → uiBundles}/reactbasic/playwright.config.ts +0 -0
  153. /package/lib/templates/{webapplication → uiBundles}/reactbasic/scripts/rewrite-e2e-assets.mjs +0 -0
  154. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/api/graphqlClient.ts +0 -0
  155. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/app.tsx +0 -0
  156. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/appLayout.tsx +0 -0
  157. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/book.svg +0 -0
  158. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/copy.svg +0 -0
  159. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/rocket.svg +0 -0
  160. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/star.svg +0 -0
  161. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/codey-1.png +0 -0
  162. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/codey-2.png +0 -0
  163. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/codey-3.png +0 -0
  164. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/vibe-codey.svg +0 -0
  165. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/alerts/status-alert.tsx +0 -0
  166. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/layouts/card-layout.tsx +0 -0
  167. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/alert.tsx +0 -0
  168. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/badge.tsx +0 -0
  169. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/breadcrumb.tsx +0 -0
  170. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/button.tsx +0 -0
  171. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/calendar.tsx +0 -0
  172. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/card.tsx +0 -0
  173. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/checkbox.tsx +0 -0
  174. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/collapsible.tsx +0 -0
  175. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/datePicker.tsx +0 -0
  176. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/dialog.tsx +0 -0
  177. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/field.tsx +0 -0
  178. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/index.ts +0 -0
  179. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/input.tsx +0 -0
  180. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/label.tsx +0 -0
  181. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/pagination.tsx +0 -0
  182. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/popover.tsx +0 -0
  183. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/select.tsx +0 -0
  184. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/separator.tsx +0 -0
  185. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/skeleton.tsx +0 -0
  186. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/sonner.tsx +0 -0
  187. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/spinner.tsx +0 -0
  188. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/table.tsx +0 -0
  189. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/tabs.tsx +0 -0
  190. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/lib/utils.ts +0 -0
  191. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/navigationMenu.tsx +0 -0
  192. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/pages/Home.tsx +0 -0
  193. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/pages/NotFound.tsx +0 -0
  194. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/router-utils.tsx +0 -0
  195. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/routes.tsx +0 -0
  196. /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/styles/global.css +0 -0
  197. /package/lib/templates/{webapplication → uiBundles}/reactbasic/tsconfig.json +0 -0
  198. /package/lib/templates/{webapplication → uiBundles}/reactbasic/tsconfig.node.json +0 -0
  199. /package/lib/templates/{webapplication/reactbasic/webapplication.json → uiBundles/reactbasic/ui-bundle.json} +0 -0
  200. /package/lib/templates/{webapplication → uiBundles}/reactbasic/vite-env.d.ts +0 -0
  201. /package/lib/templates/{webapplication → uiBundles}/reactbasic/vitest-env.d.ts +0 -0
  202. /package/lib/templates/{webapplication → uiBundles}/reactbasic/vitest.config.ts +0 -0
  203. /package/lib/templates/{webapplication → uiBundles}/reactbasic/vitest.setup.ts +0 -0
  204. /package/lib/templates/{webapplication → uiBundles}/webappbasic/src/index.html +0 -0
  205. /package/lib/templates/{webapplication/webappbasic/webapplication.json → uiBundles/webappbasic/ui-bundle.json} +0 -0
@@ -1,12 +1,34 @@
1
- export default function Home() {
2
- return (
3
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
4
- <div className="text-center">
5
- <h1 className="text-4xl font-bold text-gray-900 mb-4">Home</h1>
6
- <p className="text-lg text-gray-600 mb-8">
7
- Welcome to your React application.
8
- </p>
9
- </div>
10
- </div>
11
- );
1
+ import { useState } from "react";
2
+ import { useNavigate } from "react-router";
3
+ import { SearchBar } from "../features/object-search/components/SearchBar";
4
+ import { Button } from "../components/ui/button";
5
+
6
+ export default function HomePage() {
7
+ const navigate = useNavigate();
8
+ const [text, setText] = useState("");
9
+
10
+ const handleSubmit = (e: React.SyntheticEvent<HTMLFormElement>) => {
11
+ e.preventDefault();
12
+ const params = text ? `?q=${encodeURIComponent(text)}` : "";
13
+ navigate(`/accounts${params}`);
14
+ };
15
+
16
+ return (
17
+ <div className="max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
18
+ <div className="flex items-center gap-6 mb-6">
19
+ <h1 className="text-2xl font-bold">Account Search</h1>
20
+ <Button variant="outline" size="sm" onClick={() => navigate("/accounts")}>
21
+ Browse All Accounts
22
+ </Button>
23
+ </div>
24
+ <form onSubmit={handleSubmit} className="flex gap-2">
25
+ <SearchBar
26
+ placeholder="Search by name, phone, or industry..."
27
+ value={text}
28
+ handleChange={setText}
29
+ />
30
+ <Button type="submit">Search</Button>
31
+ </form>
32
+ </div>
33
+ );
12
34
  }
@@ -1,5 +1,5 @@
1
1
  import type { RouteObject } from 'react-router';
2
- import Home from './features/object-search/__examples__/pages/Home';
2
+ import Home from './pages/Home';
3
3
  import NotFound from './pages/NotFound';
4
4
  import Login from "./features/authentication/pages/Login";
5
5
  import Register from "./features/authentication/pages/Register";
@@ -10,8 +10,8 @@ import ChangePassword from "./features/authentication/pages/ChangePassword";
10
10
  import AuthenticationRoute from "./features/authentication/layouts/authenticationRouteLayout";
11
11
  import PrivateRoute from "./features/authentication/layouts/privateRouteLayout";
12
12
  import { ROUTES } from "./features/authentication/authenticationConfig";
13
- import AccountSearch from "./features/object-search/__examples__/pages/AccountSearch";
14
- import AccountObjectDetail from "./features/object-search/__examples__/pages/AccountObjectDetailPage";
13
+ import AccountSearch from "./pages/AccountSearch";
14
+ import AccountObjectDetail from "./pages/AccountObjectDetailPage";
15
15
  import AuthAppLayout from "./features/authentication/layouts/AuthAppLayout";
16
16
 
17
17
  export const routes: RouteObject[] = [
@@ -4,7 +4,7 @@ import react from '@vitejs/plugin-react';
4
4
  import path from 'path';
5
5
  import { resolve } from 'path';
6
6
  import tailwindcss from '@tailwindcss/vite';
7
- import salesforce from '@salesforce/vite-plugin-webapp-experimental';
7
+ import salesforce from '@salesforce/vite-plugin-ui-bundle';
8
8
  import codegen from 'vite-plugin-graphql-codegen';
9
9
 
10
10
  const schemaPath = resolve(__dirname, '../../../../../schema.graphql');
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Utility class for Web Application authentication REST endpoints.
3
3
  */
4
- public without sharing class WebAppAuthUtils {
4
+ public without sharing class UIBundleAuthUtils {
5
5
 
6
6
  /**
7
7
  * Exception for authentication errors with HTTP status code support.
@@ -10,7 +10,7 @@
10
10
  * can change their own password.
11
11
  */
12
12
  @RestResource(urlMapping='/auth/change-password')
13
- global with sharing class WebAppChangePassword {
13
+ global with sharing class UIBundleChangePassword {
14
14
 
15
15
  /**
16
16
  * Changes the password for the currently authenticated user.
@@ -36,7 +36,7 @@ global with sharing class WebAppChangePassword {
36
36
  }
37
37
 
38
38
  // Logs are only captured if a Trace Flag is active for the user
39
- WebAppAuthUtils.debugLog(ex, LoggingLevel.ERROR);
39
+ UIBundleAuthUtils.debugLog(ex, LoggingLevel.ERROR);
40
40
 
41
41
  RestContext.response.statusCode = 500;
42
42
  return new ErrorPasswordChangeResponse('Password change failed');
@@ -6,7 +6,7 @@
6
6
  * Sends a password reset email to the user's registered email address.
7
7
  */
8
8
  @RestResource(urlMapping='/auth/forgot-password')
9
- global with sharing class WebAppForgotPassword {
9
+ global with sharing class UIBundleForgotPassword {
10
10
 
11
11
  /**
12
12
  * Initiates the forgot password process by sending a reset email.
@@ -30,7 +30,7 @@ global with sharing class WebAppForgotPassword {
30
30
  return new SuccessForgotPasswordResponse();
31
31
  } catch (Exception ex) {
32
32
  // Logs are only captured if a Trace Flag is active for the user
33
- WebAppAuthUtils.debugLog(ex, LoggingLevel.ERROR);
33
+ UIBundleAuthUtils.debugLog(ex, LoggingLevel.ERROR);
34
34
 
35
35
  RestContext.response.statusCode = 500;
36
36
  return new ErrorForgotPasswordResponse('Could not send password reset link.');
@@ -8,7 +8,7 @@
8
8
  * @see https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_classes_sites.htm#apex_System_Site_login
9
9
  */
10
10
  @RestResource(urlMapping='/auth/login')
11
- global with sharing class WebAppLogin {
11
+ global with sharing class UIBundleLogin {
12
12
 
13
13
  /**
14
14
  * Authenticates a user and returns a redirect URL.
@@ -23,7 +23,7 @@ global with sharing class WebAppLogin {
23
23
  validateInput(email, password);
24
24
 
25
25
  String username = email.trim().toLowerCase();
26
- String sanitizedStartUrl = WebAppAuthUtils.getSanitizedStartUrl(startUrl, Site.getPathPrefix());
26
+ String sanitizedStartUrl = UIBundleAuthUtils.getSanitizedStartUrl(startUrl, Site.getPathPrefix());
27
27
 
28
28
  PageReference loginResult;
29
29
  try {
@@ -41,11 +41,11 @@ global with sharing class WebAppLogin {
41
41
  'Your login attempt has failed. Make sure the username and password are correct.'
42
42
  );
43
43
  }
44
- } catch (WebAppAuthUtils.AuthException ex) {
44
+ } catch (UIBundleAuthUtils.AuthException ex) {
45
45
  RestContext.response.statusCode = ex.statusCode;
46
46
  return new ErrorLoginResponse(ex.messages);
47
47
  } catch (Exception ex) {
48
- WebAppAuthUtils.debugLog(ex, LoggingLevel.ERROR);
48
+ UIBundleAuthUtils.debugLog(ex, LoggingLevel.ERROR);
49
49
  RestContext.response.statusCode = 500;
50
50
  return new ErrorLoginResponse('An unexpected error occurred. Please contact your administrator.');
51
51
  }
@@ -55,7 +55,7 @@ global with sharing class WebAppLogin {
55
55
  * Validates login input fields.
56
56
  * @param email The email to validate.
57
57
  * @param password The password to validate.
58
- * @throws WebAppAuthUtils.AuthException if validation fails.
58
+ * @throws UIBundleAuthUtils.AuthException if validation fails.
59
59
  */
60
60
  private static void validateInput(String email, String password) {
61
61
  List<String> errors = new List<String>();
@@ -66,7 +66,7 @@ global with sharing class WebAppLogin {
66
66
  errors.add('Password is required.');
67
67
  }
68
68
  if (!errors.isEmpty()) {
69
- throw new WebAppAuthUtils.AuthException(400, errors);
69
+ throw new UIBundleAuthUtils.AuthException(400, errors);
70
70
  }
71
71
  }
72
72
 
@@ -9,7 +9,7 @@
9
9
  * Security: Uses 'without sharing' to allow guest users to check for duplicate usernames.
10
10
  */
11
11
  @RestResource(urlMapping='/auth/register')
12
- global without sharing class WebAppRegistration {
12
+ global without sharing class UIBundleRegistration {
13
13
 
14
14
  /**
15
15
  * Registers a new external user and logs them in.
@@ -35,11 +35,11 @@ global without sharing class WebAppRegistration {
35
35
  validatePassword(u, request.password);
36
36
  createUser(u, request.password);
37
37
 
38
- String startUrl = WebAppAuthUtils.getSanitizedStartUrl(request.startUrl, Site.getPathPrefix());
38
+ String startUrl = UIBundleAuthUtils.getSanitizedStartUrl(request.startUrl, Site.getPathPrefix());
39
39
  PageReference pageRef = Site.login(request.email, request.password, startUrl);
40
40
 
41
41
  return new SuccessRegistrationResponse(pageRef?.getUrl());
42
- } catch (WebAppAuthUtils.AuthException ex) {
42
+ } catch (UIBundleAuthUtils.AuthException ex) {
43
43
  Database.rollback(sp);
44
44
  RestContext.response.statusCode = ex.statusCode;
45
45
  return new ErrorRegistrationResponse(ex.messages);
@@ -95,7 +95,7 @@ global without sharing class WebAppRegistration {
95
95
 
96
96
  /**
97
97
  * Trims fields and validates required fields and business rules.
98
- * @throws WebAppAuthUtils.AuthException if validation fails.
98
+ * @throws UIBundleAuthUtils.AuthException if validation fails.
99
99
  */
100
100
  public void validate() {
101
101
  email = email?.trim()?.toLowerCase();
@@ -112,7 +112,7 @@ global without sharing class WebAppRegistration {
112
112
  errors.add('A user with this email already exists.');
113
113
  }
114
114
  if (!errors.isEmpty()) {
115
- throw new WebAppAuthUtils.AuthException(400, errors);
115
+ throw new UIBundleAuthUtils.AuthException(400, errors);
116
116
  }
117
117
  }
118
118
  }
@@ -121,13 +121,13 @@ global without sharing class WebAppRegistration {
121
121
  * Validates password against org password policy.
122
122
  * @param user The user record.
123
123
  * @param password The password to validate.
124
- * @throws WebAppAuthUtils.AuthException if password does not meet requirements.
124
+ * @throws UIBundleAuthUtils.AuthException if password does not meet requirements.
125
125
  */
126
126
  private static void validatePassword(User user, String password) {
127
127
  try {
128
128
  Site.validatePassword(user, password, password);
129
129
  } catch (System.SecurityException ex) {
130
- throw new WebAppAuthUtils.AuthException(400, ex.getMessage());
130
+ throw new UIBundleAuthUtils.AuthException(400, ex.getMessage());
131
131
  }
132
132
  }
133
133
 
@@ -136,17 +136,17 @@ global without sharing class WebAppRegistration {
136
136
  * @param u The user record.
137
137
  * @param password The password for the new user.
138
138
  * @return The new user's ID.
139
- * @throws WebAppAuthUtils.AuthException if user creation fails.
139
+ * @throws UIBundleAuthUtils.AuthException if user creation fails.
140
140
  */
141
141
  private static String createUser(User u, String password) {
142
142
  String userId;
143
143
  try {
144
144
  userId = Site.createExternalUser(u, null, password);
145
145
  } catch (Site.ExternalUserCreateException ex) {
146
- throw new WebAppAuthUtils.AuthException(500, ex.getDisplayMessages());
146
+ throw new UIBundleAuthUtils.AuthException(500, ex.getDisplayMessages());
147
147
  }
148
148
  if (userId == null) {
149
- throw new WebAppAuthUtils.AuthException(500, 'Could not register new user.');
149
+ throw new UIBundleAuthUtils.AuthException(500, 'Could not register new user.');
150
150
  }
151
151
  return userId;
152
152
  }
@@ -5,7 +5,7 @@
5
5
  <changePasswordTemplate>unfiled$public/CommunityChangePasswordEmailTemplate</changePasswordTemplate>
6
6
  <communityRoles/>
7
7
  <disableReputationRecordConversations>true</disableReputationRecordConversations>
8
- <emailSenderAddress>trialorgfarmforu@salesforce.com.invalid.invalid</emailSenderAddress>
8
+ <emailSenderAddress>admin@company.com</emailSenderAddress>
9
9
  <emailSenderName>reactexternalapp</emailSenderName>
10
10
  <embeddedLoginEnabled>false</embeddedLoginEnabled>
11
11
  <enableApexCDNCaching>true</enableApexCDNCaching>
@@ -44,7 +44,7 @@
44
44
  <loginPageOverrideSetting>Designer</loginPageOverrideSetting>
45
45
  <selfRegProfilePageOverrideSetting>Designer</selfRegProfilePageOverrideSetting>
46
46
  </networkPageOverrides>
47
- <newSenderAddress>trialorgfarmforu@salesforce.com</newSenderAddress>
47
+ <newSenderAddress>admin@company.com</newSenderAddress>
48
48
  <picassoSite>reactexternalapp1</picassoSite>
49
49
  <selfRegistration>false</selfRegistration>
50
50
  <sendWelcomeEmail>true</sendWelcomeEmail>
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "@salesforce/webapp-template-base-sfdx-project-experimental",
3
- "version": "1.114.0",
2
+ "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
+ "version": "1.117.3",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
@@ -60,8 +60,8 @@ if [ ! -f "$SCHEMA" ]; then
60
60
  echo "ERROR: schema.graphql not found at $SCHEMA"
61
61
  echo " Make sure you are running from the SFDX project root, or pass the path explicitly:"
62
62
  echo " bash $0 --schema <path/to/schema.graphql> <EntityName>"
63
- echo " If the file is missing entirely, generate it from the webapp dir:"
64
- echo " cd force-app/main/default/webapplications/<app-name> && npm run graphql:schema"
63
+ echo " If the file is missing entirely, generate it from the ui-bundle dir:"
64
+ echo " cd force-app/main/default/uiBundles/<app-name> && npm run graphql:schema"
65
65
  exit 1
66
66
  fi
67
67
 
@@ -73,8 +73,8 @@ fi
73
73
 
74
74
  if [ ! -s "$SCHEMA" ]; then
75
75
  echo "ERROR: schema.graphql is empty at $SCHEMA"
76
- echo " Regenerate it from the webapp dir:"
77
- echo " cd force-app/main/default/webapplications/<app-name> && npm run graphql:schema"
76
+ echo " Regenerate it from the ui-bundle dir:"
77
+ echo " cd force-app/main/default/uiBundles/<app-name> && npm run graphql:schema"
78
78
  exit 1
79
79
  fi
80
80
 
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * One-command setup: login, deploy, optional permset/data, GraphQL schema/codegen, web app build.
3
+ * One-command setup: login, deploy, optional permset/data, GraphQL schema/codegen, UI bundle build.
4
4
  * Use this script to make setup easier for each app generated from this template.
5
5
  *
6
6
  * Usage:
7
7
  * node scripts/setup-cli.mjs --target-org <alias> # interactive step picker (all selected)
8
8
  * node scripts/setup-cli.mjs --target-org <alias> --yes # skip picker, run all steps
9
9
  * node scripts/setup-cli.mjs --target-org afv5 --skip-login
10
- * node scripts/setup-cli.mjs --target-org afv5 --skip-data --skip-webapp-build
11
- * node scripts/setup-cli.mjs --target-org myorg --webapp-name my-app
10
+ * node scripts/setup-cli.mjs --target-org afv5 --skip-data --skip-ui-bundle-build
11
+ * node scripts/setup-cli.mjs --target-org myorg --ui-bundle-name my-app
12
12
  *
13
13
  * Steps (in order):
14
14
  * 1. login — sf org login web only if org not already connected (skip with --skip-login)
15
- * 2. webapp — (all web apps) npm install && npm run build so dist exists for deploy (skip with --skip-webapp-build)
15
+ * 2. uiBundle — (all UI bundles) npm install && npm run build so dist exists for deploy (skip with --skip-ui-bundle-build)
16
16
  * 3. deploy — sf project deploy start --target-org <alias> (requires dist for entity deployment)
17
17
  * 4. permset — sf org assign permset for each *.permissionset-meta.xml (skip with --skip-permset; override via --permset-name)
18
18
  * 5. data — prepare unique fields + sf data import tree (skipped if no data dir/plan)
19
- * 6. graphql — (in webapp) npm run graphql:schema then npm run graphql:codegen
20
- * 7. dev — (in webapp) npm run dev — launch dev server (skip with --skip-dev)
19
+ * 6. graphql — (in UI bundle) npm run graphql:schema then npm run graphql:codegen
20
+ * 7. dev — (in UI bundle) npm run dev — launch dev server (skip with --skip-dev)
21
21
  */
22
22
 
23
23
  import { spawnSync } from 'node:child_process';
@@ -44,14 +44,14 @@ function resolveSfdxSource() {
44
44
  }
45
45
 
46
46
  const SFDX_SOURCE = resolveSfdxSource();
47
- const WEBAPPLICATIONS_DIR = resolve(SFDX_SOURCE, 'webapplications');
47
+ const UIBUNDLES_DIR = resolve(SFDX_SOURCE, 'uiBundles');
48
48
  const DATA_DIR = resolve(SFDX_SOURCE, 'data');
49
49
  const DATA_PLAN = resolve(SFDX_SOURCE, 'data/data-plan.json');
50
50
 
51
51
  function parseArgs() {
52
52
  const args = process.argv.slice(2);
53
53
  let targetOrg = null;
54
- let webappName = null;
54
+ let uiBundleName = null;
55
55
  /** If non-empty, only these names are assigned; otherwise all discovered from the project. */
56
56
  const permsetNamesExplicit = [];
57
57
  let yes = false;
@@ -61,14 +61,14 @@ function parseArgs() {
61
61
  skipPermset: false,
62
62
  skipData: false,
63
63
  skipGraphql: false,
64
- skipWebappBuild: false,
64
+ skipUIBundleBuild: false,
65
65
  skipDev: false,
66
66
  };
67
67
  for (let i = 0; i < args.length; i++) {
68
68
  if (args[i] === '--target-org' && args[i + 1]) {
69
69
  targetOrg = args[++i];
70
- } else if (args[i] === '--webapp-name' && args[i + 1]) {
71
- webappName = args[++i];
70
+ } else if (args[i] === '--ui-bundle-name' && args[i + 1]) {
71
+ uiBundleName = args[++i];
72
72
  } else if (args[i] === '--permset-name' && args[i + 1]) {
73
73
  permsetNamesExplicit.push(args[++i]);
74
74
  } else if (args[i] === '--skip-login') flags.skipLogin = true;
@@ -76,7 +76,7 @@ function parseArgs() {
76
76
  else if (args[i] === '--skip-permset') flags.skipPermset = true;
77
77
  else if (args[i] === '--skip-data') flags.skipData = true;
78
78
  else if (args[i] === '--skip-graphql') flags.skipGraphql = true;
79
- else if (args[i] === '--skip-webapp-build') flags.skipWebappBuild = true;
79
+ else if (args[i] === '--skip-ui-bundle-build') flags.skipUIBundleBuild = true;
80
80
  else if (args[i] === '--skip-dev') flags.skipDev = true;
81
81
  else if (args[i] === '--yes' || args[i] === '-y') yes = true;
82
82
  else if (args[i] === '--help' || args[i] === '-h') {
@@ -90,14 +90,14 @@ Required:
90
90
  --target-org <alias> Target Salesforce org alias (e.g. myorg)
91
91
 
92
92
  Options:
93
- --webapp-name <name> Web app folder name under webapplications/ (default: auto-detect)
93
+ --ui-bundle-name <name> UI bundle folder name under uiBundles/ (default: auto-detect)
94
94
  --permset-name <name> Assign only this permission set (repeatable). Default: all sets under permissionsets/
95
95
  --skip-login Skip login step (login is auto-skipped if org is already connected)
96
96
  --skip-deploy Do not deploy metadata
97
97
  --skip-permset Do not assign permission set
98
98
  --skip-data Do not prepare data or run data import
99
99
  --skip-graphql Do not fetch schema or run GraphQL codegen
100
- --skip-webapp-build Do not npm install / build the web application
100
+ --skip-ui-bundle-build Do not npm install / build the UI bundle
101
101
  --skip-dev Do not launch the dev server at the end
102
102
  -y, --yes Skip interactive step picker; run all enabled steps immediately
103
103
  -h, --help Show this help
@@ -109,35 +109,35 @@ Options:
109
109
  console.error('Error: --target-org <alias> is required.');
110
110
  process.exit(1);
111
111
  }
112
- return { targetOrg, webappName, permsetNamesExplicit, yes, ...flags };
112
+ return { targetOrg, uiBundleName, permsetNamesExplicit, yes, ...flags };
113
113
  }
114
114
 
115
- function discoverAllWebappDirs(webappName) {
116
- if (!existsSync(WEBAPPLICATIONS_DIR)) {
117
- console.error(`Error: webapplications directory not found: ${WEBAPPLICATIONS_DIR}`);
115
+ function discoverAllUIBundleDirs(uiBundleName) {
116
+ if (!existsSync(UIBUNDLES_DIR)) {
117
+ console.error(`Error: uiBundles directory not found: ${UIBUNDLES_DIR}`);
118
118
  process.exit(1);
119
119
  }
120
- const entries = readdirSync(WEBAPPLICATIONS_DIR, { withFileTypes: true });
120
+ const entries = readdirSync(UIBUNDLES_DIR, { withFileTypes: true });
121
121
  const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.'));
122
122
  if (dirs.length === 0) {
123
- console.error(`Error: No web app folder found under ${WEBAPPLICATIONS_DIR}`);
123
+ console.error(`Error: No UI bundle folder found under ${UIBUNDLES_DIR}`);
124
124
  process.exit(1);
125
125
  }
126
- if (webappName) {
127
- const requested = dirs.find((d) => d.name === webappName);
126
+ if (uiBundleName) {
127
+ const requested = dirs.find((d) => d.name === uiBundleName);
128
128
  if (!requested) {
129
- console.error(`Error: Web app directory not found: ${webappName}`);
129
+ console.error(`Error: UI bundle directory not found: ${uiBundleName}`);
130
130
  process.exit(1);
131
131
  }
132
- return [resolve(WEBAPPLICATIONS_DIR, requested.name)];
132
+ return [resolve(UIBUNDLES_DIR, requested.name)];
133
133
  }
134
- return dirs.map((d) => resolve(WEBAPPLICATIONS_DIR, d.name));
134
+ return dirs.map((d) => resolve(UIBUNDLES_DIR, d.name));
135
135
  }
136
136
 
137
- function discoverWebappDir(webappName) {
138
- const all = discoverAllWebappDirs(webappName);
139
- if (all.length > 1 && !webappName) {
140
- console.log(`Multiple web apps found; using first: ${all[0].split(/[/\\]/).pop()}`);
137
+ function discoverUIBundleDir(uiBundleName) {
138
+ const all = discoverAllUIBundleDirs(uiBundleName);
139
+ if (all.length > 1 && !uiBundleName) {
140
+ console.log(`Multiple UI bundles found; using first: ${all[0].split(/[/\\]/).pop()}`);
141
141
  }
142
142
  return all[0];
143
143
  }
@@ -294,7 +294,7 @@ function run(name, cmd, args, opts = {}) {
294
294
  async function main() {
295
295
  const {
296
296
  targetOrg,
297
- webappName,
297
+ uiBundleName,
298
298
  permsetNamesExplicit,
299
299
  yes,
300
300
  skipLogin: argSkipLogin,
@@ -302,7 +302,7 @@ async function main() {
302
302
  skipPermset: argSkipPermset,
303
303
  skipData: argSkipData,
304
304
  skipGraphql: argSkipGraphql,
305
- skipWebappBuild: argSkipWebappBuild,
305
+ skipUIBundleBuild: argSkipUIBundleBuild,
306
306
  skipDev: argSkipDev,
307
307
  } = parseArgs();
308
308
 
@@ -319,7 +319,7 @@ async function main() {
319
319
 
320
320
  const stepDefs = [
321
321
  { key: 'login', label: 'Login — org authentication', enabled: !argSkipLogin, available: true },
322
- { key: 'webappBuild', label: 'Webapp Build — npm install + build (pre-deploy)', enabled: !argSkipWebappBuild, available: true },
322
+ { key: 'uiBundleBuild', label: 'UI Bundle Build — npm install + build (pre-deploy)', enabled: !argSkipUIBundleBuild, available: true },
323
323
  { key: 'deploy', label: 'Deploy — sf project deploy start', enabled: !argSkipDeploy, available: true },
324
324
  { key: 'permset', label: permsetStepLabel, enabled: !argSkipPermset, available: true },
325
325
  { key: 'data', label: 'Data — delete + import records via Apex', enabled: !argSkipData && hasDataPlan, available: hasDataPlan },
@@ -334,26 +334,26 @@ async function main() {
334
334
  });
335
335
 
336
336
  const skipLogin = !on.login;
337
- const skipWebappBuild = !on.webappBuild;
337
+ const skipUIBundleBuild = !on.uiBundleBuild;
338
338
  const skipDeploy = !on.deploy;
339
339
  const skipPermset = !on.permset;
340
340
  const skipData = !on.data;
341
341
  const skipGraphql = !on.graphql;
342
342
  const skipDev = !on.dev;
343
343
 
344
- const needsWebapp = !skipWebappBuild || !skipGraphql || !skipDev;
345
- const webappDir = needsWebapp ? discoverWebappDir(webappName) : null;
344
+ const needsUIBundle = !skipUIBundleBuild || !skipGraphql || !skipDev;
345
+ const uiBundleDir = needsUIBundle ? discoverUIBundleDir(uiBundleName) : null;
346
346
  const doData = !skipData;
347
347
 
348
- console.log('Setup — target org:', targetOrg, '| web app:', webappDir ?? '(none)');
348
+ console.log('Setup — target org:', targetOrg, '| UI bundle:', uiBundleDir ?? '(none)');
349
349
  console.log(
350
- 'Steps: login=%s deploy=%s permset=%s data=%s graphql=%s webapp=%s dev=%s',
350
+ 'Steps: login=%s deploy=%s permset=%s data=%s graphql=%s uiBundle=%s dev=%s',
351
351
  !skipLogin,
352
352
  !skipDeploy,
353
353
  !skipPermset,
354
354
  doData,
355
355
  !skipGraphql,
356
- !skipWebappBuild,
356
+ !skipUIBundleBuild,
357
357
  !skipDev
358
358
  );
359
359
 
@@ -366,13 +366,13 @@ async function main() {
366
366
  }
367
367
  }
368
368
 
369
- // Build all web apps before deploy so dist exists for entity deployment
370
- if (!skipDeploy && !skipWebappBuild) {
371
- const allWebappDirs = discoverAllWebappDirs(webappName);
372
- for (const dir of allWebappDirs) {
369
+ // Build all UI Bundles before deploy so dist exists for entity deployment
370
+ if (!skipDeploy && !skipUIBundleBuild) {
371
+ const allUIBundleDirs = discoverAllUIBundleDirs(uiBundleName);
372
+ for (const dir of allUIBundleDirs) {
373
373
  const name = dir.split(/[/\\]/).pop();
374
- run(`Web app install (${name})`, 'npm', ['install'], { cwd: dir });
375
- run(`Web app build (${name})`, 'npm', ['run', 'build'], { cwd: dir });
374
+ run(`UI Bundle install (${name})`, 'npm', ['install'], { cwd: dir });
375
+ run(`UI Bundle build (${name})`, 'npm', ['run', 'build'], { cwd: dir });
376
376
  }
377
377
  }
378
378
 
@@ -535,25 +535,25 @@ async function main() {
535
535
  if (existsSync(tmpApex)) unlinkSync(tmpApex);
536
536
  }
537
537
 
538
- if (!skipGraphql || !skipWebappBuild) {
539
- run('Web app npm install', 'npm', ['install'], { cwd: webappDir });
538
+ if (!skipGraphql || !skipUIBundleBuild) {
539
+ run('UI Bundle npm install', 'npm', ['install'], { cwd: uiBundleDir });
540
540
  }
541
541
 
542
542
  if (!skipGraphql) {
543
543
  run('Set default org for schema', 'sf', ['config', 'set', 'target-org', targetOrg, '--global']);
544
- run('GraphQL schema (introspect)', 'npm', ['run', 'graphql:schema'], { cwd: webappDir });
545
- run('GraphQL codegen', 'npm', ['run', 'graphql:codegen'], { cwd: webappDir });
544
+ run('GraphQL schema (introspect)', 'npm', ['run', 'graphql:schema'], { cwd: uiBundleDir });
545
+ run('GraphQL codegen', 'npm', ['run', 'graphql:codegen'], { cwd: uiBundleDir });
546
546
  }
547
547
 
548
- if (!skipWebappBuild) {
549
- run('Web app build', 'npm', ['run', 'build'], { cwd: webappDir });
548
+ if (!skipUIBundleBuild) {
549
+ run('UI Bundle build', 'npm', ['run', 'build'], { cwd: uiBundleDir });
550
550
  }
551
551
 
552
552
  console.log('\n--- Setup complete ---');
553
553
 
554
554
  if (!skipDev) {
555
555
  console.log('\n--- Launching dev server (Ctrl+C to stop) ---\n');
556
- run('Dev server', 'npm', ['run', 'dev'], { cwd: webappDir });
556
+ run('Dev server', 'npm', ['run', 'dev'], { cwd: uiBundleDir });
557
557
  }
558
558
  }
559
559
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * Run from SFDX project root: install dependencies, build, and launch the dev server
4
- * for the web app in force-app/main/default/webapplications/.
4
+ * for the UI bundle in force-app/main/default/uiBundles/.
5
5
  *
6
6
  * Usage: npm run sf-project-setup
7
7
  * (from the directory that contains force-app/ and sfdx-project.json)
@@ -15,7 +15,7 @@ import { readdirSync, existsSync, readFileSync } from 'node:fs';
15
15
  const __dirname = dirname(fileURLToPath(import.meta.url));
16
16
  const ROOT = resolve(__dirname, '..');
17
17
 
18
- function resolveWebapplicationsDir() {
18
+ function resolveUIBundlesDir() {
19
19
  const sfdxPath = resolve(ROOT, 'sfdx-project.json');
20
20
  if (!existsSync(sfdxPath)) {
21
21
  console.error('Error: sfdx-project.json not found at project root.');
@@ -27,25 +27,25 @@ function resolveWebapplicationsDir() {
27
27
  console.error('Error: No packageDirectories[].path found in sfdx-project.json.');
28
28
  process.exit(1);
29
29
  }
30
- return resolve(ROOT, pkgDir, 'main', 'default', 'webapplications');
30
+ return resolve(ROOT, pkgDir, 'main', 'default', 'uiBundles');
31
31
  }
32
32
 
33
- function discoverWebappDir() {
34
- const webapplicationsDir = resolveWebapplicationsDir();
35
- if (!existsSync(webapplicationsDir)) {
36
- console.error(`Error: webapplications directory not found: ${webapplicationsDir}`);
33
+ function discoverUIBundleDir() {
34
+ const uiBundlesDir = resolveUIBundlesDir();
35
+ if (!existsSync(uiBundlesDir)) {
36
+ console.error(`Error: uiBundles directory not found: ${uiBundlesDir}`);
37
37
  process.exit(1);
38
38
  }
39
- const entries = readdirSync(webapplicationsDir, { withFileTypes: true });
39
+ const entries = readdirSync(uiBundlesDir, { withFileTypes: true });
40
40
  const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.'));
41
41
  if (dirs.length === 0) {
42
- console.error(`Error: No web app folder found under ${webapplicationsDir}`);
42
+ console.error(`Error: No UI bundle folder found under ${uiBundlesDir}`);
43
43
  process.exit(1);
44
44
  }
45
45
  if (dirs.length > 1) {
46
- console.log(`Multiple web apps found; using first: ${dirs[0].name}`);
46
+ console.log(`Multiple UI bundles found; using first: ${dirs[0].name}`);
47
47
  }
48
- return resolve(webapplicationsDir, dirs[0].name);
48
+ return resolve(uiBundlesDir, dirs[0].name);
49
49
  }
50
50
 
51
51
  function run(label, cmd, args, opts) {
@@ -56,11 +56,11 @@ function run(label, cmd, args, opts) {
56
56
  }
57
57
  }
58
58
 
59
- const webappDir = discoverWebappDir();
59
+ const uiBundleDir = discoverUIBundleDir();
60
60
  console.log('SFDX project root:', ROOT);
61
- console.log('Web app directory:', webappDir);
61
+ console.log('UI bundle directory:', uiBundleDir);
62
62
 
63
- run('npm install', 'npm', ['install'], { cwd: webappDir });
64
- run('npm run build', 'npm', ['run', 'build'], { cwd: webappDir });
63
+ run('npm install', 'npm', ['install', '--registry', 'https://registry.npmjs.org/'], { cwd: uiBundleDir });
64
+ run('npm run build', 'npm', ['run', 'build'], { cwd: uiBundleDir });
65
65
  console.log('\n--- Launching dev server (Ctrl+C to stop) ---\n');
66
- run('npm run dev', 'npm', ['run', 'dev'], { cwd: webappDir });
66
+ run('npm run dev', 'npm', ['run', 'dev'], { cwd: uiBundleDir });