skeptic-cli 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/AGENTS.md +25 -53
  2. package/LICENSE +24 -0
  3. package/LICENSES.md +92 -3
  4. package/README.md +36 -52
  5. package/agent-skills/skeptic/SKILL.md +151 -33
  6. package/dist/adb-DUGGW3FV.mjs +2 -0
  7. package/dist/adb-driver-TBOCCKEO.mjs +3 -0
  8. package/dist/adb-session-AVVXL3QQ.mjs +2 -0
  9. package/dist/add-G7JFXU4S.mjs +67 -0
  10. package/dist/audit-ID2BSVYC.mjs +7 -0
  11. package/dist/auto-spawn-4TO4DBO6.mjs +2 -0
  12. package/dist/browser-verbs-U54BZACP.mjs +21 -0
  13. package/dist/browsers-install-F2ZWEBOX.mjs +3 -0
  14. package/dist/chokidar-KB6GLGX4.mjs +7 -0
  15. package/dist/chunk-2N64R5DC.mjs +457 -0
  16. package/dist/chunk-2VSGDT7T.mjs +7 -0
  17. package/dist/chunk-2YKSIUIN.mjs +3 -0
  18. package/dist/chunk-2ZORFJJP.mjs +11 -0
  19. package/dist/chunk-42J77CYA.mjs +3 -0
  20. package/dist/chunk-6TLKI7UN.mjs +4 -0
  21. package/dist/chunk-6U6H22OR.mjs +3 -0
  22. package/dist/chunk-7BFRKEFV.mjs +160 -0
  23. package/dist/chunk-7ZUWKIDM.mjs +3 -0
  24. package/dist/chunk-AH75LR2T.mjs +3 -0
  25. package/dist/chunk-B26AZRXU.mjs +41 -0
  26. package/dist/chunk-BIGNULF6.mjs +12 -0
  27. package/dist/chunk-COVGJJ47.mjs +3 -0
  28. package/dist/chunk-CWNYWHJ2.mjs +143 -0
  29. package/dist/chunk-EU3OXJX4.mjs +3 -0
  30. package/dist/chunk-EYVJTUBL.mjs +3 -0
  31. package/dist/chunk-G22LGRZ4.mjs +4 -0
  32. package/dist/chunk-I4JX25Y5.mjs +13 -0
  33. package/dist/chunk-IXBYLSGB.mjs +5 -0
  34. package/dist/chunk-IYLF56WL.mjs +3 -0
  35. package/dist/chunk-K65JNLTT.mjs +3 -0
  36. package/dist/chunk-LPJF33QP.mjs +3 -0
  37. package/dist/chunk-MHNEFL35.mjs +3 -0
  38. package/dist/chunk-N3533BCE.mjs +3 -0
  39. package/dist/chunk-NXTEMSUR.mjs +4 -0
  40. package/dist/chunk-OHVNABCL.mjs +10 -0
  41. package/dist/chunk-QICYK6XT.mjs +10 -0
  42. package/dist/chunk-RU7M6UGM.mjs +5 -0
  43. package/dist/chunk-S3M2RTHJ.mjs +7 -0
  44. package/dist/chunk-U3KRIAEU.mjs +3 -0
  45. package/dist/chunk-WBPZGXOC.mjs +8 -0
  46. package/dist/chunk-YB25SMQ2.mjs +141 -0
  47. package/dist/chunk-ZN6MI2TU.mjs +4 -0
  48. package/dist/client-UR65IKYX.mjs +2 -0
  49. package/dist/comment-F734YE5S.mjs +6 -0
  50. package/dist/cookies-X7W5U3VE.mjs +3 -0
  51. package/dist/daemon-M2J3L6JW.mjs +7 -0
  52. package/dist/device-fixture-MJSDIP75.mjs +2 -0
  53. package/dist/devices-NG4P5UPS.mjs +4 -0
  54. package/dist/devtools-N5AYAR54.mjs +12 -0
  55. package/dist/doctor-WRKNAK3W.mjs +4 -0
  56. package/dist/extractor-Y477MBN6.mjs +2 -0
  57. package/dist/html-reporter-7QHIRHEY.mjs +2 -0
  58. package/dist/index.d.ts +87 -120
  59. package/dist/index.mjs +30 -1740
  60. package/dist/init-4PXSHPNW.mjs +15 -0
  61. package/dist/ink-reporter-4EN7CRMK.mjs +3 -0
  62. package/dist/inspect-3XFCCSUL.mjs +19 -0
  63. package/dist/ios-tools-WK66CQ7Q.mjs +2 -0
  64. package/dist/json-reporter-SXWPAXRY.mjs +2 -0
  65. package/dist/junit-reporter-5AT3OFWV.mjs +12 -0
  66. package/dist/mail-GTOZFXJ5.mjs +14 -0
  67. package/dist/observe-MHEV7OVP.mjs +3 -0
  68. package/dist/render-MHOBDOSP.mjs +383 -0
  69. package/dist/run-GW3X5ANC.mjs +2 -0
  70. package/dist/scaffold-6ZF6K6Y5.mjs +38 -0
  71. package/dist/screenshot-GUJSIRQB.mjs +2 -0
  72. package/dist/session-daemon-cmd-23UUK6TD.mjs +4 -0
  73. package/dist/simctl-driver-PNUN7W7G.mjs +5 -0
  74. package/dist/skeptic.mjs +3 -1749
  75. package/dist/slack-reporter-EEFO66V6.mjs +8 -0
  76. package/dist/watch-A7ZLUYR2.mjs +3 -0
  77. package/dist/webhook-reporter-BXJGZS2I.mjs +3 -0
  78. package/dist/worker.mjs +3 -724
  79. package/package.json +13 -11
