UNPKG

@berun/sparky

Version:

Sparky task runner for @berun

214 lines (191 loc) 5.29 kB
import * as fs from 'fs-extra' import * as chokidar from 'chokidar' import * as path from 'path' import { each } from 'realm-utils' import { ensureDir, string2RegExp, ensureUserPath } from './Utils' import { SparkyFile } from './SparkyFile' import { log } from './Sparky' import { Plugin } from './FuseBox' import { parse, SparkyFilePatternOptions } from './SparkyFilePattern' const glob = require('glob') export class SparkFlow { private activities = [] private watcher: any private files: SparkyFile[] private completedCallback: any private initialWatch = false public glob(globs: string[], opts?: SparkyFilePatternOptions): SparkFlow { this.activities.push(() => this.getFiles(globs, opts)) return this } public createFiles(paths: string[]) { this.files = [] paths.forEach(p => { const isAbsolute = path.isAbsolute(p) const fpath = isAbsolute ? p : path.join(process.cwd(), p) this.files.push( new SparkyFile(fpath, isAbsolute ? path.dirname(p) : process.cwd()) ) }) } public stopWatching() { if (this.watcher) { this.watcher.close() } } public watch( globs: string[], opts?: SparkyFilePatternOptions, fn?: any ): SparkFlow { this.files = [] log.echoStatus(`Watch ${globs}`) this.activities.push( () => new Promise((resolve, reject) => { const chokidarOptions = { cwd: opts ? ensureUserPath(opts.base) : null } this.watcher = chokidar .watch(globs, chokidarOptions) .on('all', (event, fp) => { if (event === 'addDir' || event === 'unlinkDir') { return } if (this.initialWatch) { this.files = [] log.echoStatus(`Changed ${fp}`) if (fn) { fn(event, fp) } } const info = parse(fp, opts) this.files.push(new SparkyFile(info.filepath, info.root)) if (this.initialWatch) { // call it again this.exec() } }) .on('ready', () => { this.initialWatch = true log.echoStatus(`Resolved ${this.files.length} files`) this.activities[0] = undefined resolve() }) }) ) return this } public completed(fn: any): SparkFlow { this.completedCallback = fn return this } /** Gets all user files */ protected getFiles( globs: string[], opts?: SparkyFilePatternOptions ): Promise<SparkyFile[]> { this.files = [] const getFilePromises: Promise<SparkyFile[]>[] = [] globs.forEach(g => { getFilePromises.push(this.getFile(g, opts)) }) return Promise.all(getFilePromises).then(results => { this.files = [].concat(...results) return this.files }) } protected getFile( globString, opts?: SparkyFilePatternOptions ): Promise<SparkyFile[]> { const info = parse(globString, opts) return new Promise((resolve, reject) => { if (!info.isGlob) { resolve([new SparkyFile(info.filepath, info.root)]) } else { glob(info.glob, (err, files: string[]) => { if (err) { reject(err) } else { resolve(files.map(file => new SparkyFile(file, info.root))) } }) } }) } /** * Removes folder if exists * @param dest */ public clean(dest: string): SparkFlow { this.activities.push( () => new Promise((resolve, reject) => { fs.remove(ensureDir(dest), err => { if (err) { return reject(err) } return resolve() }) }) ) return this } public plugin(plugin: Plugin): SparkFlow { this.activities.push(() => { // Promise.all(this.files.map(file => file.copy(dest))) // File.createByName(collection, "sd") }) return this } public each(fn: (file: SparkyFile) => void) { this.activities.push(() => { return each(this.files, (file: SparkyFile) => { return fn(file) }) }) return this } public file(mask: string, fn: any) { this.activities.push(() => { const regexp = string2RegExp(mask) return each(this.files, (file: SparkyFile) => { if (regexp.test(file.filepath)) { log.echoStatus(`Captured file ${file.homePath}`) return fn(file) } return false }) }) return this } public next(fn: (file: SparkyFile) => void) { this.activities.push(() => { return each(this.files, (file: SparkyFile) => fn(file)) }) return this } public dest(dest: string): SparkFlow { log.echoStatus(`Copy to ${dest}`) this.activities.push(() => Promise.all( this.files.map(async file => { await file.copy(dest) }) ) ) return this } public exec() { return each( this.activities, (activity: any) => activity && activity() ).then(() => { if (this.completedCallback) { this.completedCallback(this.files) } this.files = [] }) } }