111 lines
3.3 KiB
TypeScript
111 lines
3.3 KiB
TypeScript
import * as fs from 'fs/promises';
|
||
import * as path from 'path';
|
||
import { DocBuilder } from '../docx/doc-builder';
|
||
import { logger } from '../config/logger';
|
||
|
||
export class RepoToDoc {
|
||
private readonly folderPath: string;
|
||
private readonly docBuilder: DocBuilder;
|
||
private readonly blacklist: string[];
|
||
|
||
private readonly includedExtensions: string[] = [
|
||
'.js',
|
||
'.ts',
|
||
'.jsx',
|
||
'.tsx',
|
||
'.html',
|
||
'.css',
|
||
'.json',
|
||
'.yml',
|
||
'.yaml',
|
||
'.md',
|
||
'.txt',
|
||
];
|
||
|
||
constructor(blacklist: string[], folderPath: string, docBuilder: DocBuilder) {
|
||
this.folderPath = path.resolve(folderPath);
|
||
this.docBuilder = docBuilder;
|
||
this.blacklist = blacklist;
|
||
}
|
||
|
||
public async processFiles(): Promise<void> {
|
||
try {
|
||
logger.info(`Start processing files in ${this.folderPath}`);
|
||
|
||
let processedFilesCount = 0;
|
||
let skippedFilesCount = 0;
|
||
|
||
const processDirectory = async (dirPath: string) => {
|
||
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
||
|
||
for (const entry of entries) {
|
||
const entryPath = path.join(dirPath, entry.name);
|
||
const relativePath = path.relative(this.folderPath, entryPath);
|
||
|
||
if (
|
||
this.blacklist.some(
|
||
(excluded) =>
|
||
relativePath.includes(excluded) ||
|
||
entry.name.includes(excluded),
|
||
)
|
||
) {
|
||
logger.info(`Skipping blacklisted item: ${relativePath}`);
|
||
skippedFilesCount++;
|
||
continue;
|
||
}
|
||
|
||
if (entry.isDirectory()) {
|
||
await processDirectory(entryPath);
|
||
} else if (entry.isFile()) {
|
||
const extension = path.extname(entry.name).toLowerCase();
|
||
if (!this.includedExtensions.includes(extension)) {
|
||
logger.info(
|
||
`Skipping file with unsupported extension: ${relativePath}`,
|
||
);
|
||
skippedFilesCount++;
|
||
continue;
|
||
}
|
||
|
||
try {
|
||
logger.info(`Processing file: ${relativePath}`);
|
||
|
||
const stats = await fs.stat(entryPath);
|
||
if (stats.size > 1024 * 1024) {
|
||
// Если файл больше 1МБ
|
||
logger.warn(
|
||
`File ${relativePath} is too large (${Math.round(stats.size / 1024)}KB), skipping`,
|
||
);
|
||
skippedFilesCount++;
|
||
continue;
|
||
}
|
||
|
||
const content = await fs.readFile(entryPath, 'utf-8');
|
||
this.docBuilder.addSection(relativePath, content);
|
||
processedFilesCount++;
|
||
|
||
if (processedFilesCount % 10 === 0) {
|
||
console.log(`Обработано ${processedFilesCount} файлов...`);
|
||
}
|
||
} catch (fileError) {
|
||
logger.error(`Error processing file ${relativePath}:`, fileError);
|
||
skippedFilesCount++;
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
await processDirectory(this.folderPath);
|
||
|
||
logger.info(
|
||
`Processing completed: ${processedFilesCount} files processed, ${skippedFilesCount} files skipped`,
|
||
);
|
||
} catch (err) {
|
||
logger.error(
|
||
'Error processing files:',
|
||
err instanceof Error ? err.message : err,
|
||
);
|
||
throw err;
|
||
}
|
||
}
|
||
}
|