mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-07-30 03:09:50 +08:00
chore: sync React B2E & B2X (1.120.6) with uiBundle lockfiles and gitignore @W-21940169@ (#179)
chore: sync React B2E (1.120.6) & B2X (1.120.6) samples with lockfiles and gitignore Add package-lock.json generation for uiBundle directories and .gitignore writing to the sync scripts so they persist across syncs. Co-authored-by: gbockus-sf <76090802+gbockus-sf@users.noreply.github.com>
This commit is contained in:
parent
eaf5acdb7f
commit
574d8dcca2
44
package-lock.json
generated
44
package-lock.json
generated
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@salesforce/afv-skills",
|
||||
"version": "1.6.7",
|
||||
"version": "1.6.8",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@salesforce/afv-skills",
|
||||
"version": "1.6.7",
|
||||
"version": "1.6.8",
|
||||
"license": "CC-BY-NC-4.0",
|
||||
"devDependencies": {
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2e": "^1.120.3",
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2x": "^1.120.3",
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2e": "^1.120.6",
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2x": "^1.120.6",
|
||||
"@salesforce/webapp-template-app-react-sample-b2e-experimental": "^1.117.1",
|
||||
"@salesforce/webapp-template-app-react-sample-b2x-experimental": "^1.117.1",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
@ -690,22 +690,22 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@salesforce/sdk-core": {
|
||||
"version": "1.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/sdk-core/-/sdk-core-1.120.3.tgz",
|
||||
"integrity": "sha512-fzzQwWvN8GCK5peEf37sedsb1gBIHwiAOWXKrohPcwRjUd1wfhMoe45LvV8bOMgO4CBjKrNA21sf0D3FOLtzdQ==",
|
||||
"version": "1.120.6",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/sdk-core/-/sdk-core-1.120.6.tgz",
|
||||
"integrity": "sha512-yqd3Cf5hPzMJTy9GEsy9N41oFFIrcAOU/QuDDZ+nAmmXNmprM3kt93JCdhHr2L1P6JP2SHMhNMJQ1lKmSPl/uw==",
|
||||
"dev": true,
|
||||
"license": "SEE LICENSE IN LICENSE.txt"
|
||||
},
|
||||
"node_modules/@salesforce/sdk-data": {
|
||||
"version": "1.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/sdk-data/-/sdk-data-1.120.3.tgz",
|
||||
"integrity": "sha512-pw7Bx7Zo0K+apB+waxgbGpGigIsuoPmqDxbMIEdTepW/2/oxFx7RH7edG2qjjt96oHQcTCyPbNdzY/6HjC6TLw==",
|
||||
"version": "1.120.6",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/sdk-data/-/sdk-data-1.120.6.tgz",
|
||||
"integrity": "sha512-ejVCIU3EJTt2uv1kKx/3Jg98ESHbuG5zh+sn1Z4rfxtU/jVzeLZQyS3dIjw1krhSFIl9He+JU5EW8/s5W6aQSA==",
|
||||
"dev": true,
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"dependencies": {
|
||||
"@conduit-client/service-fetch-network": "3.17.0",
|
||||
"@conduit-client/utils": "3.17.0",
|
||||
"@salesforce/sdk-core": "^1.120.3"
|
||||
"@salesforce/sdk-core": "^1.120.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@salesforce/ts-types": {
|
||||
@ -719,14 +719,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@salesforce/ui-bundle": {
|
||||
"version": "1.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/ui-bundle/-/ui-bundle-1.120.3.tgz",
|
||||
"integrity": "sha512-rZAWPKRxTWwFbwudESFqromtF9OFIH7LcqrkJMkq0Wfdt6mRh3t+jVNg8z3Fj4aQf/BqpY4efLofmSnAhjABAQ==",
|
||||
"version": "1.120.6",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/ui-bundle/-/ui-bundle-1.120.6.tgz",
|
||||
"integrity": "sha512-sIHzbSMkMwvhh7IzAO/TzTMjIdphf8dTu+A4+LHobQ0XLp9Y0dii1ckMhLTb/i97qdCDq+aeIIKVQpRedgjsTw==",
|
||||
"dev": true,
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"dependencies": {
|
||||
"@salesforce/core": "^8.23.4",
|
||||
"@salesforce/sdk-data": "^1.120.3",
|
||||
"@salesforce/sdk-data": "^1.120.6",
|
||||
"micromatch": "^4.0.8",
|
||||
"path-to-regexp": "^8.3.0"
|
||||
},
|
||||
@ -735,20 +735,20 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@salesforce/ui-bundle-template-app-react-sample-b2e": {
|
||||
"version": "1.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/ui-bundle-template-app-react-sample-b2e/-/ui-bundle-template-app-react-sample-b2e-1.120.3.tgz",
|
||||
"integrity": "sha512-1Fn0gPRe4p91+nUptRgN1AcHCuYLe+ooQBSjJPdq/hVmU6E2oISIpntgDj7Z2FIc6O+F3DZDkGXyhcDs0B8j7w==",
|
||||
"version": "1.120.6",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/ui-bundle-template-app-react-sample-b2e/-/ui-bundle-template-app-react-sample-b2e-1.120.6.tgz",
|
||||
"integrity": "sha512-/A31Oon0gRvs+kshC55T2VoaEqDNfnwsSfJNfCi8Y4Y2UeGuMNtd4tvRrahQ6+QBup4NWUdOQNIwJWaXUWDC4A==",
|
||||
"dev": true,
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"dependencies": {
|
||||
"@salesforce/ui-bundle": "^1.120.3",
|
||||
"@salesforce/ui-bundle": "^1.120.6",
|
||||
"sonner": "^1.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@salesforce/ui-bundle-template-app-react-sample-b2x": {
|
||||
"version": "1.120.3",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/ui-bundle-template-app-react-sample-b2x/-/ui-bundle-template-app-react-sample-b2x-1.120.3.tgz",
|
||||
"integrity": "sha512-waF/yPAjnsM5y7RhcypNaj+WPiy1fD5FdYXPSQyZqngfc/SyVEqtuDr8J7l+pLjkyLoAAIBCRAA0I/uEQfxArQ==",
|
||||
"version": "1.120.6",
|
||||
"resolved": "https://registry.npmjs.org/@salesforce/ui-bundle-template-app-react-sample-b2x/-/ui-bundle-template-app-react-sample-b2x-1.120.6.tgz",
|
||||
"integrity": "sha512-j0joo4RYXM9OnVpZX4vb8nI/AMw9Uxz6xzm9o8KQ8WkU79P20xBdRTKBS1H379rpWV0KcxaMFBx6qGV82jgLNA==",
|
||||
"dev": true,
|
||||
"license": "SEE LICENSE IN LICENSE.txt"
|
||||
},
|
||||
|
||||
@ -11,8 +11,8 @@
|
||||
"registry": "https://registry.npmjs.org"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2e": "^1.120.3",
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2x": "^1.120.3",
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2e": "^1.120.6",
|
||||
"@salesforce/ui-bundle-template-app-react-sample-b2x": "^1.120.6",
|
||||
"@salesforce/webapp-template-app-react-sample-b2e-experimental": "^1.117.1",
|
||||
"@salesforce/webapp-template-app-react-sample-b2x-experimental": "^1.117.1",
|
||||
"@types/js-yaml": "^4.0.9",
|
||||
|
||||
45
samples/ui-bundle-template-app-react-sample-b2e/.gitignore
vendored
Normal file
45
samples/ui-bundle-template-app-react-sample-b2e/.gitignore
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
# This file is used for Git repositories to specify intentionally untracked files that Git should ignore.
|
||||
# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore
|
||||
# For useful gitignore templates see: https://github.com/github/gitignore
|
||||
|
||||
# Salesforce cache
|
||||
.sf/
|
||||
.sfdx/
|
||||
.localdevserver/
|
||||
deploy-options.json
|
||||
|
||||
# LWC VSCode autocomplete
|
||||
**/lwc/jsconfig.json
|
||||
|
||||
# LWC Jest coverage reports
|
||||
coverage/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Eslint cache
|
||||
.eslintcache
|
||||
|
||||
# MacOS system files
|
||||
.DS_Store
|
||||
|
||||
# Windows system files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Local environment variables
|
||||
.env
|
||||
|
||||
# Python Salesforce Functions
|
||||
**/__pycache__/
|
||||
**/.venv/
|
||||
**/venv/
|
||||
@ -1 +1 @@
|
||||
1.120.3
|
||||
1.120.6
|
||||
|
||||
@ -3,6 +3,33 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.120.6](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.5...v1.120.6) (2026-04-07)
|
||||
|
||||
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.120.5](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.4...v1.120.5) (2026-04-07)
|
||||
|
||||
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.120.4](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.3...v1.120.4) (2026-04-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make tenant owner of own record ([#414](https://github.com/salesforce-experience-platform-emu/webapps/issues/414)) ([bf1f289](https://github.com/salesforce-experience-platform-emu/webapps/commit/bf1f289a8d56a381adde51e642e67db38099f193))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.120.3](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.2...v1.120.3) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
||||
|
||||
@ -16,6 +16,7 @@ A property management sample React UI Bundle for the Salesforce platform. Demons
|
||||
- [6. Generate GraphQL Types](#6-generate-graphql-types)
|
||||
- [7. Rebuild the UI Bundle](#7-rebuild-the-ui-bundle)
|
||||
- [8. Deploy the UI Bundle](#8-deploy-the-ui-bundle)
|
||||
- [9. Agentforce Conversation Client](#9-agentforce-conversation-client)
|
||||
5. [Local Development](#local-development)
|
||||
6. [Resources](#resources)
|
||||
|
||||
@ -23,13 +24,14 @@ A property management sample React UI Bundle for the Salesforce platform. Demons
|
||||
|
||||
## What's Included
|
||||
|
||||
| Path | Description |
|
||||
| --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `force-app/main/default/uiBundles/propertymanagementapp/` | React UI Bundle (source, config, tests) |
|
||||
| `force-app/main/default/objects/` | 17 custom objects — `Agent__c`, `Application__c`, `KPI_Snapshot__c`, `Lease__c`, `Maintenance_Request__c`, `Maintenance_Worker__c`, `Notification__c`, `Payment__c`, `Property__c`, `Property_Cost__c`, `Property_Feature__c`, `Property_Image__c`, `Property_Listing__c`, `Property_Management_Company__c`, `Property_Owner__c`, `Property_Sale__c`, `Tenant__c` |
|
||||
| `force-app/main/default/layouts/` | Page layouts for each custom object |
|
||||
| `force-app/main/default/permissionsets/` | `Property_Management_Access` permission set — full CRUD access to all custom objects |
|
||||
| `force-app/main/default/data/` | Sample data (JSON) for all objects, importable via `sf data import tree` |
|
||||
```
|
||||
force-app/main/default/
|
||||
├── uiBundles/ # React UI Bundle (source, config, tests)
|
||||
├── objects/ # 17 Custom Objects (Property, Tenant, Lease, etc.)
|
||||
├── layouts/ # Page layouts for all custom objects
|
||||
├── permissionsets/ # Property_Management_Access (Full CRUD)
|
||||
└── data/ # Sample JSON data (use: sf data import tree)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -224,6 +226,13 @@ Once the build is complete, deploy the UI Bundle to your org:
|
||||
sf project deploy start --source-dir force-app/main/default/uiBundles --target-org <alias>
|
||||
```
|
||||
|
||||
### 9. Agentforce Conversation Client
|
||||
|
||||
The sample app includes an Agentforce Conversation Client (ACC) placeholder component in `applayout.tsx`. The ACC component requires a valid `agentId` for an agent that exists in the org. The options to create an agent specific to this use-case are:
|
||||
|
||||
- **Agentforce Vibes:** Generate agent metadata with the extension, then deploy it to the org.
|
||||
- **Agentforce Builder:** Create the agent in the UI. See [Set Up Your Agent](https://help.salesforce.com/s/articleView?id=ai.agent_parent_setup.htm&type=5).
|
||||
|
||||
---
|
||||
|
||||
## Local Development
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"permsetAssignments": {
|
||||
"defaultAssignee": "skip",
|
||||
"assignments": {
|
||||
"Property_Management_Access": { "assignee": "currentUser" },
|
||||
"Tenant_Maintenance_Access": { "assignee": "currentUser" }
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,8 @@
|
||||
"graphql:schema": "node scripts/get-graphql-schema.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@salesforce/sdk-data": "^1.120.3",
|
||||
"@salesforce/ui-bundle": "^1.120.3",
|
||||
"@salesforce/sdk-data": "^1.120.6",
|
||||
"@salesforce/ui-bundle": "^1.120.6",
|
||||
"@tailwindcss/vite": "^4.1.17",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@ -46,7 +46,7 @@
|
||||
"@graphql-eslint/eslint-plugin": "^4.1.0",
|
||||
"@graphql-tools/utils": "^11.0.0",
|
||||
"@playwright/test": "^1.49.0",
|
||||
"@salesforce/vite-plugin-ui-bundle": "^1.120.3",
|
||||
"@salesforce/vite-plugin-ui-bundle": "^1.120.6",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.1.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
@ -69,5 +69,8 @@
|
||||
"vite": "^7.2.4",
|
||||
"vite-plugin-graphql-codegen": "^3.6.3",
|
||||
"vitest": "^4.0.17"
|
||||
},
|
||||
"overrides": {
|
||||
"lodash": "^4.18.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,6 +113,7 @@ async function ensureTenantForApprovedApplication(applicationId: string): Promis
|
||||
Property__c: propertyId,
|
||||
User_Status__c: "Tenant",
|
||||
Status__c: "Active",
|
||||
OwnerId: userId,
|
||||
};
|
||||
if (startDate) {
|
||||
tenantFields.Start_Date__c = String(startDate);
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@salesforce/webapp-template-base-sfdx-project-experimental",
|
||||
"version": "1.120.3",
|
||||
"version": "1.120.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@salesforce/webapp-template-base-sfdx-project-experimental",
|
||||
"version": "1.120.3",
|
||||
"version": "1.120.6",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"devDependencies": {
|
||||
"@lwc/eslint-plugin-lwc": "^3.3.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@salesforce/ui-bundle-template-base-sfdx-project",
|
||||
"version": "1.120.3",
|
||||
"version": "1.120.6",
|
||||
"description": "Base SFDX project template",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"publishConfig": {
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"permsetAssignments": {
|
||||
"defaultAssignee": "currentUser",
|
||||
"assignments": {}
|
||||
}
|
||||
}
|
||||
@ -14,10 +14,22 @@
|
||||
* 1. login — sf org login web only if org not already connected (skip with --skip-login)
|
||||
* 2. uiBundle — (all UI bundles) npm install && npm run build so dist exists for deploy (skip with --skip-ui-bundle-build)
|
||||
* 3. deploy — sf project deploy start --target-org <alias> (requires dist for entity deployment)
|
||||
* 4. permset — sf org assign permset for each *.permissionset-meta.xml (skip with --skip-permset; override via --permset-name)
|
||||
* 4. permset — assign permsets per org-setup.config.json (skip with --skip-permset; override via --permset-name)
|
||||
* 5. data — prepare unique fields + sf data import tree (skipped if no data dir/plan)
|
||||
* 6. graphql — (in UI bundle) npm run graphql:schema then npm run graphql:codegen
|
||||
* 7. dev — (in UI bundle) npm run dev — launch dev server (skip with --skip-dev)
|
||||
*
|
||||
* Permset assignment config (scripts/org-setup.config.json):
|
||||
* {
|
||||
* "permsetAssignments": {
|
||||
* "defaultAssignee": "currentUser",
|
||||
* "assignments": {
|
||||
* "Guest_Permset": { "assignee": "guest@mysite.example.com" },
|
||||
* "Internal_Only": { "assignee": "skip" }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* Assignee values: "currentUser" (default), "skip", or a specific username.
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
@ -127,6 +139,20 @@ Options:
|
||||
--skip-dev Do not launch the dev server at the end
|
||||
-y, --yes Skip interactive step picker; run all enabled steps immediately
|
||||
-h, --help Show this help
|
||||
|
||||
Permset config (scripts/org-setup.config.json):
|
||||
Control per-permset assignment via a config file. Example:
|
||||
{
|
||||
"permsetAssignments": {
|
||||
"defaultAssignee": "currentUser",
|
||||
"assignments": {
|
||||
"Guest_Permset": { "assignee": "guest@mysite.example.com" },
|
||||
"Internal_Only": { "assignee": "skip" }
|
||||
}
|
||||
}
|
||||
}
|
||||
Assignee values: "currentUser" (default), "skip", or a specific username.
|
||||
Without this file, all discovered permsets are assigned to the current user.
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
@ -181,6 +207,51 @@ function discoverPermissionSetNames() {
|
||||
return names.sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load permset assignment configuration from org-setup.config.json.
|
||||
*
|
||||
* Config shape:
|
||||
* {
|
||||
* "permsetAssignments": {
|
||||
* "defaultAssignee": "currentUser", // "currentUser" (default) or "skip"
|
||||
* "assignments": {
|
||||
* "My_Guest_Permset": { "assignee": "guest@mysite.example.com" },
|
||||
* "Internal_Only": { "assignee": "skip" }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Assignee values:
|
||||
* "currentUser" — assign to the user running the script (default)
|
||||
* "skip" — do not assign this permset
|
||||
* "<username>" — assign to a specific user via --on-behalf-of
|
||||
*
|
||||
* Returns { defaultAssignee: string, assignments: Record<string, { assignee: string }> }
|
||||
*/
|
||||
function loadPermsetConfig() {
|
||||
const configPath = resolve(__dirname, 'org-setup.config.json');
|
||||
const defaults = { defaultAssignee: 'currentUser', assignments: {} };
|
||||
if (!existsSync(configPath)) return defaults;
|
||||
try {
|
||||
const raw = JSON.parse(readFileSync(configPath, 'utf8'));
|
||||
const section = raw?.permsetAssignments;
|
||||
if (!section) return defaults;
|
||||
return {
|
||||
defaultAssignee: section.defaultAssignee || 'currentUser',
|
||||
assignments: section.assignments || {},
|
||||
};
|
||||
} catch (err) {
|
||||
console.warn(`Warning: failed to parse org-setup.config.json: ${err.message}; using defaults.`);
|
||||
return defaults;
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve the effective assignee for a given permset name. */
|
||||
function resolveAssignee(permsetName, permsetConfig) {
|
||||
const override = permsetConfig.assignments[permsetName];
|
||||
return override?.assignee || permsetConfig.defaultAssignee;
|
||||
}
|
||||
|
||||
function isOrgConnected(targetOrg) {
|
||||
const result = spawnSync('sf', ['org', 'display', '--target-org', targetOrg, '--json'], {
|
||||
cwd: ROOT,
|
||||
@ -422,28 +493,35 @@ async function main() {
|
||||
}
|
||||
|
||||
if (!skipPermset) {
|
||||
const permsetConfig = loadPermsetConfig();
|
||||
if (permsetNames.length === 0) {
|
||||
console.log('\n--- Assign permission sets ---');
|
||||
console.log('No permission sets found under permissionsets/ and none passed via --permset-name; skipping.');
|
||||
} else {
|
||||
console.log('\n--- Assign permission sets ---');
|
||||
for (const permsetName of permsetNames) {
|
||||
const permsetResult = spawnSync(
|
||||
'sf',
|
||||
['org', 'assign', 'permset', '--name', permsetName, '--target-org', targetOrg],
|
||||
{
|
||||
cwd: ROOT,
|
||||
stdio: 'pipe',
|
||||
shell: true,
|
||||
}
|
||||
);
|
||||
const assignee = resolveAssignee(permsetName, permsetConfig);
|
||||
if (assignee === 'skip') {
|
||||
console.log(`Permission set "${permsetName}" — skipped (config).`);
|
||||
continue;
|
||||
}
|
||||
const sfArgs = ['org', 'assign', 'permset', '--name', permsetName, '--target-org', targetOrg];
|
||||
if (assignee !== 'currentUser') {
|
||||
sfArgs.push('--on-behalf-of', assignee);
|
||||
}
|
||||
const assigneeLabel = assignee === 'currentUser' ? 'current user' : assignee;
|
||||
const permsetResult = spawnSync('sf', sfArgs, {
|
||||
cwd: ROOT,
|
||||
stdio: 'pipe',
|
||||
shell: true,
|
||||
});
|
||||
if (permsetResult.status === 0) {
|
||||
console.log(`Permission set "${permsetName}" assigned.`);
|
||||
console.log(`Permission set "${permsetName}" assigned to ${assigneeLabel}.`);
|
||||
} else {
|
||||
const out =
|
||||
(permsetResult.stderr?.toString() || '') + (permsetResult.stdout?.toString() || '');
|
||||
if (out.includes('Duplicate') && out.includes('PermissionSet')) {
|
||||
console.log(`Permission set "${permsetName}" already assigned; skipping.`);
|
||||
console.log(`Permission set "${permsetName}" already assigned to ${assigneeLabel}; skipping.`);
|
||||
} else if (out.includes('not found') && out.includes('target org')) {
|
||||
console.log(`Permission set "${permsetName}" not in org; skipping.`);
|
||||
} else {
|
||||
|
||||
45
samples/ui-bundle-template-app-react-sample-b2x/.gitignore
vendored
Normal file
45
samples/ui-bundle-template-app-react-sample-b2x/.gitignore
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
# This file is used for Git repositories to specify intentionally untracked files that Git should ignore.
|
||||
# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore
|
||||
# For useful gitignore templates see: https://github.com/github/gitignore
|
||||
|
||||
# Salesforce cache
|
||||
.sf/
|
||||
.sfdx/
|
||||
.localdevserver/
|
||||
deploy-options.json
|
||||
|
||||
# LWC VSCode autocomplete
|
||||
**/lwc/jsconfig.json
|
||||
|
||||
# LWC Jest coverage reports
|
||||
coverage/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Eslint cache
|
||||
.eslintcache
|
||||
|
||||
# MacOS system files
|
||||
.DS_Store
|
||||
|
||||
# Windows system files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Local environment variables
|
||||
.env
|
||||
|
||||
# Python Salesforce Functions
|
||||
**/__pycache__/
|
||||
**/.venv/
|
||||
**/venv/
|
||||
@ -1 +1 @@
|
||||
1.120.3
|
||||
1.120.6
|
||||
|
||||
@ -3,6 +3,33 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.120.6](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.5...v1.120.6) (2026-04-07)
|
||||
|
||||
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.120.5](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.4...v1.120.5) (2026-04-07)
|
||||
|
||||
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.120.4](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.3...v1.120.4) (2026-04-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make tenant owner of own record ([#414](https://github.com/salesforce-experience-platform-emu/webapps/issues/414)) ([bf1f289](https://github.com/salesforce-experience-platform-emu/webapps/commit/bf1f289a8d56a381adde51e642e67db38099f193))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.120.3](https://github.com/salesforce-experience-platform-emu/webapps/compare/v1.120.2...v1.120.3) (2026-04-02)
|
||||
|
||||
**Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
|
||||
|
||||
@ -29,20 +29,25 @@ A property rental sample React UI Bundle for Salesforce Experience Cloud. Demons
|
||||
|
||||
## What's Included
|
||||
|
||||
| Path | Description |
|
||||
| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `force-app/main/default/uiBundles/propertyrentalapp/` | React UI Bundle (source, config, tests) |
|
||||
| `force-app/main/default/objects/` | 17 custom objects — `Agent__c`, `Application__c`, `KPI_Snapshot__c`, `Lease__c`, `Maintenance_Request__c`, `Maintenance_Worker__c`, `Notification__c`, `Payment__c`, `Property__c`, `Property_Cost__c`, `Property_Feature__c`, `Property_Image__c`, `Property_Listing__c`, `Property_Management_Company__c`, `Property_Owner__c`, `Property_Sale__c`, `Tenant__c` |
|
||||
| `force-app/main/default/layouts/` | Page layouts for each custom object |
|
||||
| `force-app/main/default/permissionsets/` | `Property_Management_Access` (full admin access) and `Tenant_Maintenance_Access` (scoped tenant access) |
|
||||
| `force-app/main/default/classes/` | Apex classes — `MaintenanceRequestTriggerHandler`, `TenantTriggerHandler`, `UIBundleAuthUtils`, `UIBundleChangePassword`, `UIBundleForgotPassword`, `UIBundleLogin`, `UIBundleAppRegistration` |
|
||||
| `force-app/main/default/triggers/` | Apex triggers — `MaintenanceRequestTrigger`, `TenantTrigger` |
|
||||
| `force-app/main/default/cspTrustedSites/` | CSP trusted sites for external resources (Google Fonts, Pexels, Unsplash, GitHub Avatars, OpenStreetMap, Open-Meteo) |
|
||||
| `force-app/main/default/data/` | Sample data (JSON) for all objects, importable via `sf data import tree` |
|
||||
| `force-app/main/default/digitalExperienceConfigs/` | Experience Cloud site configuration |
|
||||
| `force-app/main/default/digitalExperiences/` | Experience Cloud site definition |
|
||||
| `force-app/main/default/networks/` | Experience Cloud network metadata |
|
||||
| `force-app/main/default/sites/` | Salesforce Sites configuration |
|
||||
```
|
||||
force-app/main/default/
|
||||
├── classes/ # Apex Logic: Triggers, Auth, and Registration
|
||||
│ ├── MaintenanceRequestTriggerHandler.cls
|
||||
│ ├── TenantTriggerHandler.cls
|
||||
│ └── UIBundle (Auth, Login, Registration, etc.)
|
||||
├── cspTrustedSites/ # External resource security (Maps, Fonts, Avatars)
|
||||
├── data/ # Sample JSON data for "sf data import tree"
|
||||
├── digitalExperienceConfigs/ # Experience Cloud site configurations
|
||||
├── digitalExperiences/ # Experience Cloud site definitions
|
||||
├── layouts/ # Page layouts for all 17 custom objects
|
||||
├── networks/ # Experience Cloud network metadata
|
||||
├── objects/ # 17 Custom Objects (Property, Tenant, Lease, etc.)
|
||||
├── permissionsets/ # Access: Property_Management (Admin) & Tenant (Scoped)
|
||||
├── sites/ # Salesforce Sites configuration
|
||||
├── triggers/ # Apex Triggers: MaintenanceRequest & Tenant
|
||||
└── uiBundles/
|
||||
└── propertyrentalapp/ # React UI Bundle (source, config, tests)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@ -462,7 +467,7 @@ By default, Salesforce does not expose any records to guest users. You must crea
|
||||
2. Scroll to the **Property Sharing Rules** section and click **New**.
|
||||
3. Configure the rule:
|
||||
- **Label**: `Available Properties for Guest Users`
|
||||
- **Rule Type**: Select **Based on criteria**
|
||||
- **Rule Type**: Select **Guest user access, based on criteria**
|
||||
- **Criteria**: `Status Equals Available` (adjust the field and value to match your data model)
|
||||
- **Share with**: Select **Guests of the Property Rental App site** (the guest user group for your Experience Cloud site)
|
||||
- **Access Level**: `Read Only`
|
||||
@ -473,7 +478,7 @@ By default, Salesforce does not expose any records to guest users. You must crea
|
||||
Repeat the same steps in the **Property Listing Sharing Rules** section:
|
||||
|
||||
- **Label**: `Available Property Listings for Guest Users`
|
||||
- **Rule Type**: `Based on criteria`
|
||||
- **Rule Type**: `Guest user access, based on criteria`
|
||||
- **Criteria**: Match listings you want to expose (e.g., `Status Equals Active`)
|
||||
- **Share with**: `Guests of the Property Rental App site`
|
||||
- **Access Level**: `Read Only`
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"permsetAssignments": {
|
||||
"defaultAssignee": "skip",
|
||||
"assignments": {
|
||||
"Property_Management_Access": { "assignee": "currentUser" },
|
||||
"Tenant_Maintenance_Access": { "assignee": "currentUser" }
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -18,8 +18,8 @@
|
||||
"graphql:schema": "node scripts/get-graphql-schema.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@salesforce/sdk-data": "^1.120.3",
|
||||
"@salesforce/ui-bundle": "^1.120.3",
|
||||
"@salesforce/sdk-data": "^1.120.6",
|
||||
"@salesforce/ui-bundle": "^1.120.6",
|
||||
"@tailwindcss/vite": "^4.1.17",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@ -50,7 +50,7 @@
|
||||
"@graphql-eslint/eslint-plugin": "^4.1.0",
|
||||
"@graphql-tools/utils": "^11.0.0",
|
||||
"@playwright/test": "^1.49.0",
|
||||
"@salesforce/vite-plugin-ui-bundle": "^1.120.3",
|
||||
"@salesforce/vite-plugin-ui-bundle": "^1.120.6",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.1.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
@ -73,5 +73,8 @@
|
||||
"vite": "^7.2.4",
|
||||
"vite-plugin-graphql-codegen": "^3.6.3",
|
||||
"vitest": "^4.0.17"
|
||||
},
|
||||
"overrides": {
|
||||
"lodash": "^4.18.1"
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@salesforce/webapp-template-base-sfdx-project-experimental",
|
||||
"version": "1.120.3",
|
||||
"version": "1.120.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@salesforce/webapp-template-base-sfdx-project-experimental",
|
||||
"version": "1.120.3",
|
||||
"version": "1.120.6",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"devDependencies": {
|
||||
"@lwc/eslint-plugin-lwc": "^3.3.0",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@salesforce/ui-bundle-template-base-sfdx-project",
|
||||
"version": "1.120.3",
|
||||
"version": "1.120.6",
|
||||
"description": "Base SFDX project template",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"publishConfig": {
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"permsetAssignments": {
|
||||
"defaultAssignee": "currentUser",
|
||||
"assignments": {}
|
||||
}
|
||||
}
|
||||
@ -14,10 +14,22 @@
|
||||
* 1. login — sf org login web only if org not already connected (skip with --skip-login)
|
||||
* 2. uiBundle — (all UI bundles) npm install && npm run build so dist exists for deploy (skip with --skip-ui-bundle-build)
|
||||
* 3. deploy — sf project deploy start --target-org <alias> (requires dist for entity deployment)
|
||||
* 4. permset — sf org assign permset for each *.permissionset-meta.xml (skip with --skip-permset; override via --permset-name)
|
||||
* 4. permset — assign permsets per org-setup.config.json (skip with --skip-permset; override via --permset-name)
|
||||
* 5. data — prepare unique fields + sf data import tree (skipped if no data dir/plan)
|
||||
* 6. graphql — (in UI bundle) npm run graphql:schema then npm run graphql:codegen
|
||||
* 7. dev — (in UI bundle) npm run dev — launch dev server (skip with --skip-dev)
|
||||
*
|
||||
* Permset assignment config (scripts/org-setup.config.json):
|
||||
* {
|
||||
* "permsetAssignments": {
|
||||
* "defaultAssignee": "currentUser",
|
||||
* "assignments": {
|
||||
* "Guest_Permset": { "assignee": "guest@mysite.example.com" },
|
||||
* "Internal_Only": { "assignee": "skip" }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* Assignee values: "currentUser" (default), "skip", or a specific username.
|
||||
*/
|
||||
|
||||
import { spawnSync } from 'node:child_process';
|
||||
@ -127,6 +139,20 @@ Options:
|
||||
--skip-dev Do not launch the dev server at the end
|
||||
-y, --yes Skip interactive step picker; run all enabled steps immediately
|
||||
-h, --help Show this help
|
||||
|
||||
Permset config (scripts/org-setup.config.json):
|
||||
Control per-permset assignment via a config file. Example:
|
||||
{
|
||||
"permsetAssignments": {
|
||||
"defaultAssignee": "currentUser",
|
||||
"assignments": {
|
||||
"Guest_Permset": { "assignee": "guest@mysite.example.com" },
|
||||
"Internal_Only": { "assignee": "skip" }
|
||||
}
|
||||
}
|
||||
}
|
||||
Assignee values: "currentUser" (default), "skip", or a specific username.
|
||||
Without this file, all discovered permsets are assigned to the current user.
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
@ -181,6 +207,51 @@ function discoverPermissionSetNames() {
|
||||
return names.sort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load permset assignment configuration from org-setup.config.json.
|
||||
*
|
||||
* Config shape:
|
||||
* {
|
||||
* "permsetAssignments": {
|
||||
* "defaultAssignee": "currentUser", // "currentUser" (default) or "skip"
|
||||
* "assignments": {
|
||||
* "My_Guest_Permset": { "assignee": "guest@mysite.example.com" },
|
||||
* "Internal_Only": { "assignee": "skip" }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Assignee values:
|
||||
* "currentUser" — assign to the user running the script (default)
|
||||
* "skip" — do not assign this permset
|
||||
* "<username>" — assign to a specific user via --on-behalf-of
|
||||
*
|
||||
* Returns { defaultAssignee: string, assignments: Record<string, { assignee: string }> }
|
||||
*/
|
||||
function loadPermsetConfig() {
|
||||
const configPath = resolve(__dirname, 'org-setup.config.json');
|
||||
const defaults = { defaultAssignee: 'currentUser', assignments: {} };
|
||||
if (!existsSync(configPath)) return defaults;
|
||||
try {
|
||||
const raw = JSON.parse(readFileSync(configPath, 'utf8'));
|
||||
const section = raw?.permsetAssignments;
|
||||
if (!section) return defaults;
|
||||
return {
|
||||
defaultAssignee: section.defaultAssignee || 'currentUser',
|
||||
assignments: section.assignments || {},
|
||||
};
|
||||
} catch (err) {
|
||||
console.warn(`Warning: failed to parse org-setup.config.json: ${err.message}; using defaults.`);
|
||||
return defaults;
|
||||
}
|
||||
}
|
||||
|
||||
/** Resolve the effective assignee for a given permset name. */
|
||||
function resolveAssignee(permsetName, permsetConfig) {
|
||||
const override = permsetConfig.assignments[permsetName];
|
||||
return override?.assignee || permsetConfig.defaultAssignee;
|
||||
}
|
||||
|
||||
function isOrgConnected(targetOrg) {
|
||||
const result = spawnSync('sf', ['org', 'display', '--target-org', targetOrg, '--json'], {
|
||||
cwd: ROOT,
|
||||
@ -422,28 +493,35 @@ async function main() {
|
||||
}
|
||||
|
||||
if (!skipPermset) {
|
||||
const permsetConfig = loadPermsetConfig();
|
||||
if (permsetNames.length === 0) {
|
||||
console.log('\n--- Assign permission sets ---');
|
||||
console.log('No permission sets found under permissionsets/ and none passed via --permset-name; skipping.');
|
||||
} else {
|
||||
console.log('\n--- Assign permission sets ---');
|
||||
for (const permsetName of permsetNames) {
|
||||
const permsetResult = spawnSync(
|
||||
'sf',
|
||||
['org', 'assign', 'permset', '--name', permsetName, '--target-org', targetOrg],
|
||||
{
|
||||
cwd: ROOT,
|
||||
stdio: 'pipe',
|
||||
shell: true,
|
||||
}
|
||||
);
|
||||
const assignee = resolveAssignee(permsetName, permsetConfig);
|
||||
if (assignee === 'skip') {
|
||||
console.log(`Permission set "${permsetName}" — skipped (config).`);
|
||||
continue;
|
||||
}
|
||||
const sfArgs = ['org', 'assign', 'permset', '--name', permsetName, '--target-org', targetOrg];
|
||||
if (assignee !== 'currentUser') {
|
||||
sfArgs.push('--on-behalf-of', assignee);
|
||||
}
|
||||
const assigneeLabel = assignee === 'currentUser' ? 'current user' : assignee;
|
||||
const permsetResult = spawnSync('sf', sfArgs, {
|
||||
cwd: ROOT,
|
||||
stdio: 'pipe',
|
||||
shell: true,
|
||||
});
|
||||
if (permsetResult.status === 0) {
|
||||
console.log(`Permission set "${permsetName}" assigned.`);
|
||||
console.log(`Permission set "${permsetName}" assigned to ${assigneeLabel}.`);
|
||||
} else {
|
||||
const out =
|
||||
(permsetResult.stderr?.toString() || '') + (permsetResult.stdout?.toString() || '');
|
||||
if (out.includes('Duplicate') && out.includes('PermissionSet')) {
|
||||
console.log(`Permission set "${permsetName}" already assigned; skipping.`);
|
||||
console.log(`Permission set "${permsetName}" already assigned to ${assigneeLabel}; skipping.`);
|
||||
} else if (out.includes('not found') && out.includes('target org')) {
|
||||
console.log(`Permission set "${permsetName}" not in org; skipping.`);
|
||||
} else {
|
||||
|
||||
@ -68,6 +68,61 @@ if (fs.existsSync(licensePath)) {
|
||||
fs.copyFileSync(licensePath, path.join(SAMPLE_DIR, 'LICENSE.txt'));
|
||||
}
|
||||
|
||||
// Write .gitignore for the sample project
|
||||
const gitignoreContent = `# This file is used for Git repositories to specify intentionally untracked files that Git should ignore.
|
||||
# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore
|
||||
# For useful gitignore templates see: https://github.com/github/gitignore
|
||||
|
||||
# Salesforce cache
|
||||
.sf/
|
||||
.sfdx/
|
||||
.localdevserver/
|
||||
deploy-options.json
|
||||
|
||||
# LWC VSCode autocomplete
|
||||
**/lwc/jsconfig.json
|
||||
|
||||
# LWC Jest coverage reports
|
||||
coverage/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Eslint cache
|
||||
.eslintcache
|
||||
|
||||
# MacOS system files
|
||||
.DS_Store
|
||||
|
||||
# Windows system files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Local environment variables
|
||||
.env
|
||||
|
||||
# Python Salesforce Functions
|
||||
**/__pycache__/
|
||||
**/.venv/
|
||||
**/venv/
|
||||
`;
|
||||
fs.writeFileSync(path.join(SAMPLE_DIR, '.gitignore'), gitignoreContent, 'utf8');
|
||||
|
||||
// Generate package-lock.json for the uiBundle
|
||||
const { execSync } = require('child_process');
|
||||
const uiBundleDir = path.join(SAMPLE_DIR, 'force-app', 'main', 'default', 'uiBundles', 'propertymanagementapp');
|
||||
console.log(`Generating package-lock.json for uiBundles/propertymanagementapp`);
|
||||
execSync('npm install --package-lock-only --ignore-scripts', { cwd: uiBundleDir, stdio: 'inherit' });
|
||||
|
||||
// Write .version for version tracking (used by workflow and local)
|
||||
fs.writeFileSync(path.join(SAMPLE_DIR, '.version'), version + '\n', 'utf8');
|
||||
|
||||
|
||||
@ -68,6 +68,61 @@ if (fs.existsSync(licensePath)) {
|
||||
fs.copyFileSync(licensePath, path.join(SAMPLE_DIR, 'LICENSE.txt'));
|
||||
}
|
||||
|
||||
// Write .gitignore for the sample project
|
||||
const gitignoreContent = `# This file is used for Git repositories to specify intentionally untracked files that Git should ignore.
|
||||
# If you are not using git, you can delete this file. For more information see: https://git-scm.com/docs/gitignore
|
||||
# For useful gitignore templates see: https://github.com/github/gitignore
|
||||
|
||||
# Salesforce cache
|
||||
.sf/
|
||||
.sfdx/
|
||||
.localdevserver/
|
||||
deploy-options.json
|
||||
|
||||
# LWC VSCode autocomplete
|
||||
**/lwc/jsconfig.json
|
||||
|
||||
# LWC Jest coverage reports
|
||||
coverage/
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Eslint cache
|
||||
.eslintcache
|
||||
|
||||
# MacOS system files
|
||||
.DS_Store
|
||||
|
||||
# Windows system files
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
[Dd]esktop.ini
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Local environment variables
|
||||
.env
|
||||
|
||||
# Python Salesforce Functions
|
||||
**/__pycache__/
|
||||
**/.venv/
|
||||
**/venv/
|
||||
`;
|
||||
fs.writeFileSync(path.join(SAMPLE_DIR, '.gitignore'), gitignoreContent, 'utf8');
|
||||
|
||||
// Generate package-lock.json for the uiBundle
|
||||
const { execSync } = require('child_process');
|
||||
const uiBundleDir = path.join(SAMPLE_DIR, 'force-app', 'main', 'default', 'uiBundles', 'propertyrentalapp');
|
||||
console.log(`Generating package-lock.json for uiBundles/propertyrentalapp`);
|
||||
execSync('npm install --package-lock-only --ignore-scripts', { cwd: uiBundleDir, stdio: 'inherit' });
|
||||
|
||||
// Write .version for version tracking (used by workflow and local)
|
||||
fs.writeFileSync(path.join(SAMPLE_DIR, '.version'), version + '\n', 'utf8');
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user