Skip to content

Commit fd930e5

Browse files
committed
Integrate SEO File Copying into buildAll.mjs for Application Builds #7747
1 parent a6f0c4a commit fd930e5

2 files changed

Lines changed: 107 additions & 0 deletions

File tree

buildScripts/buildAll.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ if (programOpts.info) {
171171
}
172172
}
173173

174+
// Call the new script to copy SEO files
175+
childProcess = spawnSync('node', [`${neoPath}/buildScripts/copySeoFiles.mjs`, '-e', env], cpOpts);
176+
childProcess.status && process.exit(childProcess.status);
177+
174178
const processTime = (Math.round((new Date - startDate) * 100) / 100000).toFixed(2);
175179
console.log(`\nTotal time for ${programName}: ${processTime}s`);
176180

buildScripts/copySeoFiles.mjs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import chalk from 'chalk';
2+
import fs from 'fs-extra';
3+
import path from 'path';
4+
import {Command} from 'commander/esm.mjs';
5+
6+
const
7+
__dirname = path.resolve(),
8+
cwd = process.cwd(),
9+
requireJson = path => JSON.parse(fs.readFileSync((path))),
10+
packageJson = requireJson(path.join(__dirname, 'package.json')),
11+
program = new Command(),
12+
programName = `${packageJson.name} copySeoFiles`;
13+
14+
const APP_DIR = path.resolve(cwd, 'apps');
15+
const DIST_DIR = path.resolve(cwd, 'dist');
16+
const SEO_FILES = ['robots.txt', 'llm.txt', 'sitemap.xml'];
17+
18+
/**
19+
* Recursively finds application root directories by looking for index.html.
20+
* Excludes 'examples' directory.
21+
* @param {string} currentDir
22+
* @returns {string[]} Array of absolute paths to app roots.
23+
*/
24+
function findAppRoots(currentDir) {
25+
let appRoots = [];
26+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
27+
28+
for (const entry of entries) {
29+
const fullPath = path.join(currentDir, entry.name);
30+
31+
if (entry.isDirectory()) {
32+
// Check if current directory contains index.html
33+
if (fs.existsSync(path.join(fullPath, 'index.html'))) {
34+
appRoots.push(fullPath);
35+
}
36+
// Recurse into subdirectories
37+
appRoots = appRoots.concat(findAppRoots(fullPath));
38+
}
39+
}
40+
return appRoots;
41+
}
42+
43+
/**
44+
* Copies SEO files from an app root to its corresponding dist folders.
45+
* @param {string} appRootPath - Absolute path to the app's root directory.
46+
* @param {string} env - The build environment ('all', 'dev', 'prod').
47+
*/
48+
function copySeoFilesForApp(appRootPath, env) {
49+
const appName = path.basename(appRootPath);
50+
console.log(chalk.blue(`Copying SEO files for app: ${appName}`));
51+
52+
const targetEnvs = [];
53+
if (env === 'all' || env === 'dev') {
54+
targetEnvs.push('development');
55+
}
56+
if (env === 'all' || env === 'prod') {
57+
targetEnvs.push('production');
58+
}
59+
60+
for (const targetEnv of targetEnvs) {
61+
const targetDistDir = path.join(DIST_DIR, targetEnv, appName);
62+
if (!fs.existsSync(targetDistDir)) {
63+
console.warn(chalk.yellow(` Warning: Target directory ${targetDistDir} does not exist. Skipping SEO file copy.`));
64+
continue;
65+
}
66+
67+
for (const seoFile of SEO_FILES) {
68+
const sourceFilePath = path.join(appRootPath, seoFile);
69+
const targetFilePath = path.join(targetDistDir, seoFile);
70+
71+
if (fs.existsSync(sourceFilePath)) {
72+
fs.copySync(sourceFilePath, targetFilePath);
73+
console.log(chalk.gray(` Copied ${seoFile} to ${targetDistDir}`));
74+
}
75+
}
76+
}
77+
}
78+
79+
program
80+
.name(programName)
81+
.version(packageJson.version)
82+
.option('-e, --env <value>', '"all", "dev", "esm", "prod"')
83+
.allowUnknownOption()
84+
.on('--help', () => {
85+
console.log('\nIn case you have any issues, please create a ticket here:');
86+
console.log(chalk.cyan(packageJson.bugs.url));
87+
})
88+
.parse(process.argv);
89+
90+
const programOpts = program.opts();
91+
const env = programOpts.env || 'all';
92+
93+
console.log(chalk.green(programName));
94+
95+
// --- Start SEO file copying logic ---
96+
console.log(chalk.blue('Copying SEO files for applications...'));
97+
const appRoots = findAppRoots(APP_DIR);
98+
for (const appRoot of appRoots) {
99+
copySeoFilesForApp(appRoot, env);
100+
}
101+
// --- End SEO file copying logic ---
102+
103+
process.exit(0);

0 commit comments

Comments
 (0)