All files / src/utils Scaffolder.js

100% Statements 21/21
71.43% Branches 5/7
87.5% Functions 7/8
100% Lines 19/19

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          24x 24x                                 19x 19x 19x 19x 19x               23x               8x                 48x 48x 48x 48x 48x 48x 48x             19x 19x 19x      
import {join} from 'path';
import Queue from 'p-queue';
import memFs from 'mem-fs';
import editor from 'mem-fs-editor';
 
const {assign} = Object;
const silent = () => {};
/**
 * Class to create scaffolders when creating folders, and copying files/templates
 * @example
 * import {Scaffolder} from './api';
 * const scaffolder = new Scaffolder('path/to/templates');
 * await scaffolder
 *     .target('/path/to/copy/files')
 *     .copy('foo.js')
 *     .copy('bar.js')
 *     .commit();
 */
export class Scaffolder {
    /**
     * @param {string} sourceDirectory Source directory for template files
     */
    constructor(sourceDirectory = './templates') {
        const copyIfExists = false;
        const targetDirectory = './';
        const fs = editor.create(memFs.create());
        const queue = new Queue({concurrency: 1});
        assign(this, {copyIfExists, fs, queue, sourceDirectory, targetDirectory});
    }
    /**
     * Set target directory
     * @param {string} targetDirectory Target directory of template files
     * @returns {Scaffolder} Chaining OK
     */
    target(targetDirectory) {
        return assign(this, {targetDirectory});
    }
    /**
     * Set overwrite flag
     * @param {boolean} flag Overwrite files (true) or not (false)
     * @returns {Scaffolder} Chaining OK
     */
    overwrite(flag) {
        return assign(this, {copyIfExists: flag});
    }
    /**
     * Copy a file
     * @param {string} path Path string of file to be copied
     * @param {string} [filename] Name for copied file
     * @returns {Scaffolder} Chaining OK
     */
    copy(path, filename) {
        const self = this;
        const {copyIfExists, fs, queue, sourceDirectory, targetDirectory} = self;
        const source = join(sourceDirectory, path);
        const target = join(process.cwd(), targetDirectory, ...((typeof filename === 'string') ? filename : path).split('/'));
        const shouldCopy = !fs.exists(target) || copyIfExists;
        shouldCopy && queue.add(() => fs.copy(source, target)).catch(silent);
        return self;
    }
    /**
     * Write changes to disk
     * @return {Promise} Resolves when queue is empty
     */
    async commit() {
        const {fs, queue} = this;
        await new Promise(resolve => fs.commit(resolve));
        await queue.onEmpty();
    }
}
export default Scaffolder;