@salesforce/ui-bundle-template-app-react-sample-b2e 1.117.2
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/LICENSE.txt +82 -0
- package/README.md +52 -0
- package/dist/.forceignore +15 -0
- package/dist/.husky/pre-commit +4 -0
- package/dist/.prettierignore +11 -0
- package/dist/.prettierrc +17 -0
- package/dist/AGENT.md +193 -0
- package/dist/CHANGELOG.md +2128 -0
- package/dist/README.md +104 -0
- package/dist/config/project-scratch-def.json +13 -0
- package/dist/eslint.config.js +7 -0
- package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler.cls +69 -0
- package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler.cls-meta.xml +5 -0
- package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler_Test.cls +308 -0
- package/dist/force-app/main/default/classes/MaintenanceRequestTriggerHandler_Test.cls-meta.xml +5 -0
- package/dist/force-app/main/default/classes/TenantTriggerHandler.cls +77 -0
- package/dist/force-app/main/default/classes/TenantTriggerHandler.cls-meta.xml +5 -0
- package/dist/force-app/main/default/classes/TenantTriggerHandler_Test.cls +100 -0
- package/dist/force-app/main/default/classes/TenantTriggerHandler_Test.cls-meta.xml +5 -0
- package/dist/force-app/main/default/cspTrustedSites/GitHub_Avatars.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/Google_Fonts.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/Google_Fonts_Static.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/OpenStreetMap_Nominatim.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/OpenStreetMap_Tiles.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/Open_Meteo_API.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/Pexels_Images.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/Pexels_Videos.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/cspTrustedSites/Unsplash_Images.cspTrustedSite-meta.xml +15 -0
- package/dist/force-app/main/default/data/Agent__c.json +79 -0
- package/dist/force-app/main/default/data/Application__c.json +124 -0
- package/dist/force-app/main/default/data/Contact.json +44 -0
- package/dist/force-app/main/default/data/KPI_Snapshot__c.json +160 -0
- package/dist/force-app/main/default/data/Lease__c.json +9442 -0
- package/dist/force-app/main/default/data/Maintenance_Request__c.json +514 -0
- package/dist/force-app/main/default/data/Maintenance_Worker__c.json +304 -0
- package/dist/force-app/main/default/data/Notification__c.json +214 -0
- package/dist/force-app/main/default/data/Payment__c.json +1024 -0
- package/dist/force-app/main/default/data/Property_Cost__c.json +484 -0
- package/dist/force-app/main/default/data/Property_Feature__c.json +169 -0
- package/dist/force-app/main/default/data/Property_Image__c.json +148 -0
- package/dist/force-app/main/default/data/Property_Listing__c.json +130 -0
- package/dist/force-app/main/default/data/Property_Management_Company__c.json +70 -0
- package/dist/force-app/main/default/data/Property_Owner__c.json +184 -0
- package/dist/force-app/main/default/data/Property_Sale__c.json +246 -0
- package/dist/force-app/main/default/data/Property__c.json +704 -0
- package/dist/force-app/main/default/data/Tenant__c.json +184 -0
- package/dist/force-app/main/default/data/data-plan.json +110 -0
- package/dist/force-app/main/default/data/prepare-import-unique-fields.js +85 -0
- package/dist/force-app/main/default/layouts/Application__c-Application Layout.layout-meta.xml +58 -0
- package/dist/force-app/main/default/layouts/KPI_Snapshot__c-KPI Snapshot Layout.layout-meta.xml +87 -0
- package/dist/force-app/main/default/layouts/Lease__c-Lease Layout.layout-meta.xml +83 -0
- package/dist/force-app/main/default/layouts/Maintenance_Request__c-Maintenance Request Layout.layout-meta.xml +89 -0
- package/dist/force-app/main/default/layouts/Maintenance_Worker__c-Maintenance Worker Layout.layout-meta.xml +66 -0
- package/dist/force-app/main/default/layouts/Payment__c-Payment Layout.layout-meta.xml +88 -0
- package/dist/force-app/main/default/layouts/Property_Cost__c-Property Cost Layout.layout-meta.xml +88 -0
- package/dist/force-app/main/default/layouts/Property_Feature__c-Property Feature Layout.layout-meta.xml +80 -0
- package/dist/force-app/main/default/layouts/Property_Image__c-Property Image Layout.layout-meta.xml +75 -0
- package/dist/force-app/main/default/layouts/Property_Listing__c-Property Listing Layout.layout-meta.xml +92 -0
- package/dist/force-app/main/default/layouts/Property_Management_Company__c-Property Management Company Layout.layout-meta.xml +75 -0
- package/dist/force-app/main/default/layouts/Property_Owner__c-Property Owner Layout.layout-meta.xml +67 -0
- package/dist/force-app/main/default/layouts/Property_Sale__c-Property Sale Layout.layout-meta.xml +87 -0
- package/dist/force-app/main/default/layouts/Property__c-Property Layout.layout-meta.xml +130 -0
- package/dist/force-app/main/default/layouts/Tenant__c-Tenant Layout.layout-meta.xml +58 -0
- package/dist/force-app/main/default/objects/Agent__c/Agent__c.object-meta.xml +66 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/Agent_Type__c.field-meta.xml +37 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/Availability__c.field-meta.xml +37 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/Emergency_Alt__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/Language__c.field-meta.xml +42 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/License_Expiry__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/License_Number__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/Office_Location__c.field-meta.xml +42 -0
- package/dist/force-app/main/default/objects/Agent__c/fields/Territory__c.field-meta.xml +42 -0
- package/dist/force-app/main/default/objects/Application__c/Application__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Application__c/fields/Employment__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Application__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Application__c/fields/References__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Application__c/fields/Start_Date__c.field-meta.xml +9 -0
- package/dist/force-app/main/default/objects/Application__c/fields/Status__c.field-meta.xml +47 -0
- package/dist/force-app/main/default/objects/Application__c/fields/User__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/KPI_Snapshot__c.object-meta.xml +65 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Previous_Month_Sales__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Sales_MoM_Change__c.field-meta.xml +18 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Snapshot_Date__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Total_Properties__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Total_Sales_Amount__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Total_Sales_Count__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Units_Available__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/KPI_Snapshot__c/fields/Units_Occupied__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Lease__c/Lease__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/End_Date__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/Lease_Status__c.field-meta.xml +36 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/Monthly_Rent__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/Security_Deposit__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/Start_Date__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Lease__c/fields/Tenant__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Lease__c/validationRules/End_Date_After_Start_Date.validationRule-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/Maintenance_Request__c.object-meta.xml +73 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Actual_Cost__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Assigned_Worker__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Completed__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Description__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Est_Cost__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Priority__c.field-meta.xml +32 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Scheduled__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Status__c.field-meta.xml +42 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Tenant_Home__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/Type__c.field-meta.xml +62 -0
- package/dist/force-app/main/default/objects/Maintenance_Request__c/fields/User__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/Maintenance_Worker__c.object-meta.xml +71 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Certifications__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Employment_Type__c.field-meta.xml +32 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Hourly_Rate__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/IsActive__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Location__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Phone__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Rating__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Maintenance_Worker__c/fields/Type__c.field-meta.xml +57 -0
- package/dist/force-app/main/default/objects/Notification__c/Notification__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Is_Read__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Message__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Priority__c.field-meta.xml +36 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Related_Object_Type__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Related_Record_Id__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Title__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/Type__c.field-meta.xml +36 -0
- package/dist/force-app/main/default/objects/Notification__c/fields/User__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Payment__c/Payment__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Payment__c/fields/Amount__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Payment__c/fields/Lease__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Payment__c/fields/Notes__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Payment__c/fields/Payment_Date__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Payment__c/fields/Payment_Method__c.field-meta.xml +41 -0
- package/dist/force-app/main/default/objects/Payment__c/fields/Payment_Status__c.field-meta.xml +36 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/Property_Cost__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/fields/Cost_Amount__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/fields/Cost_Category__c.field-meta.xml +56 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/fields/Cost_Date__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/fields/Description__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/fields/Vendor__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Cost__c/validationRules/Cost_Amount_Limit.validationRule-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Feature__c/Property_Feature__c.object-meta.xml +65 -0
- package/dist/force-app/main/default/objects/Property_Feature__c/fields/Description__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property_Feature__c/fields/Display_on_Listing__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Feature__c/fields/Feature_Category__c.field-meta.xml +51 -0
- package/dist/force-app/main/default/objects/Property_Feature__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Property_Image__c/Property_Image__c.object-meta.xml +65 -0
- package/dist/force-app/main/default/objects/Property_Image__c/fields/Alt_Text__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Image__c/fields/Display_Order__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property_Image__c/fields/Image_Type__c.field-meta.xml +41 -0
- package/dist/force-app/main/default/objects/Property_Image__c/fields/Image_URL__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Image__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/Property_Listing__c.object-meta.xml +65 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Display_Order__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Featured__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Listing_Price__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Listing_Status__c.field-meta.xml +41 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Marketing_Description__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Property_Listing__c/fields/Short_Description__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Management_Company__c/Property_Management_Company__c.object-meta.xml +65 -0
- package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Active__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Company_Code__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Email__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Phone__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Management_Company__c/fields/Primary_Contact__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Property_Owner__c/Property_Owner__c.object-meta.xml +65 -0
- package/dist/force-app/main/default/objects/Property_Owner__c/fields/Address__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Owner__c/fields/Email__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property_Owner__c/fields/Phone__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/Property_Sale__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Buyer_Tenant__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Payment_Method__c.field-meta.xml +41 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Reference_Number__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Amount__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Date__c.field-meta.xml +10 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Status__c.field-meta.xml +36 -0
- package/dist/force-app/main/default/objects/Property_Sale__c/fields/Sale_Type__c.field-meta.xml +51 -0
- package/dist/force-app/main/default/objects/Property__c/Property__c.object-meta.xml +71 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Address__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Agent__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Available_Date__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Bathrooms__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Bedrooms__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Coordinates__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Deposit__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Description__c.field-meta.xml +12 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Features__c.field-meta.xml +38 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Hero_Image__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Lease_Term__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Monthly_Rent__c.field-meta.xml +13 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Parking__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Pet_Friendly__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Sq_Ft__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Status__c.field-meta.xml +37 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Tour_URL__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Type__c.field-meta.xml +37 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Utilities__c.field-meta.xml +38 -0
- package/dist/force-app/main/default/objects/Property__c/fields/Year_Built__c.field-meta.xml +14 -0
- package/dist/force-app/main/default/objects/Tenant__c/Tenant__c.object-meta.xml +67 -0
- package/dist/force-app/main/default/objects/Tenant__c/fields/End_Date__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Tenant__c/fields/Property__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/objects/Tenant__c/fields/Start_Date__c.field-meta.xml +11 -0
- package/dist/force-app/main/default/objects/Tenant__c/fields/Status__c.field-meta.xml +37 -0
- package/dist/force-app/main/default/objects/Tenant__c/fields/User_Status__c.field-meta.xml +42 -0
- package/dist/force-app/main/default/objects/Tenant__c/fields/User__c.field-meta.xml +15 -0
- package/dist/force-app/main/default/permissionsets/Property_Management_Access.permissionset-meta.xml +633 -0
- package/dist/force-app/main/default/permissionsets/Tenant_Maintenance_Access.permissionset-meta.xml +137 -0
- package/dist/force-app/main/default/triggers/MaintenanceRequestTrigger.trigger +5 -0
- package/dist/force-app/main/default/triggers/MaintenanceRequestTrigger.trigger-meta.xml +5 -0
- package/dist/force-app/main/default/triggers/TenantTrigger.trigger +8 -0
- package/dist/force-app/main/default/triggers/TenantTrigger.trigger-meta.xml +5 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/.forceignore +15 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/.graphqlrc.yml +2 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/.prettierignore +9 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/.prettierrc +11 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/CHANGELOG.md +10 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/README.md +35 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/codegen.yml +95 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/components.json +18 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/e2e/app.spec.ts +17 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/eslint.config.js +169 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/index.html +12 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/package.json +70 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/playwright.config.ts +24 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/propertymanagementapp.uibundle-meta.xml +7 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/scripts/get-graphql-schema.mjs +68 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/scripts/rewrite-e2e-assets.mjs +23 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/applicationSearchService.ts +46 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/applications.ts +122 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/applicationForApproval.graphql +22 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/distinctApplicationStatus.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/existingTenant.graphql +16 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/getApplications.graphql +44 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/searchApplications.graphql +65 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/updateApplicationStatus.graphql +13 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/applications/query/userByContact.graphql +13 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/dashboard.ts +108 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/query/getDashboardMetrics.graphql +39 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/query/getOpenApplications.graphql +36 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/dashboard/query/getUserInfo.graphql +16 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/graphql-operations-types.ts +16420 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/graphqlClient.ts +25 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/maintenanceRequestSearchService.ts +66 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/maintenanceRequests.ts +75 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/distinctMaintenanceRequestPriority.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/distinctMaintenanceRequestStatus.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/distinctMaintenanceRequestType.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/getAllMaintenanceRequests.graphql +71 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/getMaintenanceRequests.graphql +41 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/searchMaintenanceRequests.graphql +82 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceRequests/query/updateMaintenanceStatus.graphql +13 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceWorkers/maintenanceWorkerSearchService.ts +46 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceWorkers/query/distinctMaintenanceWorkerEmploymentType.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/maintenanceWorkers/query/searchMaintenanceWorkers.graphql +64 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/properties.ts +43 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/propertySearchService.ts +56 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/distinctPropertyStatus.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/distinctPropertyType.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/getProperties.graphql +77 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/api/properties/query/searchProperties.graphql +105 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/app.tsx +17 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/appLayout.tsx +32 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/appliances.svg +13 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/book.svg +3 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/copy.svg +4 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/dashboard.svg +4 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/downgraph.svg +3 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/electrical.svg +41 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/files.svg +7 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/hvac.svg +79 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/maintenance-worker.svg +8 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/maintenance.svg +4 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/pest.svg +5 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/plumbing.svg +7 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/properties.svg +14 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/rocket.svg +3 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/star.svg +3 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/support.svg +6 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/upgraph.svg +3 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/users.svg +8 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/icons/zen-logo.svg +5 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/codey-1.png +0 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/codey-2.png +0 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/codey-3.png +0 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/assets/images/vibe-codey.svg +194 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/AgentforceConversationClient.tsx +168 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/alerts/status-alert.tsx +49 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/applications/ApplicationDetailsModal.tsx +142 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/GlobalSearchBar.tsx +101 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/IssuesDonutChart.tsx +122 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/MaintenanceTable.tsx +129 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/dashboard/StatCard.tsx +73 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/FilterRow.tsx +23 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/PageContainer.tsx +13 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/PageHeader.tsx +17 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/TopBar.tsx +55 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layout/VerticalNav.tsx +75 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/layouts/card-layout.tsx +29 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/maintenanceRequests/MaintenanceDetailsModal.tsx +193 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/maintenanceRequests/MaintenanceRequestCard.tsx +80 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/maintenanceWorkers/WorkerDetailsModal.tsx +66 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/properties/PropertyCard.tsx +61 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/properties/PropertyDetailsModal.tsx +263 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/shared/ObjectSearchErrorState.tsx +45 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/shared/UserAvatar.tsx +35 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/alert.tsx +76 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/badge.tsx +48 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/breadcrumb.tsx +109 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/button.tsx +67 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/calendar.tsx +232 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/card.tsx +103 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/checkbox.tsx +32 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/collapsible.tsx +33 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/datePicker.tsx +127 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/dialog.tsx +162 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/field.tsx +237 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/index.ts +84 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/input.tsx +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/label.tsx +22 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/pagination.tsx +132 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/popover.tsx +89 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/select.tsx +193 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/separator.tsx +26 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/skeleton.tsx +14 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/sonner.tsx +20 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/spinner.tsx +16 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/table.tsx +114 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/components/ui/tabs.tsx +88 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/accountSearchService.ts +46 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/distinctAccountIndustries.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/distinctAccountTypes.graphql +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/getAccountDetail.graphql +121 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/api/query/searchAccounts.graphql +51 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/pages/AccountObjectDetailPage.tsx +357 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/pages/AccountSearch.tsx +312 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/__examples__/pages/Home.tsx +34 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/api/objectSearchService.ts +84 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/ActiveFilters.tsx +89 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/FilterContext.tsx +83 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/ObjectBreadcrumb.tsx +66 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/PaginationControls.tsx +109 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/SearchBar.tsx +41 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/SortControl.tsx +143 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/BooleanFilter.tsx +78 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/DateFilter.tsx +128 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/DateRangeFilter.tsx +70 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/FilterFieldWrapper.tsx +33 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/MultiSelectFilter.tsx +97 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/NumericRangeFilter.tsx +163 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/SearchFilter.tsx +50 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/SelectFilter.tsx +97 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/components/filters/TextFilter.tsx +91 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useAsyncData.ts +54 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useCachedAsyncData.ts +184 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useDebouncedCallback.ts +34 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/hooks/useObjectSearchParams.ts +252 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/debounce.ts +25 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/fieldUtils.ts +29 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/filterUtils.ts +395 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/features/object-search/utils/sortUtils.ts +38 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/index.ts +6 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/lib/constants.ts +60 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/lib/routeConfig.ts +35 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/lib/utils.ts +6 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/navigationMenu.tsx +80 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/ApplicationSearch.tsx +373 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/Home.tsx +183 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/MaintenanceRequestSearch.tsx +465 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/MaintenanceWorkerSearch.tsx +324 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/NotFound.tsx +18 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/PropertySearch.tsx +258 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/pages/TestAccPage.tsx +19 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/router-utils.tsx +35 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/routes.tsx +63 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/styles/global.css +173 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/src/types/conversation.ts +33 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/tsconfig.json +42 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/tsconfig.node.json +13 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/ui-bundle.json +7 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/vite-env.d.ts +1 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/vite.config.ts +106 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/vitest-env.d.ts +2 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/vitest.config.ts +11 -0
- package/dist/force-app/main/default/uiBundles/propertymanagementapp/vitest.setup.ts +1 -0
- package/dist/jest.config.js +6 -0
- package/dist/package-lock.json +9995 -0
- package/dist/package.json +40 -0
- package/dist/scripts/apex/hello.apex +10 -0
- package/dist/scripts/graphql-search.sh +191 -0
- package/dist/scripts/prepare-import-unique-fields.js +122 -0
- package/dist/scripts/setup-cli.mjs +563 -0
- package/dist/scripts/sf-project-setup.mjs +66 -0
- package/dist/scripts/soql/account.soql +6 -0
- package/dist/sfdx-project.json +12 -0
- package/package.json +51 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* One-command setup: login, deploy, optional permset/data, GraphQL schema/codegen, UI bundle build.
|
|
4
|
+
* Use this script to make setup easier for each app generated from this template.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* node scripts/setup-cli.mjs --target-org <alias> # interactive step picker (all selected)
|
|
8
|
+
* node scripts/setup-cli.mjs --target-org <alias> --yes # skip picker, run all steps
|
|
9
|
+
* node scripts/setup-cli.mjs --target-org afv5 --skip-login
|
|
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
|
+
*
|
|
13
|
+
* Steps (in order):
|
|
14
|
+
* 1. login — sf org login web only if org not already connected (skip with --skip-login)
|
|
15
|
+
* 2. uiBundle — (all UI bundles) npm install && npm run build so dist exists for deploy (skip with --skip-ui-bundle-build)
|
|
16
|
+
* 3. deploy — sf project deploy start --target-org <alias> (requires dist for entity deployment)
|
|
17
|
+
* 4. permset — sf org assign permset for each *.permissionset-meta.xml (skip with --skip-permset; override via --permset-name)
|
|
18
|
+
* 5. data — prepare unique fields + sf data import tree (skipped if no data dir/plan)
|
|
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
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { spawnSync } from 'node:child_process';
|
|
24
|
+
import { resolve, dirname } from 'node:path';
|
|
25
|
+
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import { readdirSync, existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
27
|
+
|
|
28
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
29
|
+
const ROOT = resolve(__dirname, '..');
|
|
30
|
+
|
|
31
|
+
function resolveSfdxSource() {
|
|
32
|
+
const sfdxPath = resolve(ROOT, 'sfdx-project.json');
|
|
33
|
+
if (!existsSync(sfdxPath)) {
|
|
34
|
+
console.error('Error: sfdx-project.json not found at project root.');
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
const sfdxProject = JSON.parse(readFileSync(sfdxPath, 'utf8'));
|
|
38
|
+
const pkgDir = sfdxProject?.packageDirectories?.[0]?.path;
|
|
39
|
+
if (!pkgDir) {
|
|
40
|
+
console.error('Error: No packageDirectories[].path found in sfdx-project.json.');
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
return resolve(ROOT, pkgDir, 'main', 'default');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const SFDX_SOURCE = resolveSfdxSource();
|
|
47
|
+
const UIBUNDLES_DIR = resolve(SFDX_SOURCE, 'uiBundles');
|
|
48
|
+
const DATA_DIR = resolve(SFDX_SOURCE, 'data');
|
|
49
|
+
const DATA_PLAN = resolve(SFDX_SOURCE, 'data/data-plan.json');
|
|
50
|
+
|
|
51
|
+
function parseArgs() {
|
|
52
|
+
const args = process.argv.slice(2);
|
|
53
|
+
let targetOrg = null;
|
|
54
|
+
let uiBundleName = null;
|
|
55
|
+
/** If non-empty, only these names are assigned; otherwise all discovered from the project. */
|
|
56
|
+
const permsetNamesExplicit = [];
|
|
57
|
+
let yes = false;
|
|
58
|
+
const flags = {
|
|
59
|
+
skipLogin: false,
|
|
60
|
+
skipDeploy: false,
|
|
61
|
+
skipPermset: false,
|
|
62
|
+
skipData: false,
|
|
63
|
+
skipGraphql: false,
|
|
64
|
+
skipUIBundleBuild: false,
|
|
65
|
+
skipDev: false,
|
|
66
|
+
};
|
|
67
|
+
for (let i = 0; i < args.length; i++) {
|
|
68
|
+
if (args[i] === '--target-org' && args[i + 1]) {
|
|
69
|
+
targetOrg = args[++i];
|
|
70
|
+
} else if (args[i] === '--ui-bundle-name' && args[i + 1]) {
|
|
71
|
+
uiBundleName = args[++i];
|
|
72
|
+
} else if (args[i] === '--permset-name' && args[i + 1]) {
|
|
73
|
+
permsetNamesExplicit.push(args[++i]);
|
|
74
|
+
} else if (args[i] === '--skip-login') flags.skipLogin = true;
|
|
75
|
+
else if (args[i] === '--skip-deploy') flags.skipDeploy = true;
|
|
76
|
+
else if (args[i] === '--skip-permset') flags.skipPermset = true;
|
|
77
|
+
else if (args[i] === '--skip-data') flags.skipData = true;
|
|
78
|
+
else if (args[i] === '--skip-graphql') flags.skipGraphql = true;
|
|
79
|
+
else if (args[i] === '--skip-ui-bundle-build') flags.skipUIBundleBuild = true;
|
|
80
|
+
else if (args[i] === '--skip-dev') flags.skipDev = true;
|
|
81
|
+
else if (args[i] === '--yes' || args[i] === '-y') yes = true;
|
|
82
|
+
else if (args[i] === '--help' || args[i] === '-h') {
|
|
83
|
+
console.log(`
|
|
84
|
+
Setup CLI — one-command setup for apps in this project
|
|
85
|
+
|
|
86
|
+
Usage:
|
|
87
|
+
node scripts/setup-cli.mjs --target-org <alias> [options]
|
|
88
|
+
|
|
89
|
+
Required:
|
|
90
|
+
--target-org <alias> Target Salesforce org alias (e.g. myorg)
|
|
91
|
+
|
|
92
|
+
Options:
|
|
93
|
+
--ui-bundle-name <name> UI bundle folder name under uiBundles/ (default: auto-detect)
|
|
94
|
+
--permset-name <name> Assign only this permission set (repeatable). Default: all sets under permissionsets/
|
|
95
|
+
--skip-login Skip login step (login is auto-skipped if org is already connected)
|
|
96
|
+
--skip-deploy Do not deploy metadata
|
|
97
|
+
--skip-permset Do not assign permission set
|
|
98
|
+
--skip-data Do not prepare data or run data import
|
|
99
|
+
--skip-graphql Do not fetch schema or run GraphQL codegen
|
|
100
|
+
--skip-ui-bundle-build Do not npm install / build the UI bundle
|
|
101
|
+
--skip-dev Do not launch the dev server at the end
|
|
102
|
+
-y, --yes Skip interactive step picker; run all enabled steps immediately
|
|
103
|
+
-h, --help Show this help
|
|
104
|
+
`);
|
|
105
|
+
process.exit(0);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (!targetOrg) {
|
|
109
|
+
console.error('Error: --target-org <alias> is required.');
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
return { targetOrg, uiBundleName, permsetNamesExplicit, yes, ...flags };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function discoverAllUIBundleDirs(uiBundleName) {
|
|
116
|
+
if (!existsSync(UIBUNDLES_DIR)) {
|
|
117
|
+
console.error(`Error: uiBundles directory not found: ${UIBUNDLES_DIR}`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
const entries = readdirSync(UIBUNDLES_DIR, { withFileTypes: true });
|
|
121
|
+
const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.'));
|
|
122
|
+
if (dirs.length === 0) {
|
|
123
|
+
console.error(`Error: No UI bundle folder found under ${UIBUNDLES_DIR}`);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
if (uiBundleName) {
|
|
127
|
+
const requested = dirs.find((d) => d.name === uiBundleName);
|
|
128
|
+
if (!requested) {
|
|
129
|
+
console.error(`Error: UI bundle directory not found: ${uiBundleName}`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
return [resolve(UIBUNDLES_DIR, requested.name)];
|
|
133
|
+
}
|
|
134
|
+
return dirs.map((d) => resolve(UIBUNDLES_DIR, d.name));
|
|
135
|
+
}
|
|
136
|
+
|
|
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
|
+
}
|
|
142
|
+
return all[0];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** API names from permissionsets/*.permissionset-meta.xml in the first package directory. */
|
|
146
|
+
function discoverPermissionSetNames() {
|
|
147
|
+
const dir = resolve(SFDX_SOURCE, 'permissionsets');
|
|
148
|
+
if (!existsSync(dir)) return [];
|
|
149
|
+
const names = [];
|
|
150
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
151
|
+
if (!entry.isFile()) continue;
|
|
152
|
+
const m = entry.name.match(/^(.+)\.permissionset-meta\.xml$/);
|
|
153
|
+
if (m) names.push(m[1]);
|
|
154
|
+
}
|
|
155
|
+
return names.sort();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isOrgConnected(targetOrg) {
|
|
159
|
+
const result = spawnSync('sf', ['org', 'display', '--target-org', targetOrg, '--json'], {
|
|
160
|
+
cwd: ROOT,
|
|
161
|
+
stdio: 'pipe',
|
|
162
|
+
shell: true,
|
|
163
|
+
});
|
|
164
|
+
return result.status === 0;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function apexLiteral(value) {
|
|
168
|
+
if (value === null || value === undefined) return 'null';
|
|
169
|
+
if (typeof value === 'boolean') return String(value);
|
|
170
|
+
if (typeof value === 'number') return String(value);
|
|
171
|
+
const s = String(value);
|
|
172
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(s)) return `Date.valueOf('${s}')`;
|
|
173
|
+
if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}/.test(s)) {
|
|
174
|
+
const dt = s.replace('T', ' ').replace(/\.\d+/, '').replace('Z', '');
|
|
175
|
+
return `DateTime.valueOf('${dt}')`;
|
|
176
|
+
}
|
|
177
|
+
return "'" + s.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'";
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function buildApexInsert(sobject, records, refIds) {
|
|
181
|
+
const lines = [
|
|
182
|
+
'Database.DMLOptions dmlOpts = new Database.DMLOptions();',
|
|
183
|
+
'dmlOpts.DuplicateRuleHeader.allowSave = true;',
|
|
184
|
+
`List<${sobject}> recs = new List<${sobject}>();`,
|
|
185
|
+
];
|
|
186
|
+
for (const rec of records) {
|
|
187
|
+
lines.push(`{ ${sobject} r = new ${sobject}();`);
|
|
188
|
+
for (const [key, val] of Object.entries(rec)) {
|
|
189
|
+
if (key === 'attributes') continue;
|
|
190
|
+
lines.push(`r.put('${key}', ${apexLiteral(val)});`);
|
|
191
|
+
}
|
|
192
|
+
lines.push('recs.add(r); }');
|
|
193
|
+
}
|
|
194
|
+
lines.push('Database.SaveResult[] results = Database.insert(recs, dmlOpts);');
|
|
195
|
+
const refArray = refIds.map((r) => `'${r}'`).join(',');
|
|
196
|
+
lines.push(`String[] refs = new String[]{${refArray}};`);
|
|
197
|
+
lines.push('for (Integer i = 0; i < results.size(); i++) {');
|
|
198
|
+
lines.push(" if (results[i].isSuccess()) System.debug('REF:' + refs[i] + ':' + results[i].getId());");
|
|
199
|
+
lines.push(" else System.debug('ERR:' + refs[i] + ':' + results[i].getErrors()[0].getMessage());");
|
|
200
|
+
lines.push('}');
|
|
201
|
+
return lines.join('\n');
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Interactive multi-select: arrow keys navigate, space toggles, 'a' toggles all, enter confirms.
|
|
206
|
+
* Returns a boolean[] matching the input order. Falls through immediately when stdin is not a TTY.
|
|
207
|
+
*/
|
|
208
|
+
async function promptSteps(steps) {
|
|
209
|
+
if (!process.stdin.isTTY) return steps.map((s) => s.enabled);
|
|
210
|
+
|
|
211
|
+
const selected = steps.map((s) => s.enabled);
|
|
212
|
+
let cursor = 0;
|
|
213
|
+
const DIM = '\x1B[2m';
|
|
214
|
+
const RST = '\x1B[0m';
|
|
215
|
+
const CYAN = '\x1B[36m';
|
|
216
|
+
const GREEN = '\x1B[32m';
|
|
217
|
+
|
|
218
|
+
function render() {
|
|
219
|
+
return steps.map((s, i) => {
|
|
220
|
+
const ptr = i === cursor ? `${CYAN}❯${RST}` : ' ';
|
|
221
|
+
if (!s.available) return `${ptr} ${DIM}○ ${s.label} (n/a)${RST}`;
|
|
222
|
+
const chk = selected[i] ? `${GREEN}●${RST}` : '○';
|
|
223
|
+
return `${ptr} ${chk} ${s.label}`;
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return new Promise((resolve) => {
|
|
228
|
+
process.stdin.setRawMode(true);
|
|
229
|
+
process.stdin.resume();
|
|
230
|
+
process.stdin.setEncoding('utf8');
|
|
231
|
+
process.stdout.write('\x1B[?25l');
|
|
232
|
+
console.log('\nSelect steps (↑↓ move, space toggle, a all, enter confirm):\n');
|
|
233
|
+
process.stdout.write(render().join('\n') + '\n');
|
|
234
|
+
|
|
235
|
+
function redraw() {
|
|
236
|
+
process.stdout.write(`\x1B[${steps.length}A`);
|
|
237
|
+
for (const line of render()) process.stdout.write(`\x1B[2K${line}\n`);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
process.stdin.on('data', (key) => {
|
|
241
|
+
if (key === '\x03') {
|
|
242
|
+
process.stdout.write('\x1B[?25h\n');
|
|
243
|
+
process.exit(0);
|
|
244
|
+
}
|
|
245
|
+
if (key === '\r' || key === '\n') {
|
|
246
|
+
process.stdout.write('\x1B[?25h');
|
|
247
|
+
process.stdin.setRawMode(false);
|
|
248
|
+
process.stdin.pause();
|
|
249
|
+
process.stdin.removeAllListeners('data');
|
|
250
|
+
console.log();
|
|
251
|
+
resolve(selected);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (key === ' ') {
|
|
255
|
+
if (steps[cursor].available) selected[cursor] = !selected[cursor];
|
|
256
|
+
redraw();
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (key === 'a') {
|
|
260
|
+
const allOn = steps.every((s, i) => !s.available || selected[i]);
|
|
261
|
+
for (let i = 0; i < steps.length; i++) {
|
|
262
|
+
if (steps[i].available) selected[i] = !allOn;
|
|
263
|
+
}
|
|
264
|
+
redraw();
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
if (key === '\x1B[A' || key === 'k') {
|
|
268
|
+
cursor = Math.max(0, cursor - 1);
|
|
269
|
+
redraw();
|
|
270
|
+
} else if (key === '\x1B[B' || key === 'j') {
|
|
271
|
+
cursor = Math.min(steps.length - 1, cursor + 1);
|
|
272
|
+
redraw();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function run(name, cmd, args, opts = {}) {
|
|
279
|
+
const { cwd = ROOT, optional = false } = opts;
|
|
280
|
+
console.log('\n---', name, '---');
|
|
281
|
+
const result = spawnSync(cmd, args, {
|
|
282
|
+
cwd,
|
|
283
|
+
stdio: 'inherit',
|
|
284
|
+
shell: true,
|
|
285
|
+
...(opts.timeout && { timeout: opts.timeout }),
|
|
286
|
+
});
|
|
287
|
+
if (result.status !== 0 && !optional) {
|
|
288
|
+
console.error(`\nSetup failed at step: ${name}`);
|
|
289
|
+
process.exit(result.status ?? 1);
|
|
290
|
+
}
|
|
291
|
+
return result;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async function main() {
|
|
295
|
+
const {
|
|
296
|
+
targetOrg,
|
|
297
|
+
uiBundleName,
|
|
298
|
+
permsetNamesExplicit,
|
|
299
|
+
yes,
|
|
300
|
+
skipLogin: argSkipLogin,
|
|
301
|
+
skipDeploy: argSkipDeploy,
|
|
302
|
+
skipPermset: argSkipPermset,
|
|
303
|
+
skipData: argSkipData,
|
|
304
|
+
skipGraphql: argSkipGraphql,
|
|
305
|
+
skipUIBundleBuild: argSkipUIBundleBuild,
|
|
306
|
+
skipDev: argSkipDev,
|
|
307
|
+
} = parseArgs();
|
|
308
|
+
|
|
309
|
+
const permsetNames =
|
|
310
|
+
permsetNamesExplicit.length > 0 ? permsetNamesExplicit : discoverPermissionSetNames();
|
|
311
|
+
const permsetStepLabel =
|
|
312
|
+
permsetNames.length === 0
|
|
313
|
+
? 'Permset — (none under permissionsets/)'
|
|
314
|
+
: permsetNames.length <= 3
|
|
315
|
+
? `Permset — assign ${permsetNames.join(', ')}`
|
|
316
|
+
: `Permset — assign ${permsetNames.length} permission sets`;
|
|
317
|
+
|
|
318
|
+
const hasDataPlan = existsSync(DATA_PLAN) && existsSync(DATA_DIR);
|
|
319
|
+
|
|
320
|
+
const stepDefs = [
|
|
321
|
+
{ key: 'login', label: 'Login — org authentication', enabled: !argSkipLogin, available: true },
|
|
322
|
+
{ key: 'uiBundleBuild', label: 'UI Bundle Build — npm install + build (pre-deploy)', enabled: !argSkipUIBundleBuild, available: true },
|
|
323
|
+
{ key: 'deploy', label: 'Deploy — sf project deploy start', enabled: !argSkipDeploy, available: true },
|
|
324
|
+
{ key: 'permset', label: permsetStepLabel, enabled: !argSkipPermset, available: true },
|
|
325
|
+
{ key: 'data', label: 'Data — delete + import records via Apex', enabled: !argSkipData && hasDataPlan, available: hasDataPlan },
|
|
326
|
+
{ key: 'graphql', label: 'GraphQL — schema introspect + codegen', enabled: !argSkipGraphql, available: true },
|
|
327
|
+
{ key: 'dev', label: 'Dev — launch dev server', enabled: !argSkipDev, available: true },
|
|
328
|
+
];
|
|
329
|
+
|
|
330
|
+
const selections = yes ? stepDefs.map((s) => s.enabled) : await promptSteps(stepDefs);
|
|
331
|
+
const on = {};
|
|
332
|
+
stepDefs.forEach((s, i) => {
|
|
333
|
+
on[s.key] = selections[i];
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
const skipLogin = !on.login;
|
|
337
|
+
const skipUIBundleBuild = !on.uiBundleBuild;
|
|
338
|
+
const skipDeploy = !on.deploy;
|
|
339
|
+
const skipPermset = !on.permset;
|
|
340
|
+
const skipData = !on.data;
|
|
341
|
+
const skipGraphql = !on.graphql;
|
|
342
|
+
const skipDev = !on.dev;
|
|
343
|
+
|
|
344
|
+
const needsUIBundle = !skipUIBundleBuild || !skipGraphql || !skipDev;
|
|
345
|
+
const uiBundleDir = needsUIBundle ? discoverUIBundleDir(uiBundleName) : null;
|
|
346
|
+
const doData = !skipData;
|
|
347
|
+
|
|
348
|
+
console.log('Setup — target org:', targetOrg, '| UI bundle:', uiBundleDir ?? '(none)');
|
|
349
|
+
console.log(
|
|
350
|
+
'Steps: login=%s deploy=%s permset=%s data=%s graphql=%s uiBundle=%s dev=%s',
|
|
351
|
+
!skipLogin,
|
|
352
|
+
!skipDeploy,
|
|
353
|
+
!skipPermset,
|
|
354
|
+
doData,
|
|
355
|
+
!skipGraphql,
|
|
356
|
+
!skipUIBundleBuild,
|
|
357
|
+
!skipDev
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
if (!skipLogin) {
|
|
361
|
+
if (isOrgConnected(targetOrg)) {
|
|
362
|
+
console.log('\n--- Login ---');
|
|
363
|
+
console.log(`Org ${targetOrg} is already authenticated; skipping browser login.`);
|
|
364
|
+
} else {
|
|
365
|
+
run('Login (browser)', 'sf', ['org', 'login', 'web', '--alias', targetOrg], { optional: true });
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
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
|
+
const name = dir.split(/[/\\]/).pop();
|
|
374
|
+
run(`UI Bundle install (${name})`, 'npm', ['install'], { cwd: dir });
|
|
375
|
+
run(`UI Bundle build (${name})`, 'npm', ['run', 'build'], { cwd: dir });
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (!skipDeploy) {
|
|
380
|
+
run('Deploy metadata', 'sf', ['project', 'deploy', 'start', '--target-org', targetOrg], {
|
|
381
|
+
timeout: 180000,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (!skipPermset) {
|
|
386
|
+
if (permsetNames.length === 0) {
|
|
387
|
+
console.log('\n--- Assign permission sets ---');
|
|
388
|
+
console.log('No permission sets found under permissionsets/ and none passed via --permset-name; skipping.');
|
|
389
|
+
} else {
|
|
390
|
+
console.log('\n--- Assign permission sets ---');
|
|
391
|
+
for (const permsetName of permsetNames) {
|
|
392
|
+
const permsetResult = spawnSync(
|
|
393
|
+
'sf',
|
|
394
|
+
['org', 'assign', 'permset', '--name', permsetName, '--target-org', targetOrg],
|
|
395
|
+
{
|
|
396
|
+
cwd: ROOT,
|
|
397
|
+
stdio: 'pipe',
|
|
398
|
+
shell: true,
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
if (permsetResult.status === 0) {
|
|
402
|
+
console.log(`Permission set "${permsetName}" assigned.`);
|
|
403
|
+
} else {
|
|
404
|
+
const out =
|
|
405
|
+
(permsetResult.stderr?.toString() || '') + (permsetResult.stdout?.toString() || '');
|
|
406
|
+
if (out.includes('Duplicate') && out.includes('PermissionSet')) {
|
|
407
|
+
console.log(`Permission set "${permsetName}" already assigned; skipping.`);
|
|
408
|
+
} else if (out.includes('not found') && out.includes('target org')) {
|
|
409
|
+
console.log(`Permission set "${permsetName}" not in org; skipping.`);
|
|
410
|
+
} else {
|
|
411
|
+
process.stdout.write(permsetResult.stdout?.toString() || '');
|
|
412
|
+
process.stderr.write(permsetResult.stderr?.toString() || '');
|
|
413
|
+
console.error(`\nSetup failed at step: Assign permission set (${permsetName})`);
|
|
414
|
+
process.exit(permsetResult.status ?? 1);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (doData) {
|
|
422
|
+
// Prepare data for uniqueness (run before import so repeat imports don't conflict)
|
|
423
|
+
const prepareScript = resolve(__dirname, 'prepare-import-unique-fields.js');
|
|
424
|
+
run('Prepare data (unique fields)', 'node', [prepareScript, '--data-dir', DATA_DIR], {
|
|
425
|
+
cwd: ROOT,
|
|
426
|
+
});
|
|
427
|
+
// Normalize Lease__c Tenant refs to 1–15 so all refs resolve (Tenant__c.json has 15 records)
|
|
428
|
+
const leasePath = resolve(DATA_DIR, 'Lease__c.json');
|
|
429
|
+
if (existsSync(leasePath)) {
|
|
430
|
+
let leaseContent = readFileSync(leasePath, 'utf8');
|
|
431
|
+
leaseContent = leaseContent.replace(/@TenantRef(\d+)/g, (_m, n) => {
|
|
432
|
+
const k = ((parseInt(n, 10) - 1) % 15) + 1;
|
|
433
|
+
return `@TenantRef${k}`;
|
|
434
|
+
});
|
|
435
|
+
writeFileSync(leasePath, leaseContent);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Delete existing records so every run inserts the full dataset without duplicate conflicts.
|
|
439
|
+
// Reverse plan order ensures children are removed before parents (FK safety).
|
|
440
|
+
console.log('\n--- Clean existing data for fresh import ---');
|
|
441
|
+
const planEntries = JSON.parse(readFileSync(DATA_PLAN, 'utf8'));
|
|
442
|
+
const sobjectsReversed = [...planEntries.map((e) => e.sobject)].reverse();
|
|
443
|
+
const tmpApex = resolve(ROOT, '.tmp-setup-delete.apex');
|
|
444
|
+
for (const sobject of sobjectsReversed) {
|
|
445
|
+
const apexCode = [
|
|
446
|
+
'try {',
|
|
447
|
+
` List<SObject> recs = Database.query('SELECT Id FROM ${sobject} LIMIT 10000');`,
|
|
448
|
+
' if (!recs.isEmpty()) {',
|
|
449
|
+
' Database.delete(recs, false);',
|
|
450
|
+
' Database.emptyRecycleBin(recs);',
|
|
451
|
+
' }',
|
|
452
|
+
'} catch (Exception e) {',
|
|
453
|
+
' // non-deletable records (e.g. Contact linked to Case) are skipped via allOrNone=false',
|
|
454
|
+
'}',
|
|
455
|
+
].join('\n');
|
|
456
|
+
writeFileSync(tmpApex, apexCode);
|
|
457
|
+
spawnSync('sf', ['apex', 'run', '--target-org', targetOrg, '--file', tmpApex], {
|
|
458
|
+
cwd: ROOT,
|
|
459
|
+
stdio: 'pipe',
|
|
460
|
+
shell: true,
|
|
461
|
+
timeout: 60000,
|
|
462
|
+
});
|
|
463
|
+
console.log(` ${sobject}: cleaned`);
|
|
464
|
+
}
|
|
465
|
+
if (existsSync(tmpApex)) unlinkSync(tmpApex);
|
|
466
|
+
|
|
467
|
+
// Import via Anonymous Apex with Database.DMLOptions.duplicateRuleHeader.allowSave = true.
|
|
468
|
+
// This bypasses both duplicate-rule blocks AND matching-service timeouts that the REST
|
|
469
|
+
// API headers (Sforce-Duplicate-Rule-Action) cannot override.
|
|
470
|
+
console.log('\n--- Data import tree ---');
|
|
471
|
+
const refMap = new Map();
|
|
472
|
+
const APEX_CHAR_LIMIT = 25000;
|
|
473
|
+
const APEX_MAX_BATCH = 200;
|
|
474
|
+
|
|
475
|
+
for (const entry of planEntries) {
|
|
476
|
+
for (const file of entry.files) {
|
|
477
|
+
const data = JSON.parse(readFileSync(resolve(DATA_DIR, file), 'utf8'));
|
|
478
|
+
const records = data.records || [];
|
|
479
|
+
|
|
480
|
+
for (const rec of records) {
|
|
481
|
+
for (const key of Object.keys(rec)) {
|
|
482
|
+
if (key === 'attributes') continue;
|
|
483
|
+
const val = rec[key];
|
|
484
|
+
if (typeof val === 'string' && val.startsWith('@')) {
|
|
485
|
+
const actual = refMap.get(val.slice(1));
|
|
486
|
+
if (actual) {
|
|
487
|
+
rec[key] = actual;
|
|
488
|
+
} else if (refMap.size > 0) {
|
|
489
|
+
console.warn(` Warning: unresolved ref ${val} in ${file}`);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
let imported = 0;
|
|
496
|
+
const sampleRec = records[0] || {};
|
|
497
|
+
const fieldsPerRec = Object.keys(sampleRec).filter((k) => k !== 'attributes').length;
|
|
498
|
+
const estCharsPerRec = 40 + fieldsPerRec * 55;
|
|
499
|
+
const batchSize = Math.min(APEX_MAX_BATCH, Math.max(5, Math.floor(APEX_CHAR_LIMIT / estCharsPerRec)));
|
|
500
|
+
for (let i = 0; i < records.length; i += batchSize) {
|
|
501
|
+
const batch = records.slice(i, i + batchSize);
|
|
502
|
+
const refIds = batch.map((r) => r.attributes?.referenceId || `_idx${i}`);
|
|
503
|
+
const apex = buildApexInsert(entry.sobject, batch, refIds);
|
|
504
|
+
writeFileSync(tmpApex, apex);
|
|
505
|
+
const apexResult = spawnSync(
|
|
506
|
+
'sf',
|
|
507
|
+
['apex', 'run', '--target-org', targetOrg, '--file', tmpApex],
|
|
508
|
+
{ cwd: ROOT, stdio: 'pipe', shell: true, timeout: 120000 }
|
|
509
|
+
);
|
|
510
|
+
const apexOut = apexResult.stdout?.toString() || '';
|
|
511
|
+
const apexErr = apexResult.stderr?.toString() || '';
|
|
512
|
+
if (apexResult.status !== 0 && !apexOut.includes('Compiled successfully')) {
|
|
513
|
+
console.error(` ${entry.sobject}: apex execution failed`);
|
|
514
|
+
process.stderr.write(apexErr || apexOut);
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
const okMatches = [...apexOut.matchAll(/\|DEBUG\|REF:([^:\n]+):(\w+)/g)];
|
|
518
|
+
const errMatches = [...apexOut.matchAll(/\|DEBUG\|ERR:([^:\n]+):([^\n]+)/g)];
|
|
519
|
+
if (errMatches.length) {
|
|
520
|
+
for (const m of errMatches.slice(0, 5)) {
|
|
521
|
+
console.error(` ${m[1]}: ${m[2].trim()}`);
|
|
522
|
+
}
|
|
523
|
+
if (errMatches.length > 5) console.error(` ... and ${errMatches.length - 5} more`);
|
|
524
|
+
console.error(`\nSetup failed at step: Data import tree (${entry.sobject})`);
|
|
525
|
+
process.exit(1);
|
|
526
|
+
}
|
|
527
|
+
if (entry.saveRefs) {
|
|
528
|
+
for (const m of okMatches) refMap.set(m[1], m[2]);
|
|
529
|
+
}
|
|
530
|
+
imported += okMatches.length;
|
|
531
|
+
}
|
|
532
|
+
console.log(` ${entry.sobject}: imported ${imported} records`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (existsSync(tmpApex)) unlinkSync(tmpApex);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
if (!skipGraphql || !skipUIBundleBuild) {
|
|
539
|
+
run('UI Bundle npm install', 'npm', ['install'], { cwd: uiBundleDir });
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (!skipGraphql) {
|
|
543
|
+
run('Set default org for schema', 'sf', ['config', 'set', 'target-org', targetOrg, '--global']);
|
|
544
|
+
run('GraphQL schema (introspect)', 'npm', ['run', 'graphql:schema'], { cwd: uiBundleDir });
|
|
545
|
+
run('GraphQL codegen', 'npm', ['run', 'graphql:codegen'], { cwd: uiBundleDir });
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (!skipUIBundleBuild) {
|
|
549
|
+
run('UI Bundle build', 'npm', ['run', 'build'], { cwd: uiBundleDir });
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
console.log('\n--- Setup complete ---');
|
|
553
|
+
|
|
554
|
+
if (!skipDev) {
|
|
555
|
+
console.log('\n--- Launching dev server (Ctrl+C to stop) ---\n');
|
|
556
|
+
run('Dev server', 'npm', ['run', 'dev'], { cwd: uiBundleDir });
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
main().catch((err) => {
|
|
561
|
+
console.error(err);
|
|
562
|
+
process.exit(1);
|
|
563
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Run from SFDX project root: install dependencies, build, and launch the dev server
|
|
4
|
+
* for the UI bundle in force-app/main/default/uiBundles/.
|
|
5
|
+
*
|
|
6
|
+
* Usage: npm run sf-project-setup
|
|
7
|
+
* (from the directory that contains force-app/ and sfdx-project.json)
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { spawnSync } from 'node:child_process';
|
|
11
|
+
import { resolve, dirname } from 'node:path';
|
|
12
|
+
import { fileURLToPath } from 'node:url';
|
|
13
|
+
import { readdirSync, existsSync, readFileSync } from 'node:fs';
|
|
14
|
+
|
|
15
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const ROOT = resolve(__dirname, '..');
|
|
17
|
+
|
|
18
|
+
function resolveUIBundlesDir() {
|
|
19
|
+
const sfdxPath = resolve(ROOT, 'sfdx-project.json');
|
|
20
|
+
if (!existsSync(sfdxPath)) {
|
|
21
|
+
console.error('Error: sfdx-project.json not found at project root.');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
const sfdxProject = JSON.parse(readFileSync(sfdxPath, 'utf8'));
|
|
25
|
+
const pkgDir = sfdxProject?.packageDirectories?.[0]?.path;
|
|
26
|
+
if (!pkgDir) {
|
|
27
|
+
console.error('Error: No packageDirectories[].path found in sfdx-project.json.');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
return resolve(ROOT, pkgDir, 'main', 'default', 'uiBundles');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function discoverUIBundleDir() {
|
|
34
|
+
const uiBundlesDir = resolveUIBundlesDir();
|
|
35
|
+
if (!existsSync(uiBundlesDir)) {
|
|
36
|
+
console.error(`Error: uiBundles directory not found: ${uiBundlesDir}`);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
const entries = readdirSync(uiBundlesDir, { withFileTypes: true });
|
|
40
|
+
const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.'));
|
|
41
|
+
if (dirs.length === 0) {
|
|
42
|
+
console.error(`Error: No UI bundle folder found under ${uiBundlesDir}`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
if (dirs.length > 1) {
|
|
46
|
+
console.log(`Multiple UI bundles found; using first: ${dirs[0].name}`);
|
|
47
|
+
}
|
|
48
|
+
return resolve(uiBundlesDir, dirs[0].name);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function run(label, cmd, args, opts) {
|
|
52
|
+
console.log(`\n--- ${label} ---\n`);
|
|
53
|
+
const result = spawnSync(cmd, args, { stdio: 'inherit', ...opts });
|
|
54
|
+
if (result.status !== 0) {
|
|
55
|
+
process.exit(result.status ?? 1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const uiBundleDir = discoverUIBundleDir();
|
|
60
|
+
console.log('SFDX project root:', ROOT);
|
|
61
|
+
console.log('UI bundle directory:', uiBundleDir);
|
|
62
|
+
|
|
63
|
+
run('npm install', 'npm', ['install', '--registry', 'https://registry.npmjs.org/'], { cwd: uiBundleDir });
|
|
64
|
+
run('npm run build', 'npm', ['run', 'build'], { cwd: uiBundleDir });
|
|
65
|
+
console.log('\n--- Launching dev server (Ctrl+C to stop) ---\n');
|
|
66
|
+
run('npm run dev', 'npm', ['run', 'dev'], { cwd: uiBundleDir });
|