@salesforce/templates 66.13.9 → 66.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/generators/analyticsTemplateGenerator.js +1 -1
- package/lib/generators/analyticsTemplateGenerator.js.map +1 -1
- package/lib/generators/apexClassGenerator.js +1 -1
- package/lib/generators/apexClassGenerator.js.map +1 -1
- package/lib/generators/apexTriggerGenerator.js +1 -1
- package/lib/generators/apexTriggerGenerator.js.map +1 -1
- package/lib/generators/baseGenerator.js +3 -3
- package/lib/generators/baseGenerator.js.map +1 -1
- package/lib/generators/digitalExperienceSiteGenerator.js +2 -2
- package/lib/generators/digitalExperienceSiteGenerator.js.map +1 -1
- package/lib/generators/flexipageGenerator.js +2 -2
- package/lib/generators/flexipageGenerator.js.map +1 -1
- package/lib/generators/lightningAppGenerator.js +1 -1
- package/lib/generators/lightningAppGenerator.js.map +1 -1
- package/lib/generators/lightningComponentGenerator.js +1 -1
- package/lib/generators/lightningComponentGenerator.js.map +1 -1
- package/lib/generators/lightningEventGenerator.js +1 -1
- package/lib/generators/lightningEventGenerator.js.map +1 -1
- package/lib/generators/lightningInterfaceGenerator.js +1 -1
- package/lib/generators/lightningInterfaceGenerator.js.map +1 -1
- package/lib/generators/lightningTestGenerator.js +1 -1
- package/lib/generators/lightningTestGenerator.js.map +1 -1
- package/lib/generators/projectGenerator.js +1 -1
- package/lib/generators/projectGenerator.js.map +1 -1
- package/lib/generators/staticResourceGenerator.js +1 -1
- package/lib/generators/staticResourceGenerator.js.map +1 -1
- package/lib/generators/uiBundleGenerator.js +1 -1
- package/lib/generators/uiBundleGenerator.js.map +1 -1
- package/lib/generators/uiEmbeddingGenerator.js +7 -7
- package/lib/generators/uiEmbeddingGenerator.js.map +1 -1
- package/lib/generators/visualforceComponentGenerator.js +1 -1
- package/lib/generators/visualforceComponentGenerator.js.map +1 -1
- package/lib/generators/visualforcePageGenerator.js +1 -1
- package/lib/generators/visualforcePageGenerator.js.map +1 -1
- package/lib/i18n/i18n.d.ts +2 -2
- package/lib/i18n/i18n.js +2 -2
- package/lib/i18n/i18n.js.map +1 -1
- package/lib/i18n/localization.js +2 -1
- package/lib/i18n/localization.js.map +1 -1
- package/lib/service/gitRepoUtils.js +5 -5
- package/lib/service/gitRepoUtils.js.map +1 -1
- package/lib/templates/project/angularextapp/CHANGELOG.md +429 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package-lock.json +4076 -9105
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/package.json +3 -3
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/__examples__/html-middleware-site-example.ts +41 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/__examples__/language-switcher-example.ts +41 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/build-language-url.ts +158 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/index.ts +28 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/language-switcher.html +22 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/language-switcher.ts +110 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/_f_/_ls_/languages.ts +46 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth/auth.service.ts +53 -21
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/components/ui/icon/icon.ts +6 -0
- package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/types/sf-globals.d.ts +14 -0
- package/lib/templates/project/angularextapp/package.json +1 -1
- package/lib/templates/project/angularextapp/scripts/org-setup-config-schema.mjs +14 -2
- package/lib/templates/project/angularextapp/scripts/org-setup-dev.mjs +27 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-url.mjs +108 -0
- package/lib/templates/project/angularextapp/scripts/org-setup-xml.mjs +96 -0
- package/lib/templates/project/angularextapp/scripts/org-setup.mjs +195 -3
- package/lib/templates/project/angularintapp/CHANGELOG.md +429 -0
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package-lock.json +4083 -9112
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/package.json +4 -4
- package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/components/ui/icon/icon.ts +6 -0
- package/lib/templates/project/angularintapp/package.json +1 -1
- package/lib/templates/project/angularintapp/scripts/org-setup-config-schema.mjs +14 -2
- package/lib/templates/project/angularintapp/scripts/org-setup-dev.mjs +27 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-url.mjs +108 -0
- package/lib/templates/project/angularintapp/scripts/org-setup-xml.mjs +96 -0
- package/lib/templates/project/angularintapp/scripts/org-setup.mjs +195 -3
- package/lib/templates/project/reactexternalapp/CHANGELOG.md +533 -0
- package/lib/templates/project/reactexternalapp/README.md +2 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package-lock.json +888 -640
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package.json +6 -4
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/patches/aria-hidden+1.2.6.patch +45 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Login.tsx +3 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Register.tsx +3 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +9 -6
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +14 -3
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +7 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +1 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +17 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +2 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +16 -4
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +1 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +27 -4
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +7 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +12 -7
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +24 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/appLayout.tsx +42 -7
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/components/ObjectBreadcrumb.tsx +1 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +34 -47
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +3 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/utils/accountFields.ts +1 -14
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleAuthUtils_Test.cls +141 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleAuthUtils_Test.cls-meta.xml +5 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls +23 -11
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls +80 -0
- package/lib/templates/project/reactexternalapp/package.json +1 -1
- package/lib/templates/project/reactexternalapp/scripts/org-setup-config-schema.mjs +14 -2
- package/lib/templates/project/reactexternalapp/scripts/org-setup-dev.mjs +27 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup-url.mjs +108 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup-xml.mjs +96 -0
- package/lib/templates/project/reactexternalapp/scripts/org-setup.mjs +195 -3
- package/lib/templates/project/reactinternalapp/CHANGELOG.md +533 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package-lock.json +892 -644
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package.json +7 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/patches/aria-hidden+1.2.6.patch +45 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/api/searchableContentTypesService.ts +9 -6
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/cmsQueryFragment.ts +14 -3
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/contentTypeUtils.ts +7 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/index.ts +1 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/cms/searchChannel.ts +17 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/adapters/types.ts +2 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/MergedSearchResults.tsx +16 -4
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SearchResults.tsx +1 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/SourceSection.tsx +27 -4
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/components/filters/DefaultFilterPanel.tsx +7 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/hooks/useSearch.ts +12 -7
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/utils/filterUtils.ts +24 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/appLayout.tsx +41 -7
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/ObjectBreadcrumb.tsx +1 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +40 -50
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +7 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/utils/accountFields.ts +1 -14
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/tsconfig.tsbuildinfo +1 -1
- package/lib/templates/project/reactinternalapp/package.json +1 -1
- package/lib/templates/project/reactinternalapp/scripts/org-setup-config-schema.mjs +14 -2
- package/lib/templates/project/reactinternalapp/scripts/org-setup-dev.mjs +27 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup-url.mjs +108 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup-xml.mjs +96 -0
- package/lib/templates/project/reactinternalapp/scripts/org-setup.mjs +195 -3
- package/lib/templates/uiBundles/angularbasic/package-lock.json +4076 -9105
- package/lib/templates/uiBundles/angularbasic/package.json +3 -3
- package/lib/templates/uiBundles/angularbasic/src/app/components/ui/icon/icon.ts +6 -0
- package/lib/templates/uiBundles/reactbasic/package-lock.json +885 -637
- package/lib/templates/uiBundles/reactbasic/package.json +6 -4
- package/lib/templates/uiBundles/reactbasic/patches/aria-hidden+1.2.6.patch +45 -0
- package/lib/templates/uiembedding/default/default.html +1 -1
- package/lib/utils/constants.js +2 -1
- package/lib/utils/constants.js.map +1 -1
- package/lib/utils/createUtil.js +3 -2
- package/lib/utils/createUtil.js.map +1 -1
- package/lib/utils/template-placeholders.d.ts +1 -1
- package/lib/utils/template-placeholders.js +3 -1
- package/lib/utils/template-placeholders.js.map +1 -1
- package/lib/utils/types.d.ts +1 -1
- package/lib/utils/types.js +17 -16
- package/lib/utils/types.js.map +1 -1
- package/lib/utils/uiBundleTemplateUtils.js +4 -4
- package/lib/utils/uiBundleTemplateUtils.js.map +1 -1
- package/package.json +23 -23
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +0 -246
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/search/README.md +0 -246
- package/lib/tsconfig.tsbuildinfo +0 -1
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/api/object-search.service.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/object-search-state.service.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/debounce.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/field-utils.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/filter-utils.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/index.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/sort-utils.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth/auth.guard.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-form/auth-form.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-form/auth-form.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-layout/auth-layout.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/auth-layout/auth-layout.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/card-layout/card-layout.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/card-layout/card-layout.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/config/authentication.config.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/footer-link/footer-link.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/footer-link/footer-link.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/menu/auth-menu/auth-menu.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/menu/auth-menu/auth-menu.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/reactive-form-page.base.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/session/session.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/session/session.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/status-alert/status-alert.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/status-alert/status-alert.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/submit-button/submit-button.html +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/submit-button/submit-button.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/auth-helpers.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/auth-validators.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/helpers.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/session-time-servlet.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/session-timeout.config.ts +0 -0
- /package/lib/templates/project/angularextapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/authentication/utils/session-timeout.service.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/api/object-search.service.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/breadcrumb/breadcrumb.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/active-filters.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/date-range-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/filter-field-wrapper.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/multi-select-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/numeric-range-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/search-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/select-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/filters/text-filter.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/object-search-state.service.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/pagination/pagination.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/search-bar/search-bar.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/sort-control/sort-control.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/debounce.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/field-utils.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/filter-utils.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/index.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features/object-search → _f_/_os_}/utils/sort-utils.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/agentforce/agentforce-embed.service.ts +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/agentforce/conversation.html +0 -0
- /package/lib/templates/project/angularintapp/_p_/_m_/_w_/_a_/src/app/{features → _f_}/agentforce/conversation.ts +0 -0
package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx
CHANGED
|
@@ -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
|
|
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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
</
|
|
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
|
|
141
|
-
const
|
|
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
|
-
<
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
<
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
+
}
|
package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig.cls
CHANGED
|
@@ -22,17 +22,9 @@ global with sharing class UIBundleSocialLoginConfig {
|
|
|
22
22
|
@HttpGet
|
|
23
23
|
global static SocialLoginConfigResponse getConfig() {
|
|
24
24
|
try {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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;
|
package/lib/templates/project/reactexternalapp/_p_/_m_/classes/UIBundleSocialLoginConfig_Test.cls
CHANGED
|
@@ -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
|
}
|
|
@@ -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
|
|
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);
|