All files / src template.ts

88% Statements 66/75
75% Branches 12/16
100% Functions 4/4
88% Lines 66/75

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 1181x               1x 1x   1x   1x         1x 24x 24x 24x   24x 24x       24x         1x 17x   17x 17x 17x 17x   17x   85x     85x 85x   85x 85x 85x 85x 85x 85x 85x 85x 85x 85x 85x 85x 85x 85x           85x 85x     17x 17x         1x 10x       10x   10x 10x 10x         1x 67x 67x 67x 67x 67x   67x 242x 242x 242x   242x 44x 44x 242x 198x     198x   198x 198x 242x 67x  
import {
    existsSync,
    mkdirSync,
    readFileSync,
    readdirSync,
    statSync,
    writeFileSync
} from 'node:fs';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { TemplateInfo, TemplateVariables } from './types';
import { replaceTemplateVariables } from './utils/index';
 
const __dirname = dirname(fileURLToPath(import.meta.url));
 
/**
 * Get version of esmx from package.json
 */
export function getEsmxVersion(): string {
    try {
        const packageJsonPath = resolve(__dirname, '../package.json');
        const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
 
        return packageJson.version || 'latest';
    } catch (error) {
        console.warn('Failed to read esmx version, using latest version');
        return 'latest';
    }
}
 
/**
 * Get list of available templates
 */
export function getAvailableTemplates(): TemplateInfo[] {
    const templateDir = resolve(__dirname, '../template');
 
    const templates: TemplateInfo[] = [];
    const templateFolders = readdirSync(templateDir, { withFileTypes: true })
        .filter((dirent) => dirent.isDirectory())
        .map((dirent) => dirent.name);
 
    for (const folder of templateFolders) {
        // Use folder name as display name
        const name = folder;
 
        // Try to read description from package.json
        const packageJsonPath = resolve(templateDir, folder, 'package.json');
        let description = `${name} template`;
 
        if (existsSync(packageJsonPath)) {
            try {
                const packageJson = JSON.parse(
                    readFileSync(packageJsonPath, 'utf-8')
                );
                if (packageJson.description) {
                    description = packageJson.description;
                }
                templates.push({
                    folder,
                    name,
                    description
                });
            } catch (error) {
                // JSON parsing failed, skip this template
                console.warn(
                    `Warning: Failed to parse package.json for template '${folder}', skipping.`
                );
            }
        }
    }
 
    // Sort by name alphabetically
    return templates.sort((a, b) => a.name.localeCompare(b.name));
}
 
/**
 * Check if directory is empty (ignoring hidden files)
 */
export function isDirectoryEmpty(dirPath: string): boolean {
    if (!existsSync(dirPath)) {
        return true;
    }
 
    const files = readdirSync(dirPath);
    // Only consider non-hidden files and directories
    const nonHiddenFiles = files.filter((file) => !file.startsWith('.'));
    return nonHiddenFiles.length === 0;
}
 
/**
 * Copy template files to target directory with variable replacement
 */
export function copyTemplateFiles(
    templatePath: string,
    targetPath: string,
    variables: TemplateVariables
): void {
    const files = readdirSync(templatePath);
 
    for (const file of files) {
        const filePath = join(templatePath, file);
        const targetFilePath = join(targetPath, file);
        const stat = statSync(filePath);
 
        if (stat.isDirectory()) {
            mkdirSync(targetFilePath, { recursive: true });
            copyTemplateFiles(filePath, targetFilePath, variables);
        } else {
            let content = readFileSync(filePath, 'utf-8');
 
            // Replace all template variables using the utility function
            content = replaceTemplateVariables(content, variables);
 
            writeFileSync(targetFilePath, content);
        }
    }
}