| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- import z from "zod"
- import { Bus } from "../bus"
- import { Instance } from "../project/instance"
- import { Log } from "../util/log"
- import { FileIgnore } from "./ignore"
- import { Config } from "../config/config"
- // @ts-ignore
- import { createWrapper } from "@parcel/watcher/wrapper"
- import { lazy } from "@/util/lazy"
- import type ParcelWatcher from "@parcel/watcher"
- export namespace FileWatcher {
- const log = Log.create({ service: "file.watcher" })
- export const Event = {
- Updated: Bus.event(
- "file.watcher.updated",
- z.object({
- file: z.string(),
- event: z.union([z.literal("add"), z.literal("change"), z.literal("unlink")]),
- }),
- ),
- }
- const watcher = lazy(() => {
- const binding = require(
- `@parcel/watcher-${process.platform}-${process.arch}${process.platform === "linux" ? "-glibc" : ""}`,
- )
- return createWrapper(binding) as typeof import("@parcel/watcher")
- })
- const state = Instance.state(
- async () => {
- if (Instance.project.vcs !== "git") return {}
- log.info("init")
- const cfg = await Config.get()
- const backend = (() => {
- if (process.platform === "win32") return "windows"
- if (process.platform === "darwin") return "fs-events"
- if (process.platform === "linux") return "inotify"
- })()
- if (!backend) {
- log.error("watcher backend not supported", { platform: process.platform })
- return {}
- }
- log.info("watcher backend", { platform: process.platform, backend })
- const subscribe: ParcelWatcher.SubscribeCallback = (err, evts) => {
- if (err) return
- for (const evt of evts) {
- log.info("event", evt)
- if (evt.type === "create") Bus.publish(Event.Updated, { file: evt.path, event: "add" })
- if (evt.type === "update") Bus.publish(Event.Updated, { file: evt.path, event: "change" })
- if (evt.type === "delete") Bus.publish(Event.Updated, { file: evt.path, event: "unlink" })
- }
- }
- const subs = []
- const cfgIgnores = cfg.watcher?.ignore ?? []
- subs.push(
- await watcher().subscribe(Instance.directory, subscribe, {
- ignore: [...FileIgnore.PATTERNS, ...cfgIgnores],
- backend,
- }),
- )
- const vcsDir = Instance.project.vcsDir
- if (vcsDir && !cfgIgnores.includes(".git") && !cfgIgnores.includes(vcsDir)) {
- subs.push(
- await watcher().subscribe(vcsDir, subscribe, {
- ignore: ["hooks", "info", "logs", "objects", "refs", "worktrees", "modules", "lfs"],
- backend,
- }),
- )
- }
- return { subs }
- },
- async (state) => {
- if (!state.subs) return
- await Promise.all(state.subs.map((sub) => sub?.unsubscribe()))
- },
- )
- export function init() {
- // if (!Flag.OPENCODE_EXPERIMENTAL_WATCHER) return
- state()
- }
- }
|