@@ -0,0 +1,67 @@
1
+ import {createRequire}from'node:module';import {d}from'./chunk-ZN6MI2TU.mjs';import {a,b}from'./chunk-MHNEFL35.mjs';import {a as a$1}from'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as s from'fs';import*as g from'os';import*as r from'path';import {execSync}from'child_process';import {fileURLToPath}from'url';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ async function B(e){let t=e.devCommand??"npm run dev",n=e.devUrl??"http://localhost:3000",o=r.resolve(process.cwd(),".github/workflows");s.mkdirSync(o,{recursive:true});let i=r.join(o,"skeptic-tests.yml"),a$2=`name: ${a} E2E Tests
4
+
5
+ on:
6
+ pull_request:
7
+ branches: [main]
8
+ push:
9
+ branches: [main]
10
+
11
+ jobs:
12
+ e2e-tests:
13
+ runs-on: ubuntu-latest
14
+ timeout-minutes: 15
15
+ permissions:
16
+ contents: read
17
+ pull-requests: write
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - uses: actions/setup-node@v4
23
+ with:
24
+ node-version: 22
25
+ cache: npm
26
+
27
+ - name: Install dependencies
28
+ run: npm ci
29
+
30
+ - name: Install Playwright browsers
31
+ run: npx playwright install --with-deps chromium
32
+
33
+ - name: Start dev server
34
+ run: ${t} &
35
+ env:
36
+ PORT: 3000
37
+
38
+ - name: Wait for server
39
+ run: npx wait-on ${n} --timeout 30000
40
+
41
+ - name: Run ${a} tests
42
+ run: npx ${b} run --ci --reporter console --reporter junit --reporter json --output ./skeptic-output
43
+ env:
44
+ BASE_URL: ${n}
45
+
46
+ - name: Upload test artifacts
47
+ uses: actions/upload-artifact@v4
48
+ if: always()
49
+ with:
50
+ name: skeptic-test-results
51
+ path: skeptic-output/
52
+ retention-days: 14
53
+
54
+ - name: Comment on PR
55
+ if: github.event_name == 'pull_request' && always()
56
+ run: |
57
+ npx ${b} comment \\
58
+ --results ./skeptic-output/results.json \\
59
+ --pr \${{ github.event.pull_request.number }} \\
60
+ --run-url \${{ github.server_url }}/\${{ github.repository }}/actions/runs/\${{ github.run_id }}
61
+ env:
62
+ GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
63
+ `;s.writeFileSync(i,a$2,"utf-8"),d.success(`Created ${a$1.cyan(i)}`);}var u="skeptic",A="skeptic-agent-skill: managed by skeptic-cli",m=["claude","codex","cursor","opencode"],x=new Set([".DS_Store","Thumbs.db"]),S='---\nname: skeptic\ndescription: Use Skeptic for CLI-first browser QA and TypeScript E2E tests. Use when asked to inspect pages, drive a browser interactively, write or run skeptic-cli specs, validate UI changes, or capture observability evidence. Not for unit-only logic with no browser behavior.\n---\n\n<!-- skeptic-agent-skill: managed by skeptic-cli -->\n\n# Skeptic\n\nUse Skeptic when you need browser evidence: interactive page-driving, page inspection, TypeScript E2E specs, one-off QA captures, or observability evidence. Do not claim a UI/browser change works until you have run a relevant Skeptic command and checked the evidence.\n\nSkeptic is **agent-native**: it has no model of its own, makes no LLM calls, and needs no API keys. You (the coding agent) are the intelligence; Skeptic is the deterministic hands and eyes. Everything is driven from the shell \u2014 there is no MCP server.\n\n## Choose The Surface\n\n- **Drive a browser interactively** (click through a flow, check a fix): use the persistent session verbs \u2014 `skeptic open <url>`, `skeptic snapshot -i`, `skeptic click @e3`, etc. Refs persist between commands.\n- **One-off discovery** (get stable selectors to write a spec): `skeptic inspect <url> --interactive --compact --with-playwright-hints`.\n- **One-off QA / bug hunt** (full evidence bundle for one page): `skeptic observe <url> --full-page --video --trace`.\n- **Persistent regression coverage**: inspect, write a `tests/*.spec.ts`, then `skeptic run`.\n- **Changed-code verification**: run existing specs with `skeptic run`.\n\nIf the `skeptic` binary is not on PATH, try `npx skeptic-cli` or `npx --yes skeptic-cli@latest`.\n\nSpecs import the project dependency `skeptic-cli`. A normal `skeptic init` writes that dependency to `package.json`. If specs fail with `Cannot find package \'skeptic-cli\'`: in an initialized project run `npm install`; in a project that never ran `skeptic init`, run `skeptic init` first, then `npm install`.\n\n## Persistent Browser Session\n\nA daemon holds the browser, so `@eN` refs from one `skeptic snapshot` stay valid for the next `skeptic click @eN` \u2014 across separate commands. The loop:\n\n```bash\nskeptic open https://app.example.com # opens a session (default name "default")\nskeptic snapshot -i # mints @e1.. refs + stable selectorHints\nskeptic click @e3 # act on a ref from the last snapshot\nskeptic fill @e5 "user@test.com"\nskeptic snapshot -i # RE-SNAPSHOT after the DOM changed\nskeptic console --errors # check for uncaught errors\nskeptic screenshot --full # returns a file path\nskeptic close # end the session\n```\n\nVerbs: `open`, `snapshot` (`-i` interactive, `-c` compact), `click`, `fill`, `type`, `press`, `hover`, `check`, `uncheck`, `select`, `get <text|box|url|title> [@ref]`, `screenshot` (`--full`, `--annotate`), `console` (`--errors`), `wait` (`--ms` or `--selector`), `list`, `close` (`--all`). Add `--json` to any verb for machine-readable output.\n\nRules:\n\n- **Re-snapshot after any navigation, route change, modal open/close, or DOM mutation.** Refs are minted per snapshot and invalidated by navigation; acting on a stale ref returns a clear `[ariaRef:stale]` error \u2014 re-run `skeptic snapshot`.\n- Prefer `@eN` refs from the latest snapshot; for selectors, use the `selectorHint` grammar (`role=button:Save`, `text=...`, `css=...`, `testid=...`).\n- Use `--session <name>` for parallel isolated sessions.\n- The session browser defaults to headed for local debugging; pass `--headless` on the first `open` for headless environments (CI/containers).\n- Binary outputs (screenshots) come back as file paths, not inline data.\n\n## Mobile (Android)\n\nThe same verbs drive an Android app on an emulator or attached device via `adb` (no installed driver, no Appium). Pass `--platform android`; `open` takes a package name or deep link instead of a URL:\n\n```bash\nskeptic open com.example.app --platform android # launches the app\nskeptic snapshot -i # uiautomator tree \u2192 @eN refs\nskeptic click @e5 # taps the node\'s center\nskeptic fill @e3 "user@test.com" # ASCII input\nskeptic screenshot # device screencap \u2192 file path\nskeptic console --errors # logcat (app-filtered)\nskeptic close\n```\n\nRe-snapshot after every screen change; prefer `res=` (resource-id) and `desc=` (content-description) selectorHints over `text=`. `adb` text input is ASCII-only; non-ASCII `fill`/`type` returns a `[adbInput:unicode_unsupported]` error \u2014 set the value via a deep link or test seam instead. WebView contents are invisible to uiautomator; drive the web surface separately for in-WebView assertions. iOS simulator support (`--platform ios-sim`) is planned.\n\n## Writing Specs\n\nSkeptic specs import from `skeptic-cli`.\n\n```ts\nimport { test, expect } from "skeptic-cli";\n\ntest("homepage smoke", async ({ page, snapshot, screenshot, observability }) => {\n await page.goto("https://example.com");\n await expect(page).toHaveTitle(/Example Domain/);\n\n const tree = await snapshot(page, { interactive: true, compact: true });\n await (await tree.byRef("e1")).click();\n\n await screenshot("homepage", { fullPage: true });\n await observability.expectNoConsoleErrors();\n});\n```\n\nRules:\n\n- Put browser side effects inside `test(...)`, hooks, or helper functions called from tests.\n- Prefer role, label, text, and test-id locators over CSS.\n- `await snapshot(page)` before interacting through refs; `tree.byRef("eN")` is async \u2014 always `await` it.\n- Re-snapshot after navigation, route changes, modal open/close, or major DOM mutation.\n- Do not paste CLI `@eN` refs into specs. Use `selectorHint` from `inspect`, or `tree.byRef("eN")` only for refs from the same in-test `snapshot(page)` call.\n- Add `screenshot("name")` for states that would help debug a failure.\n\n## Observability Checks\n\nUse `--observability` for real QA evidence. In specs, assert the signals that match the risk:\n\n```ts\nawait observability.expectNoConsoleErrors();\nawait observability.expectNoNetworkErrors({ allow: [/analytics/] });\nawait observability.expectPerformance({ lcp: "<2500ms", cls: "<0.1" });\nawait observability.expectAccessible({ standard: "WCAG21AA" });\n```\n\n`skeptic run` always writes `results.json` to the output dir (default `./skeptic-output`). Use it plus screenshots, videos, traces, `network.json`, `console.json`, `accessibility.json`, and `perf-trace.md` as the evidence source. Reference artifact paths from `results.json` instead of guessing filenames. If an observability artifact reports a failure, fix the product or the test and re-run the same flow immediately.\n\n## Verification Standard\n\nBefore reporting completion for browser-facing work:\n\n- Run the smallest Skeptic command (session verbs or a spec) that actually exercises the changed behavior.\n- Test at least one adjacent or negative path when forms, routing, validation, auth, persistence, or shared components changed.\n- Read the full command output. Passing navigation alone is not enough.\n- If there are console errors, network failures, serious accessibility issues, poor Web Vitals, or visible regressions, fix and re-run.\n- State the exact command run and the main artifact path in the final report.\n',E=`interface:
64
+ display_name: "Skeptic"
65
+ short_description: "Use Skeptic to inspect pages, write TypeScript E2E tests, run browser QA, and collect observability evidence."
66
+ default_prompt: "Use Skeptic to verify this UI or browser behavior with real evidence and report the relevant artifacts."
67
+ `;async function F(e){let t=I(e.scope);if(!t){d.error("Unknown skill scope. Use --scope project or --scope user."),process.exitCode=1;return}let n=R(e.agent);if(n.length===0){d.error("No AI agent detected. Specify one with --agent (claude, codex, cursor, opencode, all)"),process.exitCode=1;return}let o=n.map(i=>T(i,t));for(let i of o){let a$2=`${i.agent} ${i.scope}`;if(i.status==="skipped"){d.warn(`${a$2}: skipped ${a$1.dim(i.targetDir)} (${i.reason??"unknown reason"})`);continue}let c=i.status==="already-installed"?"already installed":i.status==="updated"?"updated":"installed";d.success(`${a} skill ${c} for ${a$1.cyan(a$2)} at ${a$1.dim(i.targetDir)}`);}o.every(i=>i.status==="skipped")&&(process.exitCode=1);}function I(e){return e===void 0||e==="project"?"project":e==="user"?"user":null}function R(e){if(e==="all")return [...m];if(e!==void 0)return j(e)?[e]:[];let t=L();return t?[t]:[]}function j(e){return m.includes(e)}function L(){for(let e of m)try{return execSync(`which ${e}`,{stdio:"ignore"}),e}catch{}return null}function T(e,t){let n=_(e,t);return C(n,e,t)}function _(e,t){if(t==="project"){let i={claude:".claude/skills",codex:".agents/skills",cursor:".cursor/skills",opencode:".opencode/skills"};return r.resolve(process.cwd(),i[e],u)}let n=process.env.HOME||g.homedir();return e==="codex"?r.join(process.env.CODEX_HOME||r.join(n,".codex"),"skills",u):r.join(n,{claude:".claude/skills",cursor:".cursor/skills",opencode:".opencode/skills"}[e],u)}function C(e,t,n){let o=h(e),i=N(),a=r.join(e,"SKILL.md");if(i?v(i,e):s.existsSync(a)&&s.readFileSync(a,"utf-8")===S)return {agent:t,scope:n,targetDir:e,status:"already-installed"};if(o){if(o.isSymbolicLink())return {agent:t,scope:n,targetDir:e,status:"skipped",reason:"target is a symlink"};if(o.isDirectory())if(s.existsSync(a))if(k(a))s.rmSync(e,{recursive:true,force:true});else return {agent:t,scope:n,targetDir:e,status:"skipped",reason:"existing skill was not created by skeptic-cli"};else if($(e))s.rmSync(e,{recursive:true,force:true});else return {agent:t,scope:n,targetDir:e,status:"skipped",reason:"existing directory is not a Skeptic skill"};else if(o.isFile()){if(!k(e))return {agent:t,scope:n,targetDir:e,status:"skipped",reason:"existing file was not created by skeptic-cli"};s.unlinkSync(e);}else return {agent:t,scope:n,targetDir:e,status:"skipped",reason:"unsupported existing path"}}return s.mkdirSync(r.dirname(e),{recursive:true}),i?s.cpSync(i,e,{recursive:true}):U(e),{agent:t,scope:n,targetDir:e,status:o?"updated":"installed"}}function N(){let e=r.dirname(fileURLToPath(import.meta.url));return [r.resolve(e,"../agent-skills",u),r.resolve(e,"../../agent-skills",u),r.resolve(e,"../../../agent-skills",u)].find(n=>s.existsSync(r.join(n,"SKILL.md")))??null}function U(e){s.mkdirSync(r.join(e,"agents"),{recursive:true}),s.writeFileSync(r.join(e,"SKILL.md"),S,"utf-8"),s.writeFileSync(r.join(e,"agents","openai.yaml"),E,"utf-8");}function h(e){try{return s.lstatSync(e)}catch(t){if(t instanceof Error&&"code"in t&&t.code==="ENOENT")return null;throw t}}function $(e){return s.readdirSync(e).every(t=>x.has(t))}function k(e){let t=s.readFileSync(e,"utf-8");return t.includes(A)||t.includes(`# ${a} E2E Testing`)||t.includes(`${a} is a TypeScript test runner for AI agents`)}function v(e,t){let n=h(e),o=h(t);if(!n||!o||n.isSymbolicLink()||o.isSymbolicLink())return false;if(n.isDirectory()&&o.isDirectory()){let i=s.readdirSync(e).sort(),a=s.readdirSync(t).sort();return i.length!==a.length?false:i.every((c,y)=>c!==a[y]?false:v(r.join(e,c),r.join(t,c)))}return n.isFile()&&o.isFile()?s.readFileSync(e).equals(s.readFileSync(t)):false}export{B as runAddGitHubAction,F as runAddSkill};
@@ -0,0 +1,7 @@
1
+ import {createRequire}from'node:module';import {d}from'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import {a}from'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as s from'fs';import {execFileSync}from'child_process';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var y=["lint","check","typecheck","type-check","format","tsc"];async function S(u){let p="package.json";if(!s.existsSync(p)){d.error("No package.json found in current directory"),process.exitCode=1;return}let a$1=JSON.parse(s.readFileSync(p,"utf-8")).scripts??{},c=s.existsSync("pnpm-lock.yaml")?"pnpm":s.existsSync("yarn.lock")?"yarn":"npm",f=Object.keys(a$1).filter(o=>y.some(e=>o.includes(e)));if(f.length===0){d.warn("No lint/check/typecheck scripts found in package.json");return}d.info(`Running ${f.length} quality check(s) with ${a.cyan(c)}...
4
+ `);let l=0,r=0;for(let o of f){let e=performance.now();try{execFileSync(c,["run",o],{stdio:"pipe",encoding:"utf-8"});let i=Math.round(performance.now()-e);console.log(` ${a.green("\u2714")} ${o} ${a.dim(`(${i}ms)`)}`),l++;}catch(i){let g=Math.round(performance.now()-e);if(console.log(` ${a.red("\u2716")} ${o} ${a.dim(`(${g}ms)`)}`),i&&typeof i=="object"&&"stdout"in i){let d=String(i.stdout).trim();d&&console.log(a.dim(` ${d.split(`
5
+ `).slice(0,5).join(`
6
+ `)}`));}r++;}}if(console.log(),d.info(`${a.green(`${l} passed`)}, ${r>0?a.red(`${r} failed`):"0 failed"}`),u.fix){let o=Object.keys(a$1).find(e=>e==="lint:fix"||e==="fix");if(o){d.info(`
7
+ Running ${a.cyan(`${c} run ${o}`)}...`);try{execFileSync(c,["run",o],{stdio:"inherit"});}catch{d.warn("Auto-fix completed with issues");}}else d.warn("No lint:fix or fix script found \u2014 skipping --fix");}r>0&&(process.exitCode=1);}export{S as runAudit};
@@ -0,0 +1,2 @@
1
+ import {createRequire}from'node:module';export{a as commandUsesBrowser,b as prewarmDaemonIfNeeded}from'./chunk-AH75LR2T.mjs';import'./chunk-RU7M6UGM.mjs';import'./chunk-2VSGDT7T.mjs';import'./chunk-IYLF56WL.mjs';import'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
@@ -0,0 +1,21 @@
1
+ import {createRequire}from'node:module';import {d}from'./chunk-2ZORFJJP.mjs';import'./chunk-OHVNABCL.mjs';import {e}from'./chunk-RU7M6UGM.mjs';import {h as h$1,q as q$1,m,b}from'./chunk-2VSGDT7T.mjs';import'./chunk-7BFRKEFV.mjs';import'./chunk-IYLF56WL.mjs';import'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';import*as O from'fs';import*as h from'net';import {spawn}from'child_process';import {fileURLToPath}from'url';import {setTimeout as setTimeout$1}from'timers/promises';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var w=e=>new Promise(n=>{if(process.platform!=="win32"&&!O.existsSync(e)){n(false);return}let s=h.createConnection(b(e)),r=c=>{s.removeAllListeners(),s.destroy(),n(c);},o=setTimeout(()=>r(false),800);s.on("connect",()=>{clearTimeout(o),r(true);}),s.on("error",()=>{clearTimeout(o),r(false);});}),P=()=>{let e=process.env.SKEPTIC_DAEMON_BIN;if(e)return e;let n=process.argv[1];return n||fileURLToPath(new URL("../../dist/skeptic.mjs",import.meta.url))},B=async e=>{m();let n=h$1();if(await w(n))return {ok:true};if(e.autoSpawn===false)return {ok:false,reason:"no-session-daemon"};let s=["session-daemon","--engine",e.engine,e.headed?"--headed":"--headless"],r=spawn(process.execPath,[P(),...s],{detached:true,stdio:"ignore",env:{...process.env}});r.unref(),r.on("error",()=>{});let o=Date.now()+(e.spawnTimeoutMs??15e3);for(;Date.now()<o;){if(await w(n))return {ok:true};await setTimeout$1(100);}return {ok:false,reason:"session-daemon-spawn-timeout"}},x=async(e$1,n,s,r=3e4)=>{let o=await B(s);if(!o.ok)throw new Error(`session daemon: ${o.reason}`);let c=h$1(),d=process.env.SKEPTIC_DAEMON_AUTH_TOKEN,V={engine:s.engine,...d?{authToken:d}:{}},p=await q$1(c,V);if(!p.ok)throw new Error(`session daemon handshake failed: ${p.reason??"unknown"}`);return e(c,{method:e$1,params:d?{...n,authToken:d}:n},r)};var $=e=>({engine:e.platform==="android"?"android":e.platform==="ios-sim"?"ios-sim":"chromium",headed:e.headless!==true,cliVersion:"1.0.0"}),i=(e,n={})=>({session:e.session??"default",...n}),t=async(e,n,s,r)=>{let o;try{o=await x(e,n,$(s));}catch(c){let d=c instanceof Error?c.message:String(c);s.json?process.stdout.write(`${JSON.stringify({success:false,error:d})}
4
+ `):process.stderr.write(`skeptic: ${d}
5
+ `),process.exitCode=3;return}if(o.error){s.json?process.stdout.write(`${JSON.stringify({success:false,error:o.error})}
6
+ `):process.stderr.write(`skeptic: ${o.error}
7
+ `),process.exitCode=1;return}s.json?process.stdout.write(`${JSON.stringify({success:true,data:o.result})}
8
+ `):process.stdout.write(r(o.result));},U=(e,n)=>t("session.open",i(n,{url:e,...n.waitUntil?{waitUntil:n.waitUntil}:{}}),n,s=>{let r=s;return `opened ${r.url}${r.title?` \u2014 "${r.title}"`:""}
9
+ `}),j=e=>t("session.snapshot",i(e,{interactive:!!e.interactive,compact:!!e.compact}),e,n=>{let s=n;return d({yaml:s.yaml,refs:s.refs,stats:s.stats},{...s.note?{portabilityNote:s.note}:{}})}),S=e=>e.startsWith("@")?{ref:e.slice(1)}:{selector:e},a=(e,n)=>(s,r,o)=>t("session.act",i(o,{verb:e,...S(s),...r}),o,()=>`${n} ${s}
10
+ `),I=(e,n)=>a("click","clicked")(e,{},n),J=(e,n)=>a("hover","hovered")(e,{},n),A=(e,n)=>a("check","checked")(e,{},n),L=(e,n)=>a("uncheck","unchecked")(e,{},n),K=(e,n,s)=>a("press",`pressed ${n} on`)(e,{key:n},s),W=(e,n,s)=>a("fill","filled")(e,{text:n},s),G=(e,n,s)=>a("type","typed into")(e,{text:n},s),H=(e,n,s)=>a("select","selected in")(e,{value:n},s),q=e=>t("session.screenshot",i(e,{name:e.name??"screenshot",fullPage:!!e.full,annotate:!!e.annotate}),e,n=>`screenshot: ${n.path}
11
+ `),F=(e,n,s)=>t("session.query",i(s,{query:e,...n?S(n):{}}),s,r=>`${JSON.stringify(r.value)}
12
+ `),z=(e,n)=>e?a("scrollIntoView","scrolled into view")(e,{},n):t("session.act",i(n,{verb:"scroll",dx:n.dx??0,dy:n.dy??0}),n,()=>`scrolled by (${n.dx??0}, ${n.dy??0})
13
+ `),Q=e=>t("session.record",i(e,{durationSec:e.duration??3}),e,n=>{let s=n,r=s.degraded?" \u26A0 file is tiny \u2014 the device/emulator GPU may not be compositing into the capture (see `skeptic doctor`)":"";return `recorded ${s.durationSec}s \u2192 ${s.path} (${s.bytes} bytes)${r}
14
+ `}),X=e=>t("session.observe",i(e,{collector:e.errors?"errors":"console"}),e,n=>`${JSON.stringify(n,null,2)}
15
+ `),Y=(e,n)=>t("session.observe",i(n,{collector:e}),n,s=>`${JSON.stringify(s,null,2)}
16
+ `),Z=e=>t("session.wait",i(e,{...e.ms!==void 0?{ms:e.ms}:{},...e.selector?{selector:e.selector}:{},...e.state?{state:e.state}:{},...e.timeoutMs!==void 0?{timeoutMs:e.timeoutMs}:{}}),e,()=>`ok
17
+ `),ee=e=>t("session.close",i(e),e,n=>{let s=n;return s.closed?`closed session "${s.session}"
18
+ `:`no open session "${s.session}"
19
+ `}),ne=e=>t("session.list",{},e,n=>{let s=n.sessions;return s.length===0?`no open sessions
20
+ `:s.map(r=>`${r.name} ${r.url||"(blank)"} ${Math.round(r.ageMs/1e3)}s
21
+ `).join("")});export{A as runCheck,I as runClick,ee as runClose,X as runConsole,W as runFill,F as runGet,J as runHover,ne as runList,Y as runObserve,U as runOpen,K as runPress,Q as runRecord,q as runScreenshot,z as runScroll,H as runSelect,j as runSnapshot,G as runType,L as runUncheck,Z as runWait};
@@ -0,0 +1,3 @@
1
+ import {createRequire}from'node:module';import {b}from'./chunk-IYLF56WL.mjs';import {d}from'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ async function f(o,a={}){let l=await b(),{registry:r}=l,w=o.includes("all")?[]:o,s=r.resolveBrowsers(w,{}),c=()=>{let n=s.map(t=>t.name).filter(Boolean);return n.length>0?n.join(", "):"default browsers"};if(a.dryRun){a.withDeps&&(d.info("[dry-run] Would install OS-level dependencies for Playwright browsers (sudo on Linux)."),await r.installDeps(s,true)),d.info(`[dry-run] Would install Playwright browsers: ${c()}`),d.info("[dry-run] No changes made. Re-run without --dry-run to install.");return}a.withDeps&&(d.info("Installing system dependencies for Playwright browsers\u2026"),await r.installDeps(s,false)),d.info("Installing Playwright browsers\u2026"),await r.install(s,{force:false});try{await r.validateHostRequirementsForExecutablesIfNeeded(s,"javascript");}catch(n){let t=n;t.name="Playwright Host validation warning",d.warn(t.message);}d.success("Playwright browser install complete.");}export{f as runBrowsersInstall};
@@ -0,0 +1,7 @@
1
+ import {createRequire}from'node:module';import'./chunk-2YKSIUIN.mjs';import {EventEmitter}from'events';import {stat as stat$1,unwatchFile,watchFile,watch}from'fs';import {stat,realpath,lstat,readdir,open}from'fs/promises';import*as f from'path';import {resolve,join,relative,sep}from'path';import {Readable}from'stream';import {type}from'os';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
2
+ createRequire(import.meta.url);
3
+ var E={FILE_TYPE:"files",DIR_TYPE:"directories",FILE_DIR_TYPE:"files_directories",EVERYTHING_TYPE:"all"},N={root:".",fileFilter:r=>true,directoryFilter:r=>true,type:E.FILE_TYPE,lstat:false,depth:2147483648,alwaysStat:false,highWaterMark:4096};Object.freeze(N);var q="READDIRP_RECURSIVE_ERROR",Et=new Set(["ENOENT","EPERM","EACCES","ELOOP",q]),V=[E.DIR_TYPE,E.EVERYTHING_TYPE,E.FILE_DIR_TYPE,E.FILE_TYPE],gt=new Set([E.DIR_TYPE,E.EVERYTHING_TYPE,E.FILE_DIR_TYPE]),yt=new Set([E.EVERYTHING_TYPE,E.FILE_DIR_TYPE,E.FILE_TYPE]),Pt=r=>Et.has(r.code),Rt=process.platform==="win32",B=r=>true,$=r=>{if(r===void 0)return B;if(typeof r=="function")return r;if(typeof r=="string"){let t=r.trim();return e=>e.basename===t}if(Array.isArray(r)){let t=r.map(e=>e.trim());return e=>t.some(i=>e.basename===i)}return B},k=class extends Readable{parents;reading;parent;_stat;_maxDepth;_wantsDir;_wantsFile;_wantsEverything;_root;_isDirent;_statsProp;_rdOptions;_fileFilter;_directoryFilter;constructor(t={}){super({objectMode:true,autoDestroy:true,highWaterMark:t.highWaterMark});let e={...N,...t},{root:i,type:s}=e;this._fileFilter=$(e.fileFilter),this._directoryFilter=$(e.directoryFilter);let n=e.lstat?lstat:stat;Rt?this._stat=h=>n(h,{bigint:true}):this._stat=n,this._maxDepth=e.depth!=null&&Number.isSafeInteger(e.depth)?e.depth:N.depth,this._wantsDir=s?gt.has(s):false,this._wantsFile=s?yt.has(s):false,this._wantsEverything=s===E.EVERYTHING_TYPE,this._root=resolve(i),this._isDirent=!e.alwaysStat,this._statsProp=this._isDirent?"dirent":"stats",this._rdOptions={encoding:"utf8",withFileTypes:this._isDirent},this.parents=[this._exploreDir(i,1)],this.reading=false,this.parent=void 0;}async _read(t){if(!this.reading){this.reading=true;try{for(;!this.destroyed&&t>0;){let e=this.parent,i=e&&e.files;if(i&&i.length>0){let{path:s,depth:n}=e,h=i.splice(0,t).map(a=>this._formatEntry(a,s)),o=await Promise.all(h);for(let a of o){if(!a)continue;if(this.destroyed)return;let l=await this._getEntryType(a);l==="directory"&&this._directoryFilter(a)?(n<=this._maxDepth&&this.parents.push(this._exploreDir(a.fullPath,n+1)),this._wantsDir&&(this.push(a),t--)):(l==="file"||this._includeAsFile(a))&&this._fileFilter(a)&&this._wantsFile&&(this.push(a),t--);}}else {let s=this.parents.pop();if(!s){this.push(null);break}if(this.parent=await s,this.destroyed)return}}}catch(e){this.destroy(e);}finally{this.reading=false;}}}async _exploreDir(t,e){let i;try{i=await readdir(t,this._rdOptions);}catch(s){this._onError(s);}return {files:i,depth:e,path:t}}async _formatEntry(t,e){let i,s=this._isDirent?t.name:t;try{let n=resolve(join(e,s));i={path:relative(this._root,n),fullPath:n,basename:s},i[this._statsProp]=this._isDirent?t:await this._stat(n);}catch(n){this._onError(n);return}return i}_onError(t){Pt(t)&&!this.destroyed?this.emit("warn",t):this.destroy(t);}async _getEntryType(t){if(!t&&this._statsProp in t)return "";let e=t[this._statsProp];if(e.isFile())return "file";if(e.isDirectory())return "directory";if(e&&e.isSymbolicLink()){let i=t.fullPath;try{let s=await realpath(i),n=await lstat(s);if(n.isFile())return "file";if(n.isDirectory()){let h=s.length;if(i.startsWith(s)&&i.substr(h,1)===sep){let o=new Error(`Circular symlink detected: "${i}" points to "${s}"`);return o.code=q,this._onError(o)}return "directory"}}catch(s){return this._onError(s),""}}}_includeAsFile(t){let e=t&&t[this._statsProp];return e&&this._wantsEverything&&!e.isDirectory()}};function J(r,t={}){let e=t.entryType||t.type;if(e==="both"&&(e=E.FILE_DIR_TYPE),e&&(t.type=e),r){if(typeof r!="string")throw new TypeError("readdirp: root argument must be a string. Usage: readdirp(root, options)");if(e&&!V.includes(e))throw new Error(`readdirp: Invalid type passed. Use one of ${V.join(", ")}`)}else throw new Error("readdirp: root argument is required. Usage: readdirp(root, options)");return t.root=r,new k(t)}var xt="data",M="end",tt="close",F=()=>{};var S=process.platform,z=S==="win32",Ft=S==="darwin",St=S==="linux",At=S==="freebsd",et=type()==="OS400",p={ALL:"all",READY:"ready",ADD:"add",CHANGE:"change",ADD_DIR:"addDir",UNLINK:"unlink",UNLINK_DIR:"unlinkDir",RAW:"raw",ERROR:"error"},g=p,Wt="watch",Nt={lstat:lstat,stat:stat},P="listeners",I="errHandlers",R="rawEmitters",kt=[P,I,R],Lt=new Set(["3dm","3ds","3g2","3gp","7z","a","aac","adp","afdesign","afphoto","afpub","ai","aif","aiff","alz","ape","apk","appimage","ar","arj","asf","au","avi","bak","baml","bh","bin","bk","bmp","btif","bz2","bzip2","cab","caf","cgm","class","cmx","cpio","cr2","cur","dat","dcm","deb","dex","djvu","dll","dmg","dng","doc","docm","docx","dot","dotm","dra","DS_Store","dsk","dts","dtshd","dvb","dwg","dxf","ecelp4800","ecelp7470","ecelp9600","egg","eol","eot","epub","exe","f4v","fbs","fh","fla","flac","flatpak","fli","flv","fpx","fst","fvt","g3","gh","gif","graffle","gz","gzip","h261","h263","h264","icns","ico","ief","img","ipa","iso","jar","jpeg","jpg","jpgv","jpm","jxr","key","ktx","lha","lib","lvp","lz","lzh","lzma","lzo","m3u","m4a","m4v","mar","mdi","mht","mid","midi","mj2","mka","mkv","mmr","mng","mobi","mov","movie","mp3","mp4","mp4a","mpeg","mpg","mpga","mxu","nef","npx","numbers","nupkg","o","odp","ods","odt","oga","ogg","ogv","otf","ott","pages","pbm","pcx","pdb","pdf","pea","pgm","pic","png","pnm","pot","potm","potx","ppa","ppam","ppm","pps","ppsm","ppsx","ppt","pptm","pptx","psd","pya","pyc","pyo","pyv","qt","rar","ras","raw","resources","rgb","rip","rlc","rmf","rmvb","rpm","rtf","rz","s3m","s7z","scpt","sgi","shar","snap","sil","sketch","slk","smv","snk","so","stl","suo","sub","swf","tar","tbz","tbz2","tga","tgz","thmx","tif","tiff","tlz","ttc","ttf","txz","udf","uvh","uvi","uvm","uvp","uvs","uvu","viv","vob","war","wav","wax","wbmp","wdp","weba","webm","webp","whl","wim","wm","wma","wmv","wmx","woff","woff2","wrm","wvx","xbm","xif","xla","xlam","xls","xlsb","xlsm","xlsx","xlt","xltm","xltx","xm","xmind","xpi","xpm","xwd","xz","z","zip","zipx"]),Ct=r=>Lt.has(f.extname(r).slice(1).toLowerCase()),O=(r,t)=>{r instanceof Set?r.forEach(t):t(r);},b=(r,t,e)=>{let i=r[t];i instanceof Set||(r[t]=i=new Set([i])),i.add(e);},Ot=r=>t=>{let e=r[t];e instanceof Set?e.clear():delete r[t];},D=(r,t,e)=>{let i=r[t];i instanceof Set?i.delete(e):i===e&&delete r[t];},st=r=>r instanceof Set?r.size===0:!r,T=new Map;function X(r,t,e,i,s){let n=(h,o)=>{e(r),s(h,o,{watchedPath:r}),o&&r!==o&&v(f.resolve(r,o),P,f.join(r,o));};try{return watch(r,{persistent:t.persistent},n)}catch(h){i(h);return}}var v=(r,t,e,i,s)=>{let n=T.get(r);n&&O(n[t],h=>{h(e,i,s);});},Mt=(r,t,e,i)=>{let{listener:s,errHandler:n,rawEmitter:h}=i,o=T.get(t),a;if(!e.persistent)return a=X(r,e,s,n,h),a?a.close.bind(a):void 0;if(o)b(o,P,s),b(o,I,n),b(o,R,h);else {if(a=X(r,e,v.bind(null,t,P),n,v.bind(null,t,R)),!a)return;a.on(g.ERROR,async l=>{let c=v.bind(null,t,I);if(o&&(o.watcherUnusable=true),z&&l.code==="EPERM")try{await(await open(r,"r")).close(),c(l);}catch{}else c(l);}),o={listeners:s,errHandlers:n,rawEmitters:h,watcher:a},T.set(t,o);}return ()=>{D(o,P,s),D(o,I,n),D(o,R,h),st(o.listeners)&&(o.watcher.close(),T.delete(t),kt.forEach(Ot(o)),o.watcher=void 0,Object.freeze(o));}},C=new Map,zt=(r,t,e,i)=>{let{listener:s,rawEmitter:n}=i,h=C.get(t),o=h&&h.options;return o&&(o.persistent<e.persistent||o.interval>e.interval)&&(unwatchFile(t),h=void 0),h?(b(h,P,s),b(h,R,n)):(h={listeners:s,rawEmitters:n,options:e,watcher:watchFile(t,e,(a,l)=>{O(h.rawEmitters,u=>{u(g.CHANGE,t,{curr:a,prev:l});});let c=a.mtimeMs;(a.size!==l.size||c>l.mtimeMs||c===0)&&O(h.listeners,u=>u(r,a));})},C.set(t,h)),()=>{D(h,P,s),D(h,R,n),st(h.listeners)&&(C.delete(t),unwatchFile(t),h.options=h.watcher=void 0,Object.freeze(h));}},x=class{fsw;_boundHandleError;constructor(t){this.fsw=t,this._boundHandleError=e=>t._handleError(e);}_watchWithNodeFs(t,e){let i=this.fsw.options,s=f.dirname(t),n=f.basename(t);this.fsw._getWatchedDir(s).add(n);let o=f.resolve(t),a={persistent:i.persistent};e||(e=F);let l;if(i.usePolling){let c=i.interval!==i.binaryInterval;a.interval=c&&Ct(n)?i.binaryInterval:i.interval,l=zt(t,o,a,{listener:e,rawEmitter:this.fsw._emitRaw});}else l=Mt(t,o,a,{listener:e,errHandler:this._boundHandleError,rawEmitter:this.fsw._emitRaw});return l}_handleFile(t,e,i){if(this.fsw.closed)return;let s=f.dirname(t),n=f.basename(t),h=this.fsw._getWatchedDir(s),o=e;if(h.has(n))return;let a=async(c,u)=>{if(this.fsw._throttle(Wt,t,5)){if(!u||u.mtimeMs===0)try{let d=await stat(t);if(this.fsw.closed)return;let m=d.atimeMs,w=d.mtimeMs;if((!m||m<=w||w!==o.mtimeMs)&&this.fsw._emit(g.CHANGE,t,d),(Ft||St||At)&&o.ino!==d.ino){this.fsw._closeFile(c),o=d;let y=this._watchWithNodeFs(t,a);y&&this.fsw._addPathCloser(c,y);}else o=d;}catch{this.fsw._remove(s,n);}else if(h.has(n)){let d=u.atimeMs,m=u.mtimeMs;(!d||d<=m||m!==o.mtimeMs)&&this.fsw._emit(g.CHANGE,t,u),o=u;}}},l=this._watchWithNodeFs(t,a);if(!(i&&this.fsw.options.ignoreInitial)&&this.fsw._isntIgnored(t)){if(!this.fsw._throttle(g.ADD,t,0))return;this.fsw._emit(g.ADD,t,e);}return l}async _handleSymlink(t,e,i,s){if(this.fsw.closed)return;let n=t.fullPath,h=this.fsw._getWatchedDir(e);if(!this.fsw.options.followSymlinks){this.fsw._incrReadyCount();let o;try{o=await realpath(i);}catch{return this.fsw._emitReady(),true}return this.fsw.closed?void 0:(h.has(s)?this.fsw._symlinkPaths.get(n)!==o&&(this.fsw._symlinkPaths.set(n,o),this.fsw._emit(g.CHANGE,i,t.stats)):(h.add(s),this.fsw._symlinkPaths.set(n,o),this.fsw._emit(g.ADD,i,t.stats)),this.fsw._emitReady(),true)}if(this.fsw._symlinkPaths.has(n))return true;this.fsw._symlinkPaths.set(n,true);}_handleRead(t,e,i,s,n,h,o){t=f.join(t,"");let a=s?`${t}:${s}`:t;if(o=this.fsw._throttle("readdir",a,1e3),!o)return;let l=this.fsw._getWatchedDir(i.path),c=new Set,u=this.fsw._readdirp(t,{fileFilter:d=>i.filterPath(d),directoryFilter:d=>i.filterDir(d)});if(u)return u.on(xt,async d=>{if(this.fsw.closed){u=void 0;return}let m=d.path,w=f.join(t,m);if(c.add(m),!(d.stats.isSymbolicLink()&&await this._handleSymlink(d,t,w,m))){if(this.fsw.closed){u=void 0;return}(m===s||!s&&!l.has(m))&&(this.fsw._incrReadyCount(),w=f.join(n,f.relative(n,w)),this._addToNodeFs(w,e,i,h+1));}}).on(g.ERROR,this._boundHandleError),new Promise((d,m)=>{if(!u)return m();u.once(M,()=>{if(this.fsw.closed){u=void 0;return}let w=o?o.clear():false;d(void 0),l.getChildren().filter(y=>y!==t&&!c.has(y)).forEach(y=>{this.fsw._remove(t,y);}),u=void 0,w&&this._handleRead(t,false,i,s,n,h,o);});})}async _handleDir(t,e,i,s,n,h,o){let a=this.fsw._getWatchedDir(f.dirname(t)),l=a.has(f.basename(t));!(i&&this.fsw.options.ignoreInitial)&&!n&&!l&&this.fsw._emit(g.ADD_DIR,t,e),a.add(f.basename(t)),this.fsw._getWatchedDir(t);let c,u,d=this.fsw.options.depth;if((d==null||s<=d)&&!this.fsw._symlinkPaths.has(o)){if(!n&&(await this._handleRead(t,i,h,n,t,s,c),this.fsw.closed))return;u=this._watchWithNodeFs(t,(m,w)=>{w&&w.mtimeMs===0||this._handleRead(m,false,h,n,t,s,c);});}return u}async _addToNodeFs(t,e,i,s,n){let h=this.fsw._emitReady;if(this.fsw._isIgnored(t)||this.fsw.closed)return h(),false;let o=this.fsw._getWatchHelpers(t);i&&(o.filterPath=a=>i.filterPath(a),o.filterDir=a=>i.filterDir(a));try{let a=await Nt[o.statMethod](o.watchPath);if(this.fsw.closed)return;if(this.fsw._isIgnored(o.watchPath,a))return h(),!1;let l=this.fsw.options.followSymlinks,c;if(a.isDirectory()){let u=f.resolve(t),d=l?await realpath(t):t;if(this.fsw.closed||(c=await this._handleDir(o.watchPath,a,e,s,n,o,d),this.fsw.closed))return;u!==d&&d!==void 0&&this.fsw._symlinkPaths.set(u,d);}else if(a.isSymbolicLink()){let u=l?await realpath(t):t;if(this.fsw.closed)return;let d=f.dirname(o.watchPath);if(this.fsw._getWatchedDir(d).add(o.watchPath),this.fsw._emit(g.ADD,o.watchPath,a),c=await this._handleDir(d,a,e,s,t,o,u),this.fsw.closed)return;u!==void 0&&this.fsw._symlinkPaths.set(f.resolve(t),u);}else c=this._handleFile(o.watchPath,a,e);return h(),c&&this.fsw._addPathCloser(t,c),!1}catch(a){if(this.fsw._handleError(a))return h(),t}}};var H="/",Gt="//",at=".",Kt="..",Vt="string",Bt=/\\/g,ht=/\/\//g,$t=/\..*\.(sw[px])$|~$|\.subl.*\.tmp/,qt=/^\.[/\\]/;function A(r){return Array.isArray(r)?r:[r]}var j=r=>typeof r=="object"&&r!==null&&!(r instanceof RegExp);function Jt(r){return typeof r=="function"?r:typeof r=="string"?t=>r===t:r instanceof RegExp?t=>r.test(t):typeof r=="object"&&r!==null?t=>{if(r.path===t)return true;if(r.recursive){let e=f.relative(r.path,t);return e?!e.startsWith("..")&&!f.isAbsolute(e):false}return false}:()=>false}function Qt(r){if(typeof r!="string")throw new Error("string expected");r=f.normalize(r),r=r.replace(/\\/g,"/");let t=false;return r.startsWith("//")&&(t=true),r=r.replace(ht,"/"),t&&(r="/"+r),r}function it(r,t,e){let i=Qt(t);for(let s=0;s<r.length;s++){let n=r[s];if(n(i,e))return true}return false}function Xt(r,t){if(r==null)throw new TypeError("anymatch: specify first argument");let i=A(r).map(s=>Jt(s));return t==null?(s,n)=>it(i,s,n):it(i,t)}var rt=r=>{let t=A(r).flat();if(!t.every(e=>typeof e===Vt))throw new TypeError(`Non-string provided as watch path: ${t}`);return t.map(lt)},nt=r=>{let t=r.replace(Bt,H),e=false;return t.startsWith(Gt)&&(e=true),t=t.replace(ht,H),e&&(t=H+t),t},lt=r=>nt(f.normalize(nt(r))),ot=(r="")=>t=>typeof t=="string"?lt(f.isAbsolute(t)?t:f.join(r,t)):t,Zt=(r,t)=>f.isAbsolute(r)?r:f.join(t,r),te=Object.freeze(new Set),Y=class{path;_removeWatcher;items;constructor(t,e){this.path=t,this._removeWatcher=e,this.items=new Set;}add(t){let{items:e}=this;e&&t!==at&&t!==Kt&&e.add(t);}async remove(t){let{items:e}=this;if(!e||(e.delete(t),e.size>0))return;let i=this.path;try{await readdir(i);}catch{this._removeWatcher&&this._removeWatcher(f.dirname(i),f.basename(i));}}has(t){let{items:e}=this;if(e)return e.has(t)}getChildren(){let{items:t}=this;return t?[...t.values()]:[]}dispose(){this.items.clear(),this.path="",this._removeWatcher=F,this.items=te,Object.freeze(this);}},ee="stat",se="lstat",U=class{fsw;path;watchPath;fullWatchPath;dirParts;followSymlinks;statMethod;constructor(t,e,i){this.fsw=i;let s=t;this.path=t=t.replace(qt,""),this.watchPath=s,this.fullWatchPath=f.resolve(s),this.dirParts=[],this.dirParts.forEach(n=>{n.length>1&&n.pop();}),this.followSymlinks=e,this.statMethod=e?ee:se;}entryPath(t){return f.join(this.watchPath,f.relative(this.watchPath,t.fullPath))}filterPath(t){let{stats:e}=t;if(e&&e.isSymbolicLink())return this.filterDir(t);let i=this.entryPath(t);return this.fsw._isntIgnored(i,e)&&this.fsw._hasReadPermissions(e)}filterDir(t){return this.fsw._isntIgnored(this.entryPath(t),t.stats)}},W=class extends EventEmitter{closed;options;_closers;_ignoredPaths;_throttled;_streams;_symlinkPaths;_watched;_pendingWrites;_pendingUnlinks;_readyCount;_emitReady;_closePromise;_userIgnored;_readyEmitted;_emitRaw;_boundRemove;_nodeFsHandler;constructor(t={}){super(),this.closed=false,this._closers=new Map,this._ignoredPaths=new Set,this._throttled=new Map,this._streams=new Set,this._symlinkPaths=new Map,this._watched=new Map,this._pendingWrites=new Map,this._pendingUnlinks=new Map,this._readyCount=0,this._readyEmitted=false;let e=t.awaitWriteFinish,i={stabilityThreshold:2e3,pollInterval:100},s={persistent:true,ignoreInitial:false,ignorePermissionErrors:false,interval:100,binaryInterval:300,followSymlinks:true,usePolling:false,atomic:true,...t,ignored:t.ignored?A(t.ignored):A([]),awaitWriteFinish:e===true?i:typeof e=="object"?{...i,...e}:false};et&&(s.usePolling=true),s.atomic===void 0&&(s.atomic=!s.usePolling);let n=process.env.CHOKIDAR_USEPOLLING;if(n!==void 0){let a=n.toLowerCase();a==="false"||a==="0"?s.usePolling=false:a==="true"||a==="1"?s.usePolling=true:s.usePolling=!!a;}let h=process.env.CHOKIDAR_INTERVAL;h&&(s.interval=Number.parseInt(h,10));let o=0;this._emitReady=()=>{o++,o>=this._readyCount&&(this._emitReady=F,this._readyEmitted=true,process.nextTick(()=>this.emit(p.READY)));},this._emitRaw=(...a)=>this.emit(p.RAW,...a),this._boundRemove=this._remove.bind(this),this.options=s,this._nodeFsHandler=new x(this),Object.freeze(s);}_addIgnoredPath(t){if(j(t)){for(let e of this._ignoredPaths)if(j(e)&&e.path===t.path&&e.recursive===t.recursive)return}this._ignoredPaths.add(t);}_removeIgnoredPath(t){if(this._ignoredPaths.delete(t),typeof t=="string")for(let e of this._ignoredPaths)j(e)&&e.path===t&&this._ignoredPaths.delete(e);}add(t,e,i){let{cwd:s}=this.options;this.closed=false,this._closePromise=void 0;let n=rt(t);return s&&(n=n.map(h=>Zt(h,s))),n.forEach(h=>{this._removeIgnoredPath(h);}),this._userIgnored=void 0,this._readyCount||(this._readyCount=0),this._readyCount+=n.length,Promise.all(n.map(async h=>{let o=await this._nodeFsHandler._addToNodeFs(h,!i,void 0,0,e);return o&&this._emitReady(),o})).then(h=>{this.closed||h.forEach(o=>{o&&this.add(f.dirname(o),f.basename(e||o));});}),this}unwatch(t){if(this.closed)return this;let e=rt(t),{cwd:i}=this.options;return e.forEach(s=>{!f.isAbsolute(s)&&!this._closers.has(s)&&(i&&(s=f.join(i,s)),s=f.resolve(s)),this._closePath(s),this._addIgnoredPath(s),this._watched.has(s)&&this._addIgnoredPath({path:s,recursive:true}),this._userIgnored=void 0;}),this}close(){if(this._closePromise)return this._closePromise;this.closed=true,this.removeAllListeners();let t=[];return this._closers.forEach(e=>e.forEach(i=>{let s=i();s instanceof Promise&&t.push(s);})),this._streams.forEach(e=>e.destroy()),this._userIgnored=void 0,this._readyCount=0,this._readyEmitted=false,this._watched.forEach(e=>e.dispose()),this._closers.clear(),this._watched.clear(),this._streams.clear(),this._symlinkPaths.clear(),this._throttled.clear(),this._closePromise=t.length?Promise.all(t).then(()=>{}):Promise.resolve(),this._closePromise}getWatched(){let t={};return this._watched.forEach((e,i)=>{let n=(this.options.cwd?f.relative(this.options.cwd,i):i)||at;t[n]=e.getChildren().sort();}),t}emitWithAll(t,e){this.emit(t,...e),t!==p.ERROR&&this.emit(p.ALL,t,...e);}async _emit(t,e,i){if(this.closed)return;let s=this.options;z&&(e=f.normalize(e)),s.cwd&&(e=f.relative(s.cwd,e));let n=[e];i!=null&&n.push(i);let h=s.awaitWriteFinish,o;if(h&&(o=this._pendingWrites.get(e)))return o.lastChange=new Date,this;if(s.atomic){if(t===p.UNLINK)return this._pendingUnlinks.set(e,[t,...n]),setTimeout(()=>{this._pendingUnlinks.forEach((a,l)=>{this.emit(...a),this.emit(p.ALL,...a),this._pendingUnlinks.delete(l);});},typeof s.atomic=="number"?s.atomic:100),this;t===p.ADD&&this._pendingUnlinks.has(e)&&(t=p.CHANGE,this._pendingUnlinks.delete(e));}if(h&&(t===p.ADD||t===p.CHANGE)&&this._readyEmitted){let a=(l,c)=>{l?(t=p.ERROR,n[0]=l,this.emitWithAll(t,n)):c&&(n.length>1?n[1]=c:n.push(c),this.emitWithAll(t,n));};return this._awaitWriteFinish(e,h.stabilityThreshold,t,a),this}if(t===p.CHANGE&&!this._throttle(p.CHANGE,e,50))return this;if(s.alwaysStat&&i===void 0&&(t===p.ADD||t===p.ADD_DIR||t===p.CHANGE)){let a=s.cwd?f.join(s.cwd,e):e,l;try{l=await stat(a);}catch{}if(!l||this.closed)return;n.push(l);}return this.emitWithAll(t,n),this}_handleError(t){let e=t&&t.code;return t&&e!=="ENOENT"&&e!=="ENOTDIR"&&(!this.options.ignorePermissionErrors||e!=="EPERM"&&e!=="EACCES")&&this.emit(p.ERROR,t),t||this.closed}_throttle(t,e,i){this._throttled.has(t)||this._throttled.set(t,new Map);let s=this._throttled.get(t);if(!s)throw new Error("invalid throttle");let n=s.get(e);if(n)return n.count++,false;let h,o=()=>{let l=s.get(e),c=l?l.count:0;return s.delete(e),clearTimeout(h),l&&clearTimeout(l.timeoutObject),c};h=setTimeout(o,i);let a={timeoutObject:h,clear:o,count:0};return s.set(e,a),a}_incrReadyCount(){return this._readyCount++}_awaitWriteFinish(t,e,i,s){let n=this.options.awaitWriteFinish;if(typeof n!="object")return;let h=n.pollInterval,o,a=t;this.options.cwd&&!f.isAbsolute(t)&&(a=f.join(this.options.cwd,t));let l=new Date,c=this._pendingWrites;function u(d){stat$1(a,(m,w)=>{if(m||!c.has(t)){m&&m.code!=="ENOENT"&&s(m);return}let y=Number(new Date);d&&w.size!==d.size&&(c.get(t).lastChange=y);let ct=c.get(t);y-ct.lastChange>=e?(c.delete(t),s(void 0,w)):o=setTimeout(u,h,w);});}c.has(t)||(c.set(t,{lastChange:l,cancelWait:()=>(c.delete(t),clearTimeout(o),i)}),o=setTimeout(u,h));}_isIgnored(t,e){if(this.options.atomic&&$t.test(t))return true;if(!this._userIgnored){let{cwd:i}=this.options,n=(this.options.ignored||[]).map(ot(i)),o=[...[...this._ignoredPaths].map(ot(i)),...n];this._userIgnored=Xt(o,void 0);}return this._userIgnored(t,e)}_isntIgnored(t,e){return !this._isIgnored(t,e)}_getWatchHelpers(t){return new U(t,this.options.followSymlinks,this)}_getWatchedDir(t){let e=f.resolve(t);return this._watched.has(e)||this._watched.set(e,new Y(e,this._boundRemove)),this._watched.get(e)}_hasReadPermissions(t){return this.options.ignorePermissionErrors?true:!!(Number(t.mode)&256)}_remove(t,e,i){let s=f.join(t,e),n=f.resolve(s);if(i=i??(this._watched.has(s)||this._watched.has(n)),!this._throttle("remove",s,100))return;!i&&this._watched.size===1&&this.add(t,e,true),this._getWatchedDir(s).getChildren().forEach(d=>this._remove(s,d));let a=this._getWatchedDir(t),l=a.has(e);a.remove(e),this._symlinkPaths.has(n)&&this._symlinkPaths.delete(n);let c=s;if(this.options.cwd&&(c=f.relative(this.options.cwd,s)),this.options.awaitWriteFinish&&this._pendingWrites.has(c)&&this._pendingWrites.get(c).cancelWait()===p.ADD)return;this._watched.delete(s),this._watched.delete(n);let u=i?p.UNLINK_DIR:p.UNLINK;l&&!this._isIgnored(s)&&this._emit(u,s),this._closePath(s);}_closePath(t){this._closeFile(t);let e=f.dirname(t);this._getWatchedDir(e).remove(f.basename(t));}_closeFile(t){let e=this._closers.get(t);e&&(e.forEach(i=>i()),this._closers.delete(t));}_addPathCloser(t,e){if(!e)return;let i=this._closers.get(t);i||(i=[],this._closers.set(t,i)),i.push(e);}_readdirp(t,e){if(this.closed)return;let i={type:p.ALL,alwaysStat:true,lstat:true,...e,depth:0},s=J(t,i);return this._streams.add(s),s.once(tt,()=>{s=void 0;}),s.once(M,()=>{s&&(this._streams.delete(s),s=void 0);}),s}};function ie(r,t={}){let e=new W(t);return e.add(r),e}var ye={watch:ie,FSWatcher:W};/*! Bundled license information:
4
+
5
+ chokidar/index.js:
6
+ (*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) *)
7
+ */export{W as FSWatcher,U as WatchHelper,ye as default,ie as watch};