@salesforce/ui-bundle-template-app-react-sample-b2x 11.1.0 → 11.1.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/dist/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [11.1.2](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.1.1...v11.1.2) (2026-06-29)
7
+
8
+ **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
9
+
10
+
11
+
12
+
13
+
14
+ ## [11.1.1](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.1.0...v11.1.1) (2026-06-29)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **template:** consolidate per-app data prep into feature package @W-22910624@ ([#677](https://github.com/salesforce-experience-platform-emu/webapps/issues/677)) ([6a98367](https://github.com/salesforce-experience-platform-emu/webapps/commit/6a98367b5c3542bb4fd5090ba3fbcf7b12b71616))
20
+
21
+
22
+
6
23
  ## [11.1.0](https://github.com/salesforce-experience-platform-emu/webapps/compare/v11.0.0...v11.1.0) (2026-06-26)
7
24
 
8
25
  **Note:** Version bump only for package @salesforce/ui-bundle-template-base-sfdx-project
@@ -1,85 +1,156 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Updates unique fields in data JSON files so "sf data import tree" can be run
4
- * repeatedly (e.g. after org already has data). Run before: node prepare-import-unique-fields.js
3
+ * Property-management seed-data prep for "sf data import tree".
4
+ *
5
+ * Ships alongside this feature's seed data so it can be run repeatedly (e.g.
6
+ * after the org already has data) without hitting duplicate rules, and so all
7
+ * @-references resolve. org-setup.mjs invokes whatever prepare script lives in
8
+ * the app's data dir — the generic template script carries no object-specific
9
+ * logic.
10
+ *
11
+ * Usage:
12
+ * node prepare-import-unique-fields.js
13
+ * node prepare-import-unique-fields.js --data-dir /path/to/<sfdx-source>/data
14
+ *
15
+ * Operates on (each optional — missing files are skipped):
16
+ * Contact.json (Email unique domain+local, LastName, FirstName, Phone)
17
+ * Agent__c.json (License_Number__c — unique per record)
18
+ * Property_Management_Company__c.json (Company_Code__c, max 10 chars)
19
+ * Property_Owner__c.json (Email__c)
20
+ * Lease__c.json (Tenant__c → @TenantRef remapped into Tenant__c.json's refs)
21
+ * Maintenance_Request__c.json (User__c → @TenantRef remapped likewise)
5
22
  */
23
+
6
24
  const fs = require("fs");
7
25
  const path = require("path");
8
- const dataDir = __dirname;
26
+
27
+ function parseArgs() {
28
+ const args = process.argv.slice(2);
29
+ let dataDir = __dirname;
30
+ for (let i = 0; i < args.length; i++) {
31
+ if (args[i] === "--data-dir" && args[i + 1]) {
32
+ dataDir = path.resolve(args[++i]);
33
+ break;
34
+ }
35
+ }
36
+ return dataDir;
37
+ }
38
+
39
+ const dataDir = parseArgs();
9
40
  const runId = Date.now();
10
41
  const runSuffix2 = String(runId % 100).padStart(2, "0"); // 00-99 for Company_Code__c (10-char limit)
11
42
 
12
- // Contact: Email + LastName unique so re-runs don't hit DUPLICATES_DETECTED (matching may use name)
43
+ // Contact: Email (unique domain + local), LastName, FirstName, Phone avoid duplicate rules
13
44
  const contactPath = path.join(dataDir, "Contact.json");
14
- let contact = JSON.parse(fs.readFileSync(contactPath, "utf8"));
15
- contact.records.forEach((r, i) => {
16
- if (r.Email && r.Email.includes("@"))
17
- r.Email = r.Email.replace(/\+[0-9]+@/, "@").replace("@", "+" + runId + "@");
18
- if (r.LastName)
19
- r.LastName = r.LastName.replace(/\s*\[[0-9-]+\]$/, "") + " [" + runId + "-" + i + "]";
20
- });
21
- fs.writeFileSync(contactPath, JSON.stringify(contact, null, 2));
45
+ if (fs.existsSync(contactPath)) {
46
+ let contact = JSON.parse(fs.readFileSync(contactPath, "utf8"));
47
+ if (contact.records) {
48
+ contact.records.forEach((r, i) => {
49
+ if (r.Email && r.Email.includes("@")) {
50
+ const parts = r.Email.replace(/\+[0-9]+@/, "@").split("@");
51
+ const local = (parts[0] || "user") + "+" + runId;
52
+ const domain = "run" + runId + ".example.com";
53
+ r.Email = local + "@" + domain;
54
+ }
55
+ if (r.LastName) r.LastName = String(r.LastName).replace(/-[0-9]+$/, "") + "-" + runId;
56
+ if (r.FirstName) r.FirstName = String(r.FirstName).replace(/-[0-9]+$/, "") + "-" + (i + 1);
57
+ if (r.Phone) r.Phone = String(r.Phone).replace(/\d{2}$/, runSuffix2);
58
+ });
59
+ fs.writeFileSync(contactPath, JSON.stringify(contact, null, 2));
60
+ console.log("Updated Contact.json (Email, LastName, FirstName, Phone)");
61
+ }
62
+ }
22
63
 
23
- // Agent__c: License_Number__c — strip any existing suffix and add run id + index (each record must be unique)
64
+ // Agent__c: License_Number__c — unique per record (field is often unique in org)
24
65
  const agentPath = path.join(dataDir, "Agent__c.json");
25
- let agent = JSON.parse(fs.readFileSync(agentPath, "utf8"));
26
- agent.records.forEach((r, i) => {
27
- if (r.License_Number__c)
28
- r.License_Number__c =
29
- r.License_Number__c.replace(/-[0-9]+(-[0-9]+)?$/, "") + "-" + runId + "-" + i;
30
- });
31
- fs.writeFileSync(agentPath, JSON.stringify(agent, null, 2));
66
+ if (fs.existsSync(agentPath)) {
67
+ let agent = JSON.parse(fs.readFileSync(agentPath, "utf8"));
68
+ if (agent.records) {
69
+ agent.records.forEach((r, i) => {
70
+ if (r.License_Number__c) {
71
+ const base = r.License_Number__c.replace(/-[0-9]+(-[0-9]+)?$/, "");
72
+ r.License_Number__c = base + "-" + runId + "-" + (i + 1);
73
+ }
74
+ });
75
+ fs.writeFileSync(agentPath, JSON.stringify(agent, null, 2));
76
+ console.log("Updated Agent__c.json (License_Number__c)");
77
+ }
78
+ }
32
79
 
33
80
  // Property_Management_Company__c: Company_Code__c — max 10 chars, use 8-char base + 2-digit suffix
34
81
  const companyPath = path.join(dataDir, "Property_Management_Company__c.json");
35
- let company = JSON.parse(fs.readFileSync(companyPath, "utf8"));
36
- company.records.forEach((r) => {
37
- if (r.Company_Code__c) r.Company_Code__c = r.Company_Code__c.slice(0, 8) + runSuffix2; // 8-char base + 2-digit = 10 chars max
38
- });
39
- fs.writeFileSync(companyPath, JSON.stringify(company, null, 2));
82
+ if (fs.existsSync(companyPath)) {
83
+ let company = JSON.parse(fs.readFileSync(companyPath, "utf8"));
84
+ if (company.records) {
85
+ company.records.forEach((r) => {
86
+ if (r.Company_Code__c) r.Company_Code__c = r.Company_Code__c.slice(0, 8) + runSuffix2;
87
+ });
88
+ fs.writeFileSync(companyPath, JSON.stringify(company, null, 2));
89
+ console.log("Updated Property_Management_Company__c.json (Company_Code__c)");
90
+ }
91
+ }
40
92
 
41
93
  // Property_Owner__c: Email__c — add +runId before @
42
94
  const ownerPath = path.join(dataDir, "Property_Owner__c.json");
43
- let owner = JSON.parse(fs.readFileSync(ownerPath, "utf8"));
44
- owner.records.forEach((r) => {
45
- if (r.Email__c && r.Email__c.includes("@"))
46
- r.Email__c = r.Email__c.replace(/\+[0-9]+@/, "@").replace("@", "+" + runId + "@");
47
- });
48
- fs.writeFileSync(ownerPath, JSON.stringify(owner, null, 2));
95
+ if (fs.existsSync(ownerPath)) {
96
+ let owner = JSON.parse(fs.readFileSync(ownerPath, "utf8"));
97
+ if (owner.records) {
98
+ owner.records.forEach((r) => {
99
+ if (r.Email__c && r.Email__c.includes("@"))
100
+ r.Email__c = r.Email__c.replace(/\+[0-9]+@/, "@").replace("@", "+" + runId + "@");
101
+ });
102
+ fs.writeFileSync(ownerPath, JSON.stringify(owner, null, 2));
103
+ console.log("Updated Property_Owner__c.json (Email__c)");
104
+ }
105
+ }
49
106
 
50
- // Remap @TenantRefN in dependent files to only use refs that exist in Tenant__c.json (fix UnresolvableRefsError)
107
+ // Remap @TenantRefN in dependent files to only use refs that exist in Tenant__c.json.
108
+ // The valid ref count is derived from the data (no magic number), so refs stay in
109
+ // range and resolve even if Tenant__c.json's record count changes.
51
110
  const tenantPath = path.join(dataDir, "Tenant__c.json");
52
- const tenantData = JSON.parse(fs.readFileSync(tenantPath, "utf8"));
53
- const validTenantRefs = tenantData.records.map((r) => r.attributes?.referenceId).filter(Boolean);
54
- if (validTenantRefs.length === 0) throw new Error("Tenant__c.json has no referenceIds");
111
+ if (fs.existsSync(tenantPath)) {
112
+ const tenantData = JSON.parse(fs.readFileSync(tenantPath, "utf8"));
113
+ const validTenantRefs = (tenantData.records || [])
114
+ .map((r) => r.attributes?.referenceId)
115
+ .filter(Boolean);
116
+ if (validTenantRefs.length === 0) throw new Error("Tenant__c.json has no referenceIds");
55
117
 
56
- function remapTenantRef(refValue) {
57
- if (typeof refValue !== "string" || !refValue.startsWith("@TenantRef")) return refValue;
58
- const match = refValue.match(/^@(TenantRef)(\d+)$/);
59
- if (!match) return refValue;
60
- const n = parseInt(match[2], 10);
61
- const idx = (n - 1) % validTenantRefs.length;
62
- return "@" + validTenantRefs[idx];
63
- }
118
+ const remapTenantRef = (refValue) => {
119
+ if (typeof refValue !== "string" || !refValue.startsWith("@TenantRef")) return refValue;
120
+ const match = refValue.match(/^@(TenantRef)(\d+)$/);
121
+ if (!match) return refValue;
122
+ const n = parseInt(match[2], 10);
123
+ const idx = (n - 1) % validTenantRefs.length;
124
+ return "@" + validTenantRefs[idx];
125
+ };
64
126
 
65
- const leasePath = path.join(dataDir, "Lease__c.json");
66
- let lease = JSON.parse(fs.readFileSync(leasePath, "utf8"));
67
- lease.records.forEach((r) => {
68
- if (r.Tenant__c) r.Tenant__c = remapTenantRef(r.Tenant__c);
69
- });
70
- fs.writeFileSync(leasePath, JSON.stringify(lease, null, 2));
127
+ const leasePath = path.join(dataDir, "Lease__c.json");
128
+ if (fs.existsSync(leasePath)) {
129
+ let lease = JSON.parse(fs.readFileSync(leasePath, "utf8"));
130
+ if (lease.records) {
131
+ lease.records.forEach((r) => {
132
+ if (r.Tenant__c) r.Tenant__c = remapTenantRef(r.Tenant__c);
133
+ });
134
+ fs.writeFileSync(leasePath, JSON.stringify(lease, null, 2));
135
+ console.log(
136
+ "Updated Lease__c.json (Tenant__c @TenantRef remap, validTenants=%s)",
137
+ validTenantRefs.length,
138
+ );
139
+ }
140
+ }
71
141
 
72
- const maintPath = path.join(dataDir, "Maintenance_Request__c.json");
73
- let maint = JSON.parse(fs.readFileSync(maintPath, "utf8"));
74
- maint.records.forEach((r) => {
75
- if (r.User__c && String(r.User__c).startsWith("@TenantRef"))
76
- r.User__c = remapTenantRef(r.User__c);
77
- });
78
- fs.writeFileSync(maintPath, JSON.stringify(maint, null, 2));
142
+ const maintPath = path.join(dataDir, "Maintenance_Request__c.json");
143
+ if (fs.existsSync(maintPath)) {
144
+ let maint = JSON.parse(fs.readFileSync(maintPath, "utf8"));
145
+ if (maint.records) {
146
+ maint.records.forEach((r) => {
147
+ if (r.User__c && String(r.User__c).startsWith("@TenantRef"))
148
+ r.User__c = remapTenantRef(r.User__c);
149
+ });
150
+ fs.writeFileSync(maintPath, JSON.stringify(maint, null, 2));
151
+ console.log("Updated Maintenance_Request__c.json (User__c @TenantRef remap)");
152
+ }
153
+ }
154
+ }
79
155
 
80
- console.log(
81
- "Unique fields updated: runId=%s companySuffix=%s validTenants=%s",
82
- runId,
83
- runSuffix2,
84
- validTenantRefs.length,
85
- );
156
+ console.log("Unique fields updated: runId=%s companySuffix=%s", runId, runSuffix2);
@@ -18,8 +18,8 @@
18
18
  "graphql:schema": "node scripts/get-graphql-schema.mjs"
19
19
  },
