mirror of
https://github.com/forcedotcom/afv-library.git
synced 2026-07-30 11:43:26 +08:00
104 lines
3.6 KiB
JavaScript
104 lines
3.6 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Run from SFDX project root: install dependencies, build, and launch the dev server
|
|
* for the UI bundle in force-app/main/default/uiBundles/.
|
|
*
|
|
* Usage: npm run sf-project-setup
|
|
* (from the directory that contains force-app/ and sfdx-project.json)
|
|
*/
|
|
|
|
import { spawnSync } from 'node:child_process';
|
|
import { resolve, dirname } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { readdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const ROOT = resolve(__dirname, '..');
|
|
|
|
/**
|
|
* npm strips .gitignore from published packages — generate them on first run.
|
|
* Templates are stored in scripts/gitignore-templates.json (generated at build
|
|
* time from the actual .gitignore files). The JSON may not exist in git-cloned
|
|
* distributions where .gitignore is already present, so loading is best-effort.
|
|
*/
|
|
function loadGitignoreTemplates() {
|
|
const templatesPath = resolve(__dirname, 'gitignore-templates.json');
|
|
if (!existsSync(templatesPath)) return null;
|
|
try {
|
|
return JSON.parse(readFileSync(templatesPath, 'utf8'));
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function ensureGitignore(dir, content) {
|
|
if (!content) return;
|
|
const gitignorePath = resolve(dir, '.gitignore');
|
|
if (!existsSync(gitignorePath)) {
|
|
writeFileSync(gitignorePath, content, 'utf8');
|
|
console.log(`Created .gitignore in ${dir}`);
|
|
}
|
|
}
|
|
|
|
function resolveUIBundlesDir() {
|
|
const sfdxPath = resolve(ROOT, 'sfdx-project.json');
|
|
if (!existsSync(sfdxPath)) {
|
|
console.error('Error: sfdx-project.json not found at project root.');
|
|
process.exit(1);
|
|
}
|
|
const sfdxProject = JSON.parse(readFileSync(sfdxPath, 'utf8'));
|
|
const pkgDir = sfdxProject?.packageDirectories?.[0]?.path;
|
|
if (!pkgDir) {
|
|
console.error('Error: No packageDirectories[].path found in sfdx-project.json.');
|
|
process.exit(1);
|
|
}
|
|
return resolve(ROOT, pkgDir, 'main', 'default', 'uiBundles');
|
|
}
|
|
|
|
function discoverUIBundleDir() {
|
|
const uiBundlesDir = resolveUIBundlesDir();
|
|
if (!existsSync(uiBundlesDir)) {
|
|
console.error(`Error: uiBundles directory not found: ${uiBundlesDir}`);
|
|
process.exit(1);
|
|
}
|
|
const entries = readdirSync(uiBundlesDir, { withFileTypes: true });
|
|
const dirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith('.'));
|
|
if (dirs.length === 0) {
|
|
console.error(`Error: No UI bundle folder found under ${uiBundlesDir}`);
|
|
process.exit(1);
|
|
}
|
|
if (dirs.length > 1) {
|
|
console.log(`Multiple UI bundles found; using first: ${dirs[0].name}`);
|
|
}
|
|
return resolve(uiBundlesDir, dirs[0].name);
|
|
}
|
|
|
|
function run(label, cmd, args, opts) {
|
|
console.log(`\n--- ${label} ---\n`);
|
|
const result = spawnSync(cmd, args, { stdio: 'inherit', ...opts });
|
|
if (result.status !== 0) {
|
|
process.exit(result.status ?? 1);
|
|
}
|
|
}
|
|
|
|
// Ensure .gitignore files exist (npm strips them from published packages).
|
|
const gitignoreTemplates = loadGitignoreTemplates();
|
|
if (gitignoreTemplates) {
|
|
ensureGitignore(ROOT, gitignoreTemplates.sfdx);
|
|
const bundlesDir = resolveUIBundlesDir();
|
|
if (existsSync(bundlesDir)) {
|
|
for (const entry of readdirSync(bundlesDir, { withFileTypes: true })) {
|
|
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
ensureGitignore(resolve(bundlesDir, entry.name), gitignoreTemplates.webapp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const uiBundleDir = discoverUIBundleDir();
|
|
console.log('SFDX project root:', ROOT);
|
|
console.log('UI bundle directory:', uiBundleDir);
|
|
|
|
run('npm install', 'npm', ['install', '--registry', 'https://registry.npmjs.org/'], { cwd: uiBundleDir });
|
|
run('npm run build', 'npm', ['run', 'build'], { cwd: uiBundleDir });
|