{"version":3,"file":"watcher.cjs","names":[],"sources":["../../../src/watcher/watcher.ts"],"sourcesContent":["import { relative } from \"node:path\";\nimport { watch } from \"chokidar\";\n\nimport { DEFAULT_IGNORE } from \"../constants.js\";\nimport { shouldIgnoreRoutePath } from \"../scan/paths.js\";\nimport { toPosixPath } from \"../support/paths.js\";\nimport { scaffoldRouteFile } from \"../scaffold/scaffold.js\";\nimport type { AnalysisCache } from \"../scan/cache.js\";\n\nexport type RouteChangeEvent = \"add\" | \"change\" | \"unlink\";\n\nexport type RouteChangeBatch = {\n  events: Map<string, RouteChangeEvent>;\n};\n\nexport type WatchRoutesOptions = {\n  routesDir: string;\n  entry?: string | undefined;\n  ignore?: readonly string[] | undefined;\n  debounceMs?: number | undefined;\n  cache?: AnalysisCache | undefined;\n  autoScaffold?: boolean | undefined;\n};\n\nconst DEFAULT_DEBOUNCE_MS = 50;\n\nexport function watchRoutes(\n  options: WatchRoutesOptions,\n  onChange: (batch: RouteChangeBatch) => Promise<void> | void,\n): { close: () => Promise<void> } {\n  const debounceMs = options.debounceMs ?? DEFAULT_DEBOUNCE_MS;\n  const ignore = options.ignore ?? DEFAULT_IGNORE;\n  const autoScaffold = options.autoScaffold ?? true;\n  const pending = new Map<string, RouteChangeEvent>();\n  let timer: ReturnType<typeof setTimeout> | undefined;\n\n  const flush = async () => {\n    timer = undefined;\n    const batch: RouteChangeBatch = { events: new Map(pending) };\n    pending.clear();\n\n    let touched = false;\n    const additions: string[] = [];\n    for (const [absolutePath, event] of batch.events) {\n      if (event === \"unlink\") {\n        options.cache?.delete(absolutePath);\n        touched = true;\n        continue;\n      }\n      touched = true;\n      if (event === \"add\" && autoScaffold) {\n        additions.push(absolutePath);\n      }\n    }\n\n    if (additions.length > 0) {\n      await Promise.all(\n        additions.map(async (absolutePath) => {\n          try {\n            await scaffoldRouteFile(options.routesDir, absolutePath, {\n              ignore,\n            });\n          } catch (error) {\n            console.warn(`[taserjs] failed to scaffold ${absolutePath}:`, error);\n          }\n        }),\n      );\n    }\n\n    if (!touched) {\n      return;\n    }\n\n    try {\n      await onChange(batch);\n    } catch (error) {\n      console.warn(\"[taserjs] route watcher change callback failed:\", error);\n    }\n  };\n\n  const fsWatcher = watch(options.routesDir, {\n    ignoreInitial: true,\n    awaitWriteFinish: { stabilityThreshold: 50, pollInterval: 25 },\n    ignored(absolutePath: string) {\n      try {\n        const rel = toPosixPath(relative(options.routesDir, absolutePath));\n        return rel !== \"\" && shouldIgnoreRoutePath(rel, ignore);\n      } catch {\n        return false;\n      }\n    },\n  });\n\n  fsWatcher.on(\"all\", (event: string, absolutePath: string) => {\n    if (event !== \"add\" && event !== \"change\" && event !== \"unlink\") {\n      return;\n    }\n    pending.set(absolutePath, event as RouteChangeEvent);\n    if (timer) {\n      clearTimeout(timer);\n    }\n    timer = setTimeout(() => {\n      void flush();\n    }, debounceMs);\n  });\n\n  return {\n    close: async () => {\n      if (timer) {\n        clearTimeout(timer);\n      }\n      await fsWatcher.close();\n    },\n  };\n}\n"],"mappings":";;;;;;;AAwBA,IAAM,sBAAsB;AAE5B,SAAgB,YACd,SACA,UACgC;CAChC,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,SAAS,QAAQ,UAAU,kBAAA;CACjC,MAAM,eAAe,QAAQ,gBAAgB;CAC7C,MAAM,0BAAU,IAAI,IAA8B;CAClD,IAAI;CAEJ,MAAM,QAAQ,YAAY;EACxB,QAAQ,KAAA;EACR,MAAM,QAA0B,EAAE,QAAQ,IAAI,IAAI,OAAO,EAAE;EAC3D,QAAQ,MAAM;EAEd,IAAI,UAAU;EACd,MAAM,YAAsB,CAAC;EAC7B,KAAK,MAAM,CAAC,cAAc,UAAU,MAAM,QAAQ;GAChD,IAAI,UAAU,UAAU;IACtB,QAAQ,OAAO,OAAO,YAAY;IAClC,UAAU;IACV;GACF;GACA,UAAU;GACV,IAAI,UAAU,SAAS,cACrB,UAAU,KAAK,YAAY;EAE/B;EAEA,IAAI,UAAU,SAAS,GACrB,MAAM,QAAQ,IACZ,UAAU,IAAI,OAAO,iBAAiB;GACpC,IAAI;IACF,MAAM,iBAAA,kBAAkB,QAAQ,WAAW,cAAc,EACvD,OACF,CAAC;GACH,SAAS,OAAO;IACd,QAAQ,KAAK,gCAAgC,aAAa,IAAI,KAAK;GACrE;EACF,CAAC,CACH;EAGF,IAAI,CAAC,SACH;EAGF,IAAI;GACF,MAAM,SAAS,KAAK;EACtB,SAAS,OAAO;GACd,QAAQ,KAAK,mDAAmD,KAAK;EACvE;CACF;CAEA,MAAM,aAAA,GAAA,SAAA,MAAA,CAAkB,QAAQ,WAAW;EACzC,eAAe;EACf,kBAAkB;GAAE,oBAAoB;GAAI,cAAc;EAAG;EAC7D,QAAQ,cAAsB;GAC5B,IAAI;IACF,MAAM,MAAM,cAAA,aAAA,GAAA,UAAA,SAAA,CAAqB,QAAQ,WAAW,YAAY,CAAC;IACjE,OAAO,QAAQ,MAAM,gBAAA,sBAAsB,KAAK,MAAM;GACxD,QAAQ;IACN,OAAO;GACT;EACF;CACF,CAAC;CAED,UAAU,GAAG,QAAQ,OAAe,iBAAyB;EAC3D,IAAI,UAAU,SAAS,UAAU,YAAY,UAAU,UACrD;EAEF,QAAQ,IAAI,cAAc,KAAyB;EACnD,IAAI,OACF,aAAa,KAAK;EAEpB,QAAQ,iBAAiB;GACvB,MAAW;EACb,GAAG,UAAU;CACf,CAAC;CAED,OAAO,EACL,OAAO,YAAY;EACjB,IAAI,OACF,aAAa,KAAK;EAEpB,MAAM,UAAU,MAAM;CACxB,EACF;AACF"}