@salesforce/templates 66.6.2 → 66.7.1
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/projectGenerator.js +4 -4
- package/lib/generators/projectGenerator.js.map +1 -1
- package/lib/generators/{webApplicationGenerator.d.ts → uiBundleGenerator.d.ts} +2 -2
- package/lib/generators/{webApplicationGenerator.js → uiBundleGenerator.js} +23 -22
- package/lib/generators/uiBundleGenerator.js.map +1 -0
- package/lib/i18n/i18n.d.ts +1 -1
- package/lib/i18n/i18n.js +1 -1
- package/lib/i18n/i18n.js.map +1 -1
- package/lib/templates/project/reactexternalapp/AGENT.md +152 -46
- package/lib/templates/project/reactexternalapp/CHANGELOG.md +366 -208
- package/lib/templates/project/reactexternalapp/README.md +16 -16
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/CHANGELOG.md +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/README.md +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/eslint.config.js +13 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/package.json +3 -3
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/reactexternalapp.uibundle-meta.xml +8 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/scripts/get-graphql-schema.mjs +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +15 -6
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/FilterContext.tsx +13 -3
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +9 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +15 -8
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +8 -7
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/FilterFieldWrapper.tsx +33 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +4 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +118 -40
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +24 -11
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +9 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +29 -12
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +34 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +10 -5
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +4 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +24 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/context/AuthContext.tsx +2 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/hooks/useCountdownTimer.ts +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Profile.tsx +3 -3
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/pages/Register.tsx +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/_f_/authentication/sessionTimeout/SessionTimeoutValidator.tsx +12 -18
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +46 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +19 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +19 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/getAccountDetail.graphql +121 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +51 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +361 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +305 -0
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +33 -11
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +3 -3
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/vite.config.ts +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppAuthUtils.cls → UIBundleAuthUtils.cls} +1 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppChangePassword.cls → UIBundleChangePassword.cls} +2 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppForgotPassword.cls → UIBundleForgotPassword.cls} +2 -2
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppLogin.cls → UIBundleLogin.cls} +6 -6
- package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppRegistration.cls → UIBundleRegistration.cls} +10 -10
- package/lib/templates/project/reactexternalapp/_p_/_m_/networks/{reactexternalapp.network → reactexternalapp.network-meta.xml} +2 -2
- package/lib/templates/project/reactexternalapp/package.json +2 -2
- package/lib/templates/project/reactexternalapp/scripts/graphql-search.sh +4 -4
- package/lib/templates/project/reactexternalapp/scripts/setup-cli.mjs +51 -51
- package/lib/templates/project/reactexternalapp/scripts/sf-project-setup.mjs +16 -16
- package/lib/templates/project/reactinternalapp/AGENT.md +152 -46
- package/lib/templates/project/reactinternalapp/CHANGELOG.md +366 -208
- package/lib/templates/project/reactinternalapp/README.md +12 -12
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/CHANGELOG.md +1 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/README.md +1 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/eslint.config.js +13 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/package.json +4 -4
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/reactinternalapp.uibundle-meta.xml +7 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/scripts/get-graphql-schema.mjs +1 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/_ex_/pages/AccountSearch.tsx +15 -6
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/FilterContext.tsx +13 -3
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/BooleanFilter.tsx +9 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateFilter.tsx +15 -8
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/DateRangeFilter.tsx +8 -7
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/FilterFieldWrapper.tsx +33 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/MultiSelectFilter.tsx +4 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/NumericRangeFilter.tsx +118 -40
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SearchFilter.tsx +24 -11
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/SelectFilter.tsx +9 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/components/filters/TextFilter.tsx +29 -12
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useDebouncedCallback.ts +34 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/hooks/useObjectSearchParams.ts +10 -5
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/debounce.ts +4 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/_f_/_os_/utils/filterUtils.ts +24 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/accountSearchService.ts +46 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountIndustries.graphql +19 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/distinctAccountTypes.graphql +19 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/getAccountDetail.graphql +121 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/api/account/query/searchAccounts.graphql +51 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/components/AgentforceConversationClient.tsx +5 -2
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountObjectDetailPage.tsx +361 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/AccountSearch.tsx +305 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/pages/Home.tsx +33 -11
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/routes.tsx +12 -1
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/src/types/conversation.ts +2 -0
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/vite.config.ts +1 -1
- package/lib/templates/project/reactinternalapp/package.json +2 -2
- package/lib/templates/project/reactinternalapp/scripts/graphql-search.sh +4 -4
- package/lib/templates/project/reactinternalapp/scripts/setup-cli.mjs +51 -51
- package/lib/templates/project/reactinternalapp/scripts/sf-project-setup.mjs +16 -16
- package/lib/templates/{webapplication → uiBundles}/reactbasic/CHANGELOG.md +1 -1
- package/lib/templates/{webapplication → uiBundles}/reactbasic/README.md +10 -10
- package/lib/templates/{webapplication/reactbasic/_webapplication.webapplication-meta.xml → uiBundles/reactbasic/_uibundle.uibundle-meta.xml} +3 -3
- package/lib/templates/{webapplication → uiBundles}/reactbasic/eslint.config.js +13 -2
- package/lib/templates/{webapplication → uiBundles}/reactbasic/package.json +3 -3
- package/lib/templates/{webapplication → uiBundles}/reactbasic/scripts/get-graphql-schema.mjs +1 -1
- package/lib/templates/{webapplication → uiBundles}/reactbasic/vite.config.ts +1 -1
- package/lib/templates/uiBundles/webappbasic/README.md +15 -0
- package/lib/templates/{webapplication/webappbasic/_webapplication.webapplication-meta.xml → uiBundles/webappbasic/_uibundle.uibundle-meta.xml} +3 -3
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/constants.d.ts +1 -0
- package/lib/utils/constants.js +2 -1
- package/lib/utils/constants.js.map +1 -1
- package/lib/utils/template-placeholders.d.ts +1 -1
- package/lib/utils/template-placeholders.js +11 -4
- package/lib/utils/template-placeholders.js.map +1 -1
- package/lib/utils/types.d.ts +5 -5
- package/lib/utils/types.js +3 -3
- package/lib/utils/types.js.map +1 -1
- package/lib/utils/{webappTemplateUtils.d.ts → uiBundleTemplateUtils.d.ts} +7 -5
- package/lib/utils/{webappTemplateUtils.js → uiBundleTemplateUtils.js} +11 -8
- package/lib/utils/uiBundleTemplateUtils.js.map +1 -0
- package/package.json +5 -5
- package/lib/generators/webApplicationGenerator.js.map +0 -1
- package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/reactexternalapp.webapplication-meta.xml +0 -7
- package/lib/templates/project/reactexternalapp/_r_/webapp-data.md +0 -353
- package/lib/templates/project/reactexternalapp/_r_/webapp-ui.md +0 -16
- package/lib/templates/project/reactexternalapp/package-lock.json +0 -9995
- package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/reactinternalapp.webapplication-meta.xml +0 -7
- package/lib/templates/project/reactinternalapp/_r_/webapp-data.md +0 -353
- package/lib/templates/project/reactinternalapp/_r_/webapp-ui.md +0 -16
- package/lib/templates/project/reactinternalapp/package-lock.json +0 -9995
- package/lib/templates/webapplication/reactbasic/e2e/app.spec.ts +0 -17
- package/lib/templates/webapplication/webappbasic/README.md +0 -15
- package/lib/utils/webappTemplateUtils.js.map +0 -1
- /package/lib/templates/project/reactexternalapp/_p_/_m_/_d_/_s_/{_a1_ → reactexternalapp1}/reactexternalapp1.digitalExperience-meta.xml +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/_d_/_s_/{_a1_ → reactexternalapp1}/sfdc_cms__site/reactexternalapp1/_meta.json +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/_d_/_s_/{_a1_ → reactexternalapp1}/sfdc_cms__site/reactexternalapp1/content.json +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/{digitalExperienceConfigs/reactexternalapp1.digitalExperienceConfig → _dc_/reactexternalapp1.digitalExperienceConfig-meta.xml} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/_w_/_a_/{webapplication.json → ui-bundle.json} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppAuthUtils.cls-meta.xml → UIBundleAuthUtils.cls-meta.xml} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppChangePassword.cls-meta.xml → UIBundleChangePassword.cls-meta.xml} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppForgotPassword.cls-meta.xml → UIBundleForgotPassword.cls-meta.xml} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppLogin.cls-meta.xml → UIBundleLogin.cls-meta.xml} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppRegistration.cls-meta.xml → UIBundleRegistration.cls-meta.xml} +0 -0
- /package/lib/templates/project/reactexternalapp/_p_/_m_/sites/{reactexternalapp.site → reactexternalapp.site-meta.xml} +0 -0
- /package/lib/templates/project/reactinternalapp/_p_/_m_/_w_/_a_/{webapplication.json → ui-bundle.json} +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/.forceignore +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/.graphqlrc.yml +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/.prettierignore +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/.prettierrc +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/codegen.yml +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/components.json +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/index.html +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/playwright.config.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/scripts/rewrite-e2e-assets.mjs +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/api/graphqlClient.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/app.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/appLayout.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/book.svg +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/copy.svg +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/rocket.svg +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/icons/star.svg +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/codey-1.png +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/codey-2.png +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/codey-3.png +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/assets/images/vibe-codey.svg +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/alerts/status-alert.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/layouts/card-layout.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/alert.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/badge.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/breadcrumb.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/button.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/calendar.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/card.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/checkbox.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/collapsible.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/datePicker.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/dialog.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/field.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/index.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/input.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/label.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/pagination.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/popover.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/select.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/separator.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/skeleton.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/sonner.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/spinner.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/table.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/components/ui/tabs.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/lib/utils.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/navigationMenu.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/pages/Home.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/pages/NotFound.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/router-utils.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/routes.tsx +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/src/styles/global.css +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/tsconfig.json +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/tsconfig.node.json +0 -0
- /package/lib/templates/{webapplication/reactbasic/webapplication.json → uiBundles/reactbasic/ui-bundle.json} +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/vite-env.d.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/vitest-env.d.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/vitest.config.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/reactbasic/vitest.setup.ts +0 -0
- /package/lib/templates/{webapplication → uiBundles}/webappbasic/src/index.html +0 -0
- /package/lib/templates/{webapplication/webappbasic/webapplication.json → uiBundles/webappbasic/ui-bundle.json} +0 -0
|
@@ -1,12 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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 './
|
|
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 "./
|
|
14
|
-
import AccountObjectDetail from "./
|
|
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-
|
|
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');
|
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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.');
|
package/lib/templates/project/reactexternalapp/_p_/_m_/classes/{WebAppLogin.cls → UIBundleLogin.cls}
RENAMED
|
@@ -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
|
|
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 =
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
146
|
+
throw new UIBundleAuthUtils.AuthException(500, ex.getDisplayMessages());
|
|
147
147
|
}
|
|
148
148
|
if (userId == null) {
|
|
149
|
-
throw new
|
|
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>
|
|
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>
|
|
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/
|
|
3
|
-
"version": "1.
|
|
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
|
|
64
|
-
echo " cd force-app/main/default/
|
|
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
|
|
77
|
-
echo " cd force-app/main/default/
|
|
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,
|
|
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-
|
|
11
|
-
* node scripts/setup-cli.mjs --target-org myorg --
|
|
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.
|
|
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
|
|
20
|
-
* 7. dev — (in
|
|
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
|
|
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
|
|
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
|
-
|
|
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] === '--
|
|
71
|
-
|
|
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-
|
|
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
|
-
--
|
|
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-
|
|
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,
|
|
112
|
+
return { targetOrg, uiBundleName, permsetNamesExplicit, yes, ...flags };
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
function
|
|
116
|
-
if (!existsSync(
|
|
117
|
-
console.error(`Error:
|
|
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(
|
|
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
|
|
123
|
+
console.error(`Error: No UI bundle folder found under ${UIBUNDLES_DIR}`);
|
|
124
124
|
process.exit(1);
|
|
125
125
|
}
|
|
126
|
-
if (
|
|
127
|
-
const requested = dirs.find((d) => d.name ===
|
|
126
|
+
if (uiBundleName) {
|
|
127
|
+
const requested = dirs.find((d) => d.name === uiBundleName);
|
|
128
128
|
if (!requested) {
|
|
129
|
-
console.error(`Error:
|
|
129
|
+
console.error(`Error: UI bundle directory not found: ${uiBundleName}`);
|
|
130
130
|
process.exit(1);
|
|
131
131
|
}
|
|
132
|
-
return [resolve(
|
|
132
|
+
return [resolve(UIBUNDLES_DIR, requested.name)];
|
|
133
133
|
}
|
|
134
|
-
return dirs.map((d) => resolve(
|
|
134
|
+
return dirs.map((d) => resolve(UIBUNDLES_DIR, d.name));
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
function
|
|
138
|
-
const all =
|
|
139
|
-
if (all.length > 1 && !
|
|
140
|
-
console.log(`Multiple
|
|
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
|
-
|
|
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
|
-
|
|
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: '
|
|
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
|
|
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
|
|
345
|
-
const
|
|
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, '|
|
|
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
|
|
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
|
-
!
|
|
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
|
|
370
|
-
if (!skipDeploy && !
|
|
371
|
-
const
|
|
372
|
-
for (const dir of
|
|
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(`
|
|
375
|
-
run(`
|
|
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 || !
|
|
539
|
-
run('
|
|
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:
|
|
545
|
-
run('GraphQL codegen', 'npm', ['run', 'graphql:codegen'], { cwd:
|
|
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 (!
|
|
549
|
-
run('
|
|
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:
|
|
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
|
|
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
|
|
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', '
|
|
30
|
+
return resolve(ROOT, pkgDir, 'main', 'default', 'uiBundles');
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
function
|
|
34
|
-
const
|
|
35
|
-
if (!existsSync(
|
|
36
|
-
console.error(`Error:
|
|
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(
|
|
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
|
|
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
|
|
46
|
+
console.log(`Multiple UI bundles found; using first: ${dirs[0].name}`);
|
|
47
47
|
}
|
|
48
|
-
return resolve(
|
|
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
|
|
59
|
+
const uiBundleDir = discoverUIBundleDir();
|
|
60
60
|
console.log('SFDX project root:', ROOT);
|
|
61
|
-
console.log('
|
|
61
|
+
console.log('UI bundle directory:', uiBundleDir);
|
|
62
62
|
|
|
63
|
-
run('npm install', 'npm', ['install'], { cwd:
|
|
64
|
-
run('npm run build', 'npm', ['run', 'build'], { cwd:
|
|
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:
|
|
66
|
+
run('npm run dev', 'npm', ['run', 'dev'], { cwd: uiBundleDir });
|