UNPKG

genaiscript

Version:

A CLI for GenAIScript, a generative AI scripting framework.

112 lines 3.88 kB
// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. import { watch } from "chokidar"; import { basename, resolve } from "node:path"; import { CHANGE, CLOSE, GENAI_ANY_REGEX, OPEN, createGitIgnorer, filterScripts, logError, toSignal, } from "@genaiscript/core"; import { genaiscriptDebug } from "@genaiscript/core"; import { buildProject } from "@genaiscript/core"; const dbg = genaiscriptDebug("watch"); export class ProjectWatcher extends EventTarget { options; _watcher; _project; _scripts; constructor(options) { super(); this.options = options; const signal = toSignal(this.options.cancellationToken); signal?.addEventListener("abort", this.close.bind(this)); } get cwd() { return this.options.cwd; } async open() { if (this._watcher) return; dbg(`starting`); await this.refresh(); const { paths, cwd } = this.options; const gitIgnorer = await createGitIgnorer(); // Initialize watcher. this._watcher = watch(paths, { ignored: (path, stats) => { if (!stats) return false; if (stats.isDirectory()) { const b = basename(path); if (/^\./.test(b)) return true; } else if (stats.isFile() && !GENAI_ANY_REGEX.test(path)) { return true; } const filtered = gitIgnorer([path]); if (filtered.length === 0) return true; return false; }, persistent: false, ignoreInitial: true, awaitWriteFinish: { stabilityThreshold: 2000, pollInterval: 1000, }, atomic: true, interval: 1000, binaryInterval: 5000, depth: 30, cwd, }); const changed = () => { dbg(`changed`); this.dispatchEvent(new Event(CHANGE)); }; this._watcher .on("error", (error) => logError(`watch: ${error}`)) .on("add", changed) .on("change", changed) .on("unlink", changed); this.addEventListener(CHANGE, this.refresh.bind(this)); this.dispatchEvent(new Event(OPEN)); } async refresh() { this._project = undefined; } async project() { if (!this._project) { dbg(`building project`); this._project = await buildProject(); } return this._project; } async scripts() { if (!this._scripts) { const project = await this.project(); this._scripts = filterScripts(project.scripts, this.options); } return this._scripts?.slice(0); } async close() { dbg(`closing`); await this._watcher?.close(); this._watcher = undefined; this.dispatchEvent(new Event(CLOSE)); } } /** * Starts a file watcher for a project, monitoring specified paths and reacting to changes. * * @param options - Optional configuration object: * - paths: One or more paths to watch. Defaults to the current directory. * - cwd: The current working directory for the watcher. Defaults to the resolved current directory. * - cancellationToken: A token to signal cancellation of the watcher. * - rest: Additional options including script filtering options. * @returns An initialized ProjectWatcher instance. */ export async function startProjectWatcher(options) { const { paths = ".", cwd = resolve("."), ...rest } = options || {}; const watcher = new ProjectWatcher({ paths, cwd, ...rest }); await watcher.open(); return watcher; } //# sourceMappingURL=watch.js.map