20
20
  "dependencies": {
21
- "@salesforce/platform-sdk": "^11.1.0",
22
- "@salesforce/ui-bundle": "^11.1.0",
21
+ "@salesforce/platform-sdk": "^11.1.2",
22
+ "@salesforce/ui-bundle": "^11.1.2",
23
23
  "@tailwindcss/vite": "^4.1.17",
24
24
  "class-variance-authority": "^0.7.1",
25
25
  "clsx": "^2.1.1",
@@ -50,8 +50,8 @@
50
50
  "@graphql-eslint/eslint-plugin": "^4.1.0",
51
51
  "@graphql-tools/utils": "^11.0.0",
52
52
  "@playwright/test": "^1.49.0",
53
- "@salesforce/graphiti": "^11.1.0",
54
- "@salesforce/vite-plugin-ui-bundle": "^11.1.0",
53
+ "@salesforce/graphiti": "^11.1.2",
54
+ "@salesforce/vite-plugin-ui-bundle": "^11.1.2",
55
55
  "@testing-library/jest-dom": "^6.6.3",
56
56
  "@testing-library/react": "^16.1.0",
57
57
  "@testing-library/user-event": "^14.5.2",
@@ -76,6 +76,7 @@
76
76
  "vitest": "^4.0.17"
77
77
  },
