@schandlergarcia/sf-web-components 1.9.87 → 1.9.88
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/scripts/postinstall.mjs +68 -16
- package/scripts/reset-command-center.sh +44 -4
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.9.88] - 2026-04-07
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **Postinstall `.a4drules` copy** — now copies all root-level `.md` files (`webapp-ui.md`, `webapp-data.md`, `validation-requirements.md`, `RULES.md`) and all subdirectories (`skills/`, `features/`, `troubleshooting/`), not just `skills/` and `features/`. Ensures the full build guide reaches consuming projects.
|
|
12
|
+
- **Postinstall vite proxy injection** — when `vite.config.ts` already exists, the postinstall now checks for and injects the Agent API proxy rules (`/sf-oauth`, `/sf-agent`) if they're missing, rather than silently skipping.
|
|
13
|
+
- **Reset script `.a4drules` restore** — the reset script now force-copies every `.md` file from the package's `.a4drules` to the project root, preventing stale stubs from persisting across resets.
|
|
14
|
+
|
|
8
15
|
## [1.9.87] - 2026-04-07
|
|
9
16
|
|
|
10
17
|
### Changed
|
package/package.json
CHANGED
package/scripts/postinstall.mjs
CHANGED
|
@@ -429,7 +429,46 @@ if (fs.existsSync(viteConfigTemplatePath) && !fs.existsSync(viteConfigPath)) {
|
|
|
429
429
|
console.error(` ✗ Failed to install vite.config.ts: ${error.message}`);
|
|
430
430
|
}
|
|
431
431
|
} else if (fs.existsSync(viteConfigPath)) {
|
|
432
|
-
|
|
432
|
+
// Ensure Agent API proxy rules exist even in pre-existing vite.config.ts
|
|
433
|
+
try {
|
|
434
|
+
const existing = fs.readFileSync(viteConfigPath, 'utf-8');
|
|
435
|
+
if (!existing.includes('/sf-oauth') || !existing.includes("api.salesforce.com")) {
|
|
436
|
+
const proxyBlock = `
|
|
437
|
+
// Proxy Agentforce Agent API calls through the dev server to avoid CORS.
|
|
438
|
+
// /sf-oauth/* → Salesforce org (for OAuth client-credentials token)
|
|
439
|
+
// /sf-agent/* → Agent API base (for session + message calls)
|
|
440
|
+
server: {
|
|
441
|
+
proxy: {
|
|
442
|
+
'/sf-oauth': {
|
|
443
|
+
target: 'https://tdx26-keynote-org-1com.my.salesforce.com',
|
|
444
|
+
changeOrigin: true,
|
|
445
|
+
rewrite: (p: string) => p.replace(/^\\/sf-oauth/, ''),
|
|
446
|
+
},
|
|
447
|
+
'/sf-agent': {
|
|
448
|
+
target: 'https://api.salesforce.com',
|
|
449
|
+
changeOrigin: true,
|
|
450
|
+
rewrite: (p: string) => p.replace(/^\\/sf-agent/, ''),
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
`;
|
|
455
|
+
// Insert before the build: { section if it exists
|
|
456
|
+
if (existing.includes('build: {') && !existing.includes('server: {')) {
|
|
457
|
+
const updated = existing.replace(
|
|
458
|
+
/(\s*)(\/\/.*Build|build:\s*\{)/,
|
|
459
|
+
proxyBlock + '\n$1$2'
|
|
460
|
+
);
|
|
461
|
+
if (updated !== existing) {
|
|
462
|
+
fs.writeFileSync(viteConfigPath, updated, 'utf-8');
|
|
463
|
+
console.log(' ✓ Added Agent API proxy rules to existing vite.config.ts');
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
} else {
|
|
467
|
+
console.log(' ℹ vite.config.ts already has proxy rules');
|
|
468
|
+
}
|
|
469
|
+
} catch {
|
|
470
|
+
// Non-critical — proxy can be added manually
|
|
471
|
+
}
|
|
433
472
|
}
|
|
434
473
|
|
|
435
474
|
// Copy dataStrategy.ts template
|
|
@@ -501,35 +540,48 @@ if (fs.existsSync(packageJsonPath)) {
|
|
|
501
540
|
|
|
502
541
|
// Copy .a4drules from package to project root (so AI assistants can discover them)
|
|
503
542
|
const packageA4dRules = path.join(packageRoot, '.a4drules');
|
|
504
|
-
const projectRootA4dRules = path.join(cwd, '../../../../../.a4drules'); // Go up from webapp to project root
|
|
505
543
|
|
|
506
544
|
if (fs.existsSync(packageA4dRules)) {
|
|
507
545
|
console.log('\n📋 Copying AI assistant rules to project root...\n');
|
|
508
546
|
|
|
509
|
-
// Resolve to absolute path
|
|
510
547
|
const projectRootPath = path.resolve(cwd, '../../../../../');
|
|
511
548
|
const targetA4dRules = path.join(projectRootPath, '.a4drules');
|
|
512
549
|
|
|
513
|
-
// Create .a4drules if it doesn't exist
|
|
514
550
|
if (!fs.existsSync(targetA4dRules)) {
|
|
515
551
|
fs.mkdirSync(targetA4dRules, { recursive: true });
|
|
516
552
|
}
|
|
517
553
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
554
|
+
let totalA4dCopied = 0;
|
|
555
|
+
|
|
556
|
+
// Force-copy root-level .md files first
|
|
557
|
+
const rootFiles = fs.readdirSync(packageA4dRules).filter(f => f.endsWith('.md'));
|
|
558
|
+
for (const file of rootFiles) {
|
|
559
|
+
try {
|
|
560
|
+
fs.copyFileSync(path.join(packageA4dRules, file), path.join(targetA4dRules, file));
|
|
561
|
+
totalA4dCopied++;
|
|
562
|
+
} catch (error) {
|
|
563
|
+
console.error(` ✗ Failed to copy ${file}: ${error.message}`);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (rootFiles.length > 0) {
|
|
567
|
+
console.log(` ✓ Copied ${rootFiles.length} root rule files`);
|
|
524
568
|
}
|
|
525
569
|
|
|
526
|
-
// Copy features
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
570
|
+
// Copy all subdirectories (skills, features, troubleshooting)
|
|
571
|
+
const subdirs = fs.readdirSync(packageA4dRules).filter(d => {
|
|
572
|
+
const full = path.join(packageA4dRules, d);
|
|
573
|
+
return fs.statSync(full).isDirectory();
|
|
574
|
+
});
|
|
575
|
+
|
|
576
|
+
for (const subdir of subdirs) {
|
|
577
|
+
const src = path.join(packageA4dRules, subdir);
|
|
578
|
+
const dst = path.join(targetA4dRules, subdir);
|
|
579
|
+
const copied = copyDirectoryRecursive(src, dst);
|
|
580
|
+
totalA4dCopied += copied;
|
|
581
|
+
console.log(` ✓ Copied ${copied} files from ${subdir}/`);
|
|
532
582
|
}
|
|
583
|
+
|
|
584
|
+
console.log(` 📋 Total: ${totalA4dCopied} rule files installed`);
|
|
533
585
|
}
|
|
534
586
|
|
|
535
587
|
// Migrate any dashboards from old location (src/components/pages/) to new location (src/pages/)
|
|
@@ -27,6 +27,7 @@ else
|
|
|
27
27
|
fi
|
|
28
28
|
|
|
29
29
|
cd "$ROOT"
|
|
30
|
+
ROOT_ABS="$(cd "$ROOT" && pwd)"
|
|
30
31
|
|
|
31
32
|
echo ""
|
|
32
33
|
echo "╔════════════════════════════════════════════════╗"
|
|
@@ -799,15 +800,53 @@ else
|
|
|
799
800
|
echo " ⚠ Skipped logo (package logo not found)"
|
|
800
801
|
fi
|
|
801
802
|
|
|
803
|
+
# ── Restore .a4drules to project root ─────────────────────────────────────────
|
|
804
|
+
|
|
805
|
+
echo "→ Restoring AI assistant rules (.a4drules)..."
|
|
806
|
+
|
|
807
|
+
# Detect package .a4drules location
|
|
808
|
+
PACKAGE_A4D=""
|
|
809
|
+
if [ -d "node_modules/@schandlergarcia/sf-web-components/.a4drules" ]; then
|
|
810
|
+
PACKAGE_A4D="node_modules/@schandlergarcia/sf-web-components/.a4drules"
|
|
811
|
+
elif [ -d "$SCRIPT_DIR/../.a4drules" ]; then
|
|
812
|
+
PACKAGE_A4D="$SCRIPT_DIR/../.a4drules"
|
|
813
|
+
fi
|
|
814
|
+
|
|
815
|
+
if [ -n "$PACKAGE_A4D" ]; then
|
|
816
|
+
# Resolve project root (5 levels up from webapp, or 1 level up from package source)
|
|
817
|
+
PROJECT_ROOT=""
|
|
818
|
+
if [[ "$ROOT_ABS" == */force-app/main/default/* ]]; then
|
|
819
|
+
PROJECT_ROOT="${ROOT_ABS%%/force-app/main/default/*}"
|
|
820
|
+
else
|
|
821
|
+
PROJECT_ROOT="$ROOT/.."
|
|
822
|
+
fi
|
|
823
|
+
|
|
824
|
+
if [ -n "$PROJECT_ROOT" ] && [ -d "$PROJECT_ROOT" ]; then
|
|
825
|
+
TARGET_A4D="$PROJECT_ROOT/.a4drules"
|
|
826
|
+
a4d_copied=0
|
|
827
|
+
|
|
828
|
+
# Force-copy every .md file individually (cp -R doesn't always overwrite)
|
|
829
|
+
while IFS= read -r src_file; do
|
|
830
|
+
rel="${src_file#$PACKAGE_A4D/}"
|
|
831
|
+
dst="$TARGET_A4D/$rel"
|
|
832
|
+
mkdir -p "$(dirname "$dst")"
|
|
833
|
+
cp -f "$src_file" "$dst"
|
|
834
|
+
a4d_copied=$((a4d_copied + 1))
|
|
835
|
+
done < <(find "$PACKAGE_A4D" -name "*.md" -type f)
|
|
836
|
+
|
|
837
|
+
echo " ✓ Restored $a4d_copied rule files to $TARGET_A4D"
|
|
838
|
+
fi
|
|
839
|
+
else
|
|
840
|
+
echo " ⚠ Skipped .a4drules (package rules not found)"
|
|
841
|
+
fi
|
|
842
|
+
echo ""
|
|
843
|
+
|
|
802
844
|
# ── Clean Salesforce metadata created during the demo ────────────────────────
|
|
803
845
|
|
|
804
846
|
SFDX_DEFAULT=""
|
|
805
847
|
|
|
806
848
|
# The webapp lives inside force-app/main/default/uiBundles/..., so extract
|
|
807
|
-
# the SFDX default directory from our own path first.
|
|
808
|
-
# searching child directories if the pattern doesn't match (standalone app).
|
|
809
|
-
ROOT_ABS="$(cd "$ROOT" && pwd)"
|
|
810
|
-
|
|
849
|
+
# the SFDX default directory from our own path first.
|
|
811
850
|
if [[ "$ROOT_ABS" == */force-app/main/default/* ]]; then
|
|
812
851
|
SFDX_DEFAULT="${ROOT_ABS%%/force-app/main/default/*}/force-app/main/default"
|
|
813
852
|
fi
|
|
@@ -872,6 +911,7 @@ echo "║ • Agent API config (src/config/agentApi.ts)║"
|
|
|
872
911
|
echo "║ • Data strategy (ENABLE_SAMPLE_DATA_CACHE) ║"
|
|
873
912
|
echo "║ • GraphQL schema + PRD + logo ║"
|
|
874
913
|
echo "║ • Component library + theme providers ║"
|
|
914
|
+
echo "║ • AI assistant rules (.a4drules) ║"
|
|
875
915
|
echo "║ ║"
|
|
876
916
|
echo "║ Cleaned: ║"
|
|
877
917
|
echo "║ • Apex classes (force-app classes/) ║"
|