All files lib.ts

60.63% Statements 57/94
50% Branches 1/2
50% Functions 1/2
60.63% Lines 57/94

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 951x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                         1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                   1x 1x 1x 1x 1x 1x 1x  
import { getIO, setIO } from './io.js';
import {
    getTemplateDir,
    npmInstall,
    formatError,
    copyTemplate
} from './util.js';
 
import type { IOMap, IOPath, IOInquirer } from './io.js'
import type { CustomNodeSystemError } from './util.js';
import type { DistinctQuestion } from 'inquirer';
 
const TEMPLATE_DIR = '../../../templates';
const TEMPLATES = {
    'Typescript@4.8.4 + Node@18.11.8': 'ts-node',
    'WebExtension': 'webextension'
};
 
interface FileExistsPromptArgs {
    message: string;
    dir: string;
}
const fileExistsPrompt = async (
    { message, dir }: FileExistsPromptArgs
): Promise<void> => {
    const question: DistinctQuestion = {
        type: 'list',
        name: 'existsAction',
        message,
        choices: ['overwrite', 'abort'],
        default: 'overwrite'
    };
    const { existsAction } = await getIO<IOInquirer>('inquirer').prompt<{
        existsAction: 'overwrite' | 'abort'
    }>([question]);

    if (existsAction === 'overwrite') {
        await copyTemplate(dir, { force: true });
    } else {
        process.stderr.write('Exiting...');
        process.exit(1);
    }
}
 
interface CliConfig {
    io: IOMap;
}
const cli = async ({ io }: CliConfig) => {
 
    setIO(io);
 
    const templateQuestion = {
        type: 'list',
        name: 'templateName',
        message: 'What template do you want to use?',
        choices: Object.keys(TEMPLATES),
        default: Object.keys(TEMPLATES)[0],
    };
    const { templateName } = await getIO<IOInquirer>('inquirer').prompt<
        { templateName: keyof typeof TEMPLATES }
    >([templateQuestion]);
 
    const templateDir = getTemplateDir(import.meta.url, TEMPLATE_DIR)
    const templatePath = getIO<IOPath>('path').resolve(
        templateDir,
        TEMPLATES[templateName]
    );
    try {
        await copyTemplate(templatePath);
    } catch (e) {
        const error = (e as CustomNodeSystemError);
        switch (error.code) {
            // File-exists error
            case 'ERR_FS_CP_EEXIST':
                await fileExistsPrompt({
                    dir: templatePath,
                    message: `${error.info['message']??''}. Do you want to overwrite?`,
                });
                break;
            default:
                // Unknown error
                formatError(new Error(
                    'Failed copying template to current working directory',
                    { cause: { error } }
                ));
        }
    }
 
    npmInstall();
 
    return 0;
};
 
export { cli };