78
78
  "overrides": {
79
- "lodash": "^4.18.1"
79
+ "lodash": "^4.18.1",
80
+ "undici": "^7.28.0"
80
81
  }
81
82
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@salesforce/webapp-template-base-sfdx-project-experimental",
3
- "version": "11.1.0",
3
+ "version": "11.1.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@salesforce/webapp-template-base-sfdx-project-experimental",
9
- "version": "11.1.0",
9
+ "version": "11.1.2",
10
10
  "license": "SEE LICENSE IN LICENSE.txt",
11
11
  "devDependencies": {
12
12
  "@lwc/eslint-plugin-lwc": "^3.3.0",
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-base-sfdx-project",
3
- "version": "11.1.0",
3
+ "version": "11.1.2",
4
4
  "description": "Base SFDX project template",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "publishConfig": {
@@ -1217,20 +1217,15 @@ async function main() {
1217
1217
  const dataStep = stepDefs.find((s) => s.key === 'data');
1218
1218
  if (doData) {
1219
1219
  await runStep(dataStep, targetOrg, () => {
1220
- // Prepare data for uniqueness (run before import so repeat imports don't conflict)
1221
- const prepareScript = resolve(__dirname, 'prepare-import-unique-fields.js');
1222
- run('Prepare data (unique fields)', 'node', [prepareScript, '--data-dir', DATA_DIR], {
1223
- cwd: ROOT,
1224
- });
1225
- // Normalize Lease__c Tenant refs to 1–15 so all refs resolve (Tenant__c.json has 15 records)
1226
- const leasePath = resolve(DATA_DIR, 'Lease__c.json');
1227
- if (existsSync(leasePath)) {
1228
- let leaseContent = readFileSync(leasePath, 'utf8');
1229
- leaseContent = leaseContent.replace(/@TenantRef(\d+)/g, (_m, n) => {
1230
- const k = ((parseInt(n, 10) - 1) % 15) + 1;
1231
- return `@TenantRef${k}`;
1220
+ // Prepare data for uniqueness (run before import so repeat imports don't conflict).
1221
+ // Per-app data normalization (reference remapping, unique-field mangling) ships with
1222
+ // the app's seed data as data/prepare-import-unique-fields.js this script stays
1223
+ // object-agnostic and simply runs it if present.
1224
+ const prepareScript = resolve(DATA_DIR, 'prepare-import-unique-fields.js');
1225
+ if (existsSync(prepareScript)) {
1226
+ run('Prepare data (unique fields)', 'node', [prepareScript, '--data-dir', DATA_DIR], {
1227
+ cwd: ROOT,
1232
1228
  });
1233
- writeFileSync(leasePath, leaseContent);
1234
1229
  }
1235
1230
 
1236
1231
  // Delete existing records so every run inserts the full dataset without duplicate conflicts.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salesforce/ui-bundle-template-app-react-sample-b2x",
3
- "version": "11.1.0",
3
+ "version": "11.1.2",
4
4
  "description": "Salesforce sample property rental React app",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "author": "",
@@ -1,122 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Updates unique fields in data JSON files so "sf data import tree" can be run
4
- * repeatedly (e.g. after org already has data). Run before data import.
5
- *
6
- * Usage:
7
- * node scripts/prepare-import-unique-fields.js
8
- * node scripts/prepare-import-unique-fields.js --data-dir /path/to/<sfdx-source>/data
9
- *
10
- * Expects data dir to contain (optional) JSON files:
11
- * Contact.json (Email with unique domain per run, LastName, FirstName, Phone — standard Contact)
12
- * Agent__c.json (License_Number__c — unique per record)
13
- * Property_Management_Company__c.json (Company_Code__c, max 10 chars)
14
- * Property_Owner__c.json (Email__c)
15
- * Missing files are skipped. Customize this script for your app's objects/fields.
16
- */
17
-
18
- const fs = require('fs');
19
- const path = require('path');
20
-
21
- function resolveSfdxSource() {
22
- const sfdxPath = path.resolve(__dirname, '..', 'sfdx-project.json');
23
- if (!fs.existsSync(sfdxPath)) {
24
- console.error('Error: sfdx-project.json not found at project root.');
25
- process.exit(1);
26
- }
27
- const sfdxProject = JSON.parse(fs.readFileSync(sfdxPath, 'utf8'));
28
- const pkgDir = sfdxProject?.packageDirectories?.[0]?.path;
29
- if (!pkgDir) {
30
- console.error('Error: No packageDirectories[].path found in sfdx-project.json.');
31
- process.exit(1);
32
- }
33
- return path.resolve(__dirname, '..', pkgDir, 'main', 'default');
34
- }
35
-
36
- const DEFAULT_DATA_DIR = path.resolve(resolveSfdxSource(), 'data');
37
-
38
- function parseArgs() {
39
- const args = process.argv.slice(2);
40
- let dataDir = DEFAULT_DATA_DIR;
41
- for (let i = 0; i < args.length; i++) {
42
- if (args[i] === '--data-dir' && args[i + 1]) {
43
- dataDir = path.resolve(args[++i]);
44
- break;
45
- }
46
- }
47
- return dataDir;
48
- }
49
-
50
- const dataDir = parseArgs();
51
- const runId = Date.now();
52
- const runSuffix2 = String(runId % 100).padStart(2, '0'); // 00-99 for Company_Code__c (10-char limit)
53
-
54
- // Contact: Email (unique domain + local), LastName, FirstName, Phone — avoid duplicate rules
55
- const contactPath = path.join(dataDir, 'Contact.json');
56
- if (fs.existsSync(contactPath)) {
57
- let contact = JSON.parse(fs.readFileSync(contactPath, 'utf8'));
58
- if (contact.records) {
59
- contact.records.forEach((r, i) => {
60
- if (r.Email && r.Email.includes('@')) {
61
- const parts = r.Email.replace(/\+[0-9]+@/, '@').split('@');
62
- const local = (parts[0] || 'user') + '+' + runId;
63
- const domain = 'run' + runId + '.example.com';
64
- r.Email = local + '@' + domain;
65
- }
66
- if (r.LastName)
67
- r.LastName = String(r.LastName).replace(/-[0-9]+$/, '') + '-' + runId;
68
- if (r.FirstName)
69
- r.FirstName = String(r.FirstName).replace(/-[0-9]+$/, '') + '-' + (i + 1);
70
- if (r.Phone)
71
- r.Phone = String(r.Phone).replace(/\d{2}$/, runSuffix2);
72
- });
73
- fs.writeFileSync(contactPath, JSON.stringify(contact, null, 2));
74
- console.log('Updated Contact.json (Email, LastName, FirstName, Phone)');
75
- }
76
- }
77
-
78
- // Agent__c: License_Number__c — unique per record (field is often unique in org)
79
- const agentPath = path.join(dataDir, 'Agent__c.json');
80
- if (fs.existsSync(agentPath)) {
81
- let agent = JSON.parse(fs.readFileSync(agentPath, 'utf8'));
82
- if (agent.records) {
83
- agent.records.forEach((r, i) => {
84
- if (r.License_Number__c) {
85
- const base = r.License_Number__c.replace(/-[0-9]+(-[0-9]+)?$/, '');
86
- r.License_Number__c = base + '-' + runId + '-' + (i + 1);
87
- }
88
- });
89
- fs.writeFileSync(agentPath, JSON.stringify(agent, null, 2));
90
- console.log('Updated Agent__c.json (License_Number__c)');
91
- }
92
- }
93
-
94
- // Property_Management_Company__c: Company_Code__c — max 10 chars, use 8-char base + 2-digit suffix
95
- const companyPath = path.join(dataDir, 'Property_Management_Company__c.json');
96
- if (fs.existsSync(companyPath)) {
97
- let company = JSON.parse(fs.readFileSync(companyPath, 'utf8'));
98
- if (company.records) {
99
- company.records.forEach((r) => {
100
- if (r.Company_Code__c)
101
- r.Company_Code__c = r.Company_Code__c.slice(0, 8) + runSuffix2;
102
- });
103
- fs.writeFileSync(companyPath, JSON.stringify(company, null, 2));
104
- console.log('Updated Property_Management_Company__c.json (Company_Code__c)');
105
- }
106
- }
107
-
108
- // Property_Owner__c: Email__c — add +runId before @
109
- const ownerPath = path.join(dataDir, 'Property_Owner__c.json');
110
- if (fs.existsSync(ownerPath)) {
111
- let owner = JSON.parse(fs.readFileSync(ownerPath, 'utf8'));
112
- if (owner.records) {
113
- owner.records.forEach((r) => {
114
- if (r.Email__c && r.Email__c.includes('@'))
115
- r.Email__c = r.Email__c.replace(/\+[0-9]+@/, '@').replace('@', '+' + runId + '@');
116
- });
117
- fs.writeFileSync(ownerPath, JSON.stringify(owner, null, 2));
118
- console.log('Updated Property_Owner__c.json (Email__c)');
119
- }
120
- }
121
-
122
- console.log('Unique fields updated: runId=%s companySuffix=%s', runId, runSuffix2);