From 64865c558877d6843dfc8865fc749bcde924b5e0 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 14:43:51 +0000 Subject: [PATCH 01/15] docs: design for VS Code/Cursor preview extension Co-Authored-By: Claude Opus 4.8 (1M context) --- .../2026-07-10-vscode-extension-design.md | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 docs/specs/2026-07-10-vscode-extension-design.md diff --git a/docs/specs/2026-07-10-vscode-extension-design.md b/docs/specs/2026-07-10-vscode-extension-design.md new file mode 100644 index 0000000..bd44262 --- /dev/null +++ b/docs/specs/2026-07-10-vscode-extension-design.md @@ -0,0 +1,129 @@ +# reefdoc VS Code / Cursor Extension — Design + +**Date:** 2026-07-10 +**Status:** Design approved; not yet implemented. + +## Summary + +An editor extension that brings reefdoc's existing preview UI *inside* VS Code +and Cursor, so you no longer switch to a separate browser tab. The extension is +a thin **launcher + embedder**: it spawns the bundled `reefdoc` binary pointed +at the workspace folder, then displays that running server's localhost UI in a +VS Code webview panel. The Go backend and vanilla-JS frontend are reused +verbatim — no reimplementation of rendering, watching, or live reload. + +Cursor is a VS Code fork, so a single extension covers both editors. + +## Goals + +- Show the full reefdoc app (file tree, tabs, TOC, live reload, change + highlighting) in an editor tab instead of a browser tab. +- Reuse the existing binary and frontend with zero changes to rendering logic. +- One command to open the preview; single-instance per window. +- Bundle per-platform binaries so users need no separate install. +- Work identically in VS Code and Cursor. + +## Non-goals (YAGNI) + +- **Marketplace publishing.** Distribution is out of scope; the build produces a + local `.vsix` installed via "Install from VSIX." This is for in-editor use, + not public distribution. +- **Active-editor sync / scroll-sync / click-to-source.** The panel shows + reefdoc's own navigation (its file tree + tabs), not the currently focused + editor file. Deeper editor integration is a possible future project, not this + one. +- **Remote / Codespaces support.** Targets local desktop use. `asExternalUri` + port-forwarding is noted as a future hook but not implemented. +- **Reimplementing the frontend against VS Code APIs.** Explicitly rejected — it + throws away the whole point of bundling the binary. + +## Binary flag: already present + +The binary already accepts `--addr` (`main.go:23`, default `127.0.0.1:8080`), +so the extension can direct it to any port with no change to `main.go`. The +extension selects a free port itself (bind an ephemeral socket, read the port, +release it, pass it as `--addr 127.0.0.1:`) rather than relying on the +server to report a `:0`-assigned port. + +## Architecture & components + +The extension lives in `editor/vscode/` inside this repo — versioned alongside +the binary, sharing the release cross-compile that produces per-platform +binaries. + +- **`extension.ts` — activation & command.** Registers one command, + `reefdoc.openPreview` ("reefdoc: Open Preview"). On invoke: resolve the + workspace root, pick a free localhost port, start the server, then open the + webview panel. Holds the single-instance reference to the live panel. +- **`server.ts` — binary lifecycle.** Resolves the correct bundled binary for + the current `process.platform` / `process.arch`, spawns + `reefdoc --addr 127.0.0.1: `, polls `GET /` until the + port answers (with a timeout), and exposes `stop()` to kill the child + process. One server process per panel. +- **`panel.ts` — the webview.** Creates a `WebviewPanel` titled "reefdoc" with a + reefdoc icon. Its HTML is a full-bleed ` + +`; +} + +export function createReefdocPanel(url: string): vscode.WebviewPanel { + const panel = vscode.window.createWebviewPanel( + 'reefdoc.preview', + 'reefdoc', + vscode.ViewColumn.Beside, + { enableScripts: true, retainContextWhenHidden: true }, + ); + panel.webview.html = webviewHtml(url); + return panel; +} +``` + +- [ ] **Step 2: Compile to catch type errors** + +Run: `cd editor/vscode && npm run build` +Expected: `tsc` succeeds, `out/panel.js` produced. + +- [ ] **Step 3: Manual verification (deferred until Task 5 wires it)** + +`createReefdocPanel` has no standalone UI trigger yet — it is exercised by the command wired in Task 5. No separate manual step here; verification happens in Task 5, Step 4. + +- [ ] **Step 4: Commit** + +```bash +git add editor/vscode/src/panel.ts +git commit -m "feat: webview panel that frames the reefdoc server" +``` + +--- + +### Task 5: Wire the command — single instance, spawn, frame, cleanup, errors + +**Files:** +- Modify: `editor/vscode/src/extension.ts` + +**Interfaces:** +- Consumes: `resolveBinaryPath`, `findFreePort`, `startServer`, `ReefdocServer` from `server.ts`; `createReefdocPanel` from `panel.ts`. +- Produces: fully-wired `reefdoc.openPreview` command; `activate`/`deactivate` manage a single live `{ panel, server }`. + +This task imports `vscode`; verify manually via the Extension Development Host (Step 4). + +- [ ] **Step 1: Replace `editor/vscode/src/extension.ts` with the wired implementation** + +```ts +import * as vscode from 'vscode'; +import { + resolveBinaryPath, + findFreePort, + startServer, + ReefdocServer, +} from './server'; +import { createReefdocPanel } from './panel'; + +interface Live { + panel: vscode.WebviewPanel; + server: ReefdocServer; +} + +let current: Live | undefined; + +async function openPreview(context: vscode.ExtensionContext): Promise { + if (current) { + current.panel.reveal(vscode.ViewColumn.Beside); + return; + } + + const folder = vscode.workspace.workspaceFolders?.[0]; + if (!folder) { + vscode.window.showErrorMessage('reefdoc: Open a folder to preview.'); + return; + } + const root = folder.uri.fsPath; + + const cfg = vscode.workspace.getConfiguration('reefdoc'); + const host = cfg.get('host', '127.0.0.1'); + const overridePath = cfg.get('binaryPath', ''); + + let binaryPath: string; + try { + binaryPath = overridePath || resolveBinaryPath(context.extensionPath); + } catch (err) { + vscode.window.showErrorMessage(`reefdoc: ${(err as Error).message}`); + return; + } + + let server: ReefdocServer; + try { + const port = await findFreePort(); + server = await startServer({ binaryPath, root, host, port }); + } catch (err) { + vscode.window.showErrorMessage(`reefdoc: failed to start — ${(err as Error).message}`); + return; + } + + const panel = createReefdocPanel(server.url); + current = { panel, server }; + panel.onDidDispose(() => { + server.stop(); + current = undefined; + }); +} + +export function activate(context: vscode.ExtensionContext): void { + const disposable = vscode.commands.registerCommand('reefdoc.openPreview', () => + openPreview(context), + ); + context.subscriptions.push(disposable); +} + +export function deactivate(): void { + current?.server.stop(); + current = undefined; +} +``` + +- [ ] **Step 2: Compile** + +Run: `cd editor/vscode && npm run build` +Expected: `tsc` succeeds with no errors. + +- [ ] **Step 3: Run the full unit/smoke test suite** + +Run: `cd editor/vscode && npm test` +Expected: PASS — Task 2 and Task 3 tests still green (extension.ts is not unit-tested but must not break the build the test loader shares). + +- [ ] **Step 4: Manual verification in the Extension Development Host** + +Because the extension has no bundled binary yet (Task 6), temporarily set `reefdoc.binaryPath` to the repo-root binary for this check: +1. Build the binary: `go build -o "$PWD/reefdoc" .` from the repo root. +2. Open `editor/vscode/` in VS Code, press F5 to launch the Extension Development Host. +3. In the dev-host window, open a folder that contains markdown, set `reefdoc.binaryPath` to the absolute path of the binary from step 1. +4. Run **reefdoc: Open Preview** from the command palette. Confirm: a panel titled "reefdoc" opens beside the editor, the file tree renders, opening a doc works, editing a file on disk live-reloads the panel. +5. Close the panel; confirm the `reefdoc` process is gone (`pgrep reefdoc` returns nothing). Re-run the command; confirm only one panel/process exists. + +Record the result of step 4–5 in the commit message body. + +- [ ] **Step 5: Commit** + +```bash +git add editor/vscode/src/extension.ts +git commit -m "feat: wire reefdoc.openPreview command with lifecycle and errors" +``` + +--- + +### Task 6: Bundle per-platform binaries and package the .vsix + +**Files:** +- Create: `editor/vscode/scripts/bundle-binaries.mjs` +- Create: `editor/vscode/.vscodeignore` +- Create: `editor/vscode/README.md` +- Modify: `editor/vscode/package.json` (add `bundle` and `package` scripts) +- Modify: `editor/vscode/.gitignore` (ignore `bin/`) + +**Interfaces:** +- Consumes: the platform keys used by `resolveBinaryPath` (`darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`, `win32-x64`). +- Produces: `bin/-/reefdoc[.exe]` for each key, and a `reefdoc-0.1.0.vsix` from `npm run package`. + +- [ ] **Step 1: Create the cross-compile script `editor/vscode/scripts/bundle-binaries.mjs`** + +```js +import { execFileSync } from 'node:child_process'; +import { mkdirSync, rmSync } from 'node:fs'; +import * as path from 'node:path'; + +// Maps our bin/ directories to Go GOOS/GOARCH values. +const TARGETS = [ + { key: 'darwin-arm64', goos: 'darwin', goarch: 'arm64' }, + { key: 'darwin-x64', goos: 'darwin', goarch: 'amd64' }, + { key: 'linux-arm64', goos: 'linux', goarch: 'arm64' }, + { key: 'linux-x64', goos: 'linux', goarch: 'amd64' }, + { key: 'win32-x64', goos: 'windows', goarch: 'amd64' }, +]; + +const extDir = path.resolve(import.meta.dirname, '..'); +const repoRoot = path.resolve(extDir, '..', '..'); +const binRoot = path.join(extDir, 'bin'); + +rmSync(binRoot, { recursive: true, force: true }); + +for (const t of TARGETS) { + const outDir = path.join(binRoot, t.key); + mkdirSync(outDir, { recursive: true }); + const exe = t.goos === 'windows' ? 'reefdoc.exe' : 'reefdoc'; + const outFile = path.join(outDir, exe); + console.log(`building ${t.key} -> ${outFile}`); + execFileSync('go', ['build', '-o', outFile, '.'], { + cwd: repoRoot, + env: { ...process.env, GOOS: t.goos, GOARCH: t.goarch, CGO_ENABLED: '0' }, + stdio: 'inherit', + }); +} +console.log('done'); +``` + +- [ ] **Step 2: Create `editor/vscode/.vscodeignore`** + +``` +src/** +scripts/** +tsconfig.json +**/*.test.ts +**/*.map +.gitignore +node_modules/** +``` + +Note: `out/**` and `bin/**` are intentionally NOT ignored — they must ship in the `.vsix`. + +- [ ] **Step 3: Create `editor/vscode/README.md`** + +```markdown +# reefdoc for VS Code / Cursor + +Opens the [reefdoc](https://github.com/exilis/reefdoc) markdown / mermaid / +allium preview inside an editor panel. Bundles the reefdoc binary — no separate +install needed. + +## Usage + +Open a folder, then run **reefdoc: Open Preview** from the command palette. A +panel opens beside your editor showing reefdoc's file tree, tabs, and live +reload. Close the panel to stop the server. + +## Settings + +- `reefdoc.binaryPath` — use a custom binary instead of the bundled one. +- `reefdoc.host` — listen host (default `127.0.0.1`). + +## Build & package + +```bash +npm install +npm run bundle # cross-compiles binaries into bin/ (needs Go on PATH) +npm run build # compiles TypeScript into out/ +npm run package # produces reefdoc-.vsix +``` + +Install the `.vsix` via the Extensions view → "Install from VSIX…". +``` + +- [ ] **Step 4: Add `bundle` and `package` scripts to `editor/vscode/package.json`** + +In the `"scripts"` block, add: + +```json + "bundle": "node scripts/bundle-binaries.mjs", + "package": "npm run bundle && npm run build && vsce package --no-dependencies" +``` + +- [ ] **Step 5: Ignore the generated `bin/` directory in `editor/vscode/.gitignore`** + +Append to `editor/vscode/.gitignore`: + +``` +bin/ +``` + +- [ ] **Step 6: Run the bundle and package end-to-end** + +Run: `cd editor/vscode && npm install && npm run package` +Expected: `bin//reefdoc[.exe]` created for all five targets; `tsc` compiles; `vsce package` emits `reefdoc-0.1.0.vsix`. (Requires Go on PATH for cross-compilation.) + +- [ ] **Step 7: Verify the packaged extension installs and runs** + +1. In VS Code: Extensions view → "…" menu → "Install from VSIX…" → select `reefdoc-0.1.0.vsix`. +2. Open a folder with markdown, run **reefdoc: Open Preview** with NO `reefdoc.binaryPath` set (so the bundled binary is used). +3. Confirm the panel opens and renders, and closing it stops the process. + +- [ ] **Step 8: Commit** + +```bash +git add editor/vscode/scripts/bundle-binaries.mjs editor/vscode/.vscodeignore editor/vscode/README.md editor/vscode/package.json editor/vscode/.gitignore +git commit -m "chore: bundle per-platform binaries and package the extension" +``` + +--- + +## Self-Review + +**Spec coverage:** +- In-editor preview via bundled binary → Tasks 3–6. ✓ +- Single command `reefdoc.openPreview` → Task 1 (contribution) + Task 5 (behaviour). ✓ +- `server.ts` free of `vscode`, unit-testable → Tasks 2–3. ✓ +- Single-instance per window; kill child on panel close / deactivate → Task 5. ✓ +- Per-platform binary resolution + bundling → Task 2 (`resolveBinaryPath`) + Task 6 (bundle script). ✓ +- Config `reefdoc.binaryPath` / `reefdoc.host` → Task 1 (contribution) + Task 5 (consumption). ✓ +- Error notifications (no binary for platform, start failure, no workspace) → Task 5. ✓ +- `--addr` already present, `main.go` untouched → Global Constraints; used in Task 3. ✓ +- Smoke test drives the real binary → Task 3. ✓ +- No marketplace; local `.vsix` → Task 6. ✓ +- Cursor + VS Code from one extension → Global Constraints (no editor-specific code). ✓ + +**Placeholder scan:** No TBD/TODO; every code and command step is concrete. + +**Type consistency:** `resolveBinaryPath`, `findFreePort`, `startServer`, `ReefdocServer`, `createReefdocPanel` names/signatures match across Tasks 2–5. Platform keys in `SUPPORTED` (Task 2) match `TARGETS` keys in the bundle script (Task 6): `darwin-arm64`, `darwin-x64`, `linux-arm64`, `linux-x64`, `win32-x64`. ✓ From 83b647f1564995ea77e8d4825c61ab6c52070a3d Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 15:50:03 +0000 Subject: [PATCH 03/15] feat: scaffold reefdoc VS Code extension with stub command --- editor/vscode/.gitignore | 3 +++ editor/vscode/package.json | 44 ++++++++++++++++++++++++++++++++++ editor/vscode/src/extension.ts | 12 ++++++++++ editor/vscode/tsconfig.json | 15 ++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 editor/vscode/.gitignore create mode 100644 editor/vscode/package.json create mode 100644 editor/vscode/src/extension.ts create mode 100644 editor/vscode/tsconfig.json diff --git a/editor/vscode/.gitignore b/editor/vscode/.gitignore new file mode 100644 index 0000000..d3e15b1 --- /dev/null +++ b/editor/vscode/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +out/ +*.vsix diff --git a/editor/vscode/package.json b/editor/vscode/package.json new file mode 100644 index 0000000..90962df --- /dev/null +++ b/editor/vscode/package.json @@ -0,0 +1,44 @@ +{ + "name": "reefdoc", + "displayName": "reefdoc", + "description": "Preview markdown, mermaid & allium in an editor panel via the reefdoc binary.", + "version": "0.1.0", + "publisher": "exilis", + "private": true, + "license": "MIT", + "engines": { "vscode": "^1.85.0" }, + "categories": ["Other"], + "main": "./out/extension.js", + "contributes": { + "commands": [ + { "command": "reefdoc.openPreview", "title": "reefdoc: Open Preview" } + ], + "configuration": { + "title": "reefdoc", + "properties": { + "reefdoc.binaryPath": { + "type": "string", + "default": "", + "description": "Absolute path to a reefdoc binary to use instead of the bundled one." + }, + "reefdoc.host": { + "type": "string", + "default": "127.0.0.1", + "description": "Host the reefdoc server listens on." + } + } + } + }, + "scripts": { + "build": "tsc -p ./", + "watch": "tsc -watch -p ./", + "test": "tsx --test src/**/*.test.ts" + }, + "devDependencies": { + "@types/node": "^20.11.0", + "@types/vscode": "^1.85.0", + "tsx": "^4.19.0", + "typescript": "^5.4.0", + "@vscode/vsce": "^2.24.0" + } +} diff --git a/editor/vscode/src/extension.ts b/editor/vscode/src/extension.ts new file mode 100644 index 0000000..1e29d96 --- /dev/null +++ b/editor/vscode/src/extension.ts @@ -0,0 +1,12 @@ +import * as vscode from 'vscode'; + +export function activate(context: vscode.ExtensionContext): void { + const disposable = vscode.commands.registerCommand('reefdoc.openPreview', () => { + vscode.window.showInformationMessage('reefdoc: Open Preview (stub)'); + }); + context.subscriptions.push(disposable); +} + +export function deactivate(): void { + // no-op until later tasks +} diff --git a/editor/vscode/tsconfig.json b/editor/vscode/tsconfig.json new file mode 100644 index 0000000..01920f7 --- /dev/null +++ b/editor/vscode/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "ES2022", + "outDir": "out", + "rootDir": "src", + "lib": ["ES2022"], + "sourceMap": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true + }, + "include": ["src/**/*.ts"], + "exclude": ["src/**/*.test.ts"] +} From 6668db32a0bdda479c509eb35b4bce09eaf939d2 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 15:52:34 +0000 Subject: [PATCH 04/15] feat: add binary-path resolution and free-port selection --- editor/vscode/src/server.test.ts | 34 ++++++++++++++++++++++++++++ editor/vscode/src/server.ts | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 editor/vscode/src/server.test.ts create mode 100644 editor/vscode/src/server.ts diff --git a/editor/vscode/src/server.test.ts b/editor/vscode/src/server.test.ts new file mode 100644 index 0000000..80c3466 --- /dev/null +++ b/editor/vscode/src/server.test.ts @@ -0,0 +1,34 @@ +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { resolveBinaryPath, findFreePort } from './server.ts'; + +test('resolveBinaryPath builds a per-platform path', () => { + assert.equal( + resolveBinaryPath('/ext', 'darwin', 'arm64'), + '/ext/bin/darwin-arm64/reefdoc', + ); + assert.equal( + resolveBinaryPath('/ext', 'linux', 'x64'), + '/ext/bin/linux-x64/reefdoc', + ); +}); + +test('resolveBinaryPath adds .exe on windows', () => { + assert.equal( + resolveBinaryPath('/ext', 'win32', 'x64'), + '/ext/bin/win32-x64/reefdoc.exe', + ); +}); + +test('resolveBinaryPath rejects unsupported platform/arch', () => { + assert.throws( + () => resolveBinaryPath('/ext', 'sunos', 'mips'), + /unsupported platform: sunos-mips/, + ); +}); + +test('findFreePort returns a usable port number', async () => { + const port = await findFreePort(); + assert.ok(Number.isInteger(port)); + assert.ok(port > 0 && port < 65536); +}); diff --git a/editor/vscode/src/server.ts b/editor/vscode/src/server.ts new file mode 100644 index 0000000..ce24099 --- /dev/null +++ b/editor/vscode/src/server.ts @@ -0,0 +1,39 @@ +import * as net from 'node:net'; +import * as path from 'node:path'; + +const SUPPORTED = new Set([ + 'darwin-arm64', + 'darwin-x64', + 'linux-arm64', + 'linux-x64', + 'win32-x64', +]); + +export function resolveBinaryPath( + extensionPath: string, + platform: NodeJS.Platform = process.platform, + arch: string = process.arch, +): string { + const key = `${platform}-${arch}`; + if (!SUPPORTED.has(key)) { + throw new Error(`unsupported platform: ${key}`); + } + const exe = platform === 'win32' ? 'reefdoc.exe' : 'reefdoc'; + return path.join(extensionPath, 'bin', key, exe); +} + +export function findFreePort(): Promise { + return new Promise((resolve, reject) => { + const srv = net.createServer(); + srv.on('error', reject); + srv.listen(0, '127.0.0.1', () => { + const addr = srv.address(); + if (addr && typeof addr === 'object') { + const port = addr.port; + srv.close(() => resolve(port)); + } else { + srv.close(() => reject(new Error('could not determine free port'))); + } + }); + }); +} From 53995ae914b3d208d072b1e7b6ec586e7d953888 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 15:56:15 +0000 Subject: [PATCH 05/15] feat: spawn reefdoc binary and wait until it serves --- editor/vscode/src/server.smoke.test.ts | 40 ++++++++++++++ editor/vscode/src/server.ts | 75 ++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 editor/vscode/src/server.smoke.test.ts diff --git a/editor/vscode/src/server.smoke.test.ts b/editor/vscode/src/server.smoke.test.ts new file mode 100644 index 0000000..a10f6fa --- /dev/null +++ b/editor/vscode/src/server.smoke.test.ts @@ -0,0 +1,40 @@ +import { test, before, after } from 'node:test'; +import assert from 'node:assert/strict'; +import { execFileSync } from 'node:child_process'; +import { mkdtempSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import * as path from 'node:path'; +import * as http from 'node:http'; +import { findFreePort, startServer, ReefdocServer } from './server.ts'; + +const repoRoot = path.resolve(import.meta.dirname, '..', '..', '..'); +let binaryPath: string; +let docRoot: string; +let srv: ReefdocServer | undefined; + +before(() => { + const outDir = mkdtempSync(path.join(tmpdir(), 'reefdoc-bin-')); + binaryPath = path.join(outDir, 'reefdoc'); + // Build the real binary from repo root (requires Go on PATH). + execFileSync('go', ['build', '-o', binaryPath, '.'], { cwd: repoRoot }); + docRoot = mkdtempSync(path.join(tmpdir(), 'reefdoc-docs-')); + writeFileSync(path.join(docRoot, 'README.md'), '# hello\n'); +}); + +after(() => { + srv?.stop(); +}); + +test('startServer spawns the binary and serves over HTTP', async () => { + const port = await findFreePort(); + srv = await startServer({ binaryPath, root: docRoot, host: '127.0.0.1', port }); + assert.equal(srv.port, port); + + const status: number = await new Promise((resolve, reject) => { + http.get(srv!.url, (res) => { + res.resume(); + resolve(res.statusCode ?? 0); + }).on('error', reject); + }); + assert.equal(status, 200); +}); diff --git a/editor/vscode/src/server.ts b/editor/vscode/src/server.ts index ce24099..f403615 100644 --- a/editor/vscode/src/server.ts +++ b/editor/vscode/src/server.ts @@ -1,5 +1,7 @@ import * as net from 'node:net'; import * as path from 'node:path'; +import { spawn, ChildProcess } from 'node:child_process'; +import * as http from 'node:http'; const SUPPORTED = new Set([ 'darwin-arm64', @@ -37,3 +39,76 @@ export function findFreePort(): Promise { }); }); } + +export interface ReefdocServer { + port: number; + host: string; + url: string; + stop(): void; +} + +function probe(url: string): Promise { + return new Promise((resolve) => { + const req = http.get(url, (res) => { + res.resume(); + resolve(true); + }); + req.on('error', () => resolve(false)); + req.setTimeout(1000, () => { + req.destroy(); + resolve(false); + }); + }); +} + +function delay(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export async function startServer(opts: { + binaryPath: string; + root: string; + host: string; + port: number; + timeoutMs?: number; +}): Promise { + const { binaryPath, root, host, port } = opts; + const timeoutMs = opts.timeoutMs ?? 10_000; + const url = `http://${host}:${port}`; + + const child: ChildProcess = spawn( + binaryPath, + ['--addr', `${host}:${port}`, root], + { stdio: ['ignore', 'ignore', 'pipe'] }, + ); + + let stderrTail = ''; + child.stderr?.on('data', (chunk: Buffer) => { + stderrTail = (stderrTail + chunk.toString()).slice(-500); + }); + + let exited = false; + child.on('exit', () => { + exited = true; + }); + + const stop = () => { + if (!child.killed) { + child.kill(); + } + }; + + const deadline = Date.now() + timeoutMs; + while (Date.now() < deadline) { + if (exited) { + stop(); + throw new Error(`reefdoc exited before serving: ${stderrTail.trim()}`); + } + if (await probe(url)) { + return { port, host, url, stop }; + } + await delay(150); + } + stop(); + throw new Error(`reefdoc did not become ready within ${timeoutMs}ms`); +} From 3da6b1df0e661a875fd1df60ed48f58dd97cd774 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:01:48 +0000 Subject: [PATCH 06/15] fix: reject on reefdoc spawn error instead of crashing host startServer attached no 'error' listener on the spawned child. When spawn fails to launch the binary (bad/missing binaryPath, ENOENT, permissions), Node emits an 'error' event with no listener, producing an uncaught exception that crashes the host process; 'exit' never fires so the existing early-exit detection never engaged. Add a child.on('error') listener that marks the child as exited and records the error, and surface it in the rejection ("reefdoc failed to start: ..."). Add a regression test asserting startServer rejects (rather than crashing) on a bad binary path. Co-Authored-By: Claude Opus 4.8 (1M context) --- editor/vscode/src/server.test.ts | 9 ++++++++- editor/vscode/src/server.ts | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/editor/vscode/src/server.test.ts b/editor/vscode/src/server.test.ts index 80c3466..c875332 100644 --- a/editor/vscode/src/server.test.ts +++ b/editor/vscode/src/server.test.ts @@ -1,6 +1,6 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { resolveBinaryPath, findFreePort } from './server.ts'; +import { resolveBinaryPath, findFreePort, startServer } from './server.ts'; test('resolveBinaryPath builds a per-platform path', () => { assert.equal( @@ -32,3 +32,10 @@ test('findFreePort returns a usable port number', async () => { assert.ok(Number.isInteger(port)); assert.ok(port > 0 && port < 65536); }); + +test('startServer rejects (does not crash) on a bad binary path', async () => { + const port = await findFreePort(); + await assert.rejects( + startServer({ binaryPath: '/no/such/reefdoc-binary', root: '.', host: '127.0.0.1', port, timeoutMs: 3000 }), + ); +}); diff --git a/editor/vscode/src/server.ts b/editor/vscode/src/server.ts index f403615..f61f3c4 100644 --- a/editor/vscode/src/server.ts +++ b/editor/vscode/src/server.ts @@ -92,6 +92,15 @@ export async function startServer(opts: { exited = true; }); + // If spawn itself fails (bad binaryPath, ENOENT, permissions), Node emits + // an 'error' event and never an 'exit'. Without a listener this becomes an + // uncaught exception that crashes the host process. + let spawnError: Error | undefined; + child.on('error', (err) => { + exited = true; + spawnError = err; + }); + const stop = () => { if (!child.killed) { child.kill(); @@ -102,7 +111,9 @@ export async function startServer(opts: { while (Date.now() < deadline) { if (exited) { stop(); - throw new Error(`reefdoc exited before serving: ${stderrTail.trim()}`); + throw new Error( + `reefdoc failed to start: ${(spawnError?.message ?? stderrTail).trim()}`, + ); } if (await probe(url)) { return { port, host, url, stop }; From f13a9cd3fa3b275ebb3c45514b7e69337198cd15 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:04:16 +0000 Subject: [PATCH 07/15] feat: webview panel that frames the reefdoc server Co-Authored-By: Claude Opus 4.8 (1M context) --- editor/vscode/src/panel.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 editor/vscode/src/panel.ts diff --git a/editor/vscode/src/panel.ts b/editor/vscode/src/panel.ts new file mode 100644 index 0000000..231c58b --- /dev/null +++ b/editor/vscode/src/panel.ts @@ -0,0 +1,34 @@ +import * as vscode from 'vscode'; + +function webviewHtml(url: string): string { + const csp = [ + "default-src 'none'", + 'frame-src http://127.0.0.1:* http://localhost:*', + "style-src 'unsafe-inline'", + ].join('; '); + return ` + + + + + + + + + +`; +} + +export function createReefdocPanel(url: string): vscode.WebviewPanel { + const panel = vscode.window.createWebviewPanel( + 'reefdoc.preview', + 'reefdoc', + vscode.ViewColumn.Beside, + { enableScripts: true, retainContextWhenHidden: true }, + ); + panel.webview.html = webviewHtml(url); + return panel; +} From d799a0a5a121f5049531f4c97e7325e428a51955 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:07:11 +0000 Subject: [PATCH 08/15] feat: wire reefdoc.openPreview command with lifecycle and errors --- editor/vscode/src/extension.ts | 65 +++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/editor/vscode/src/extension.ts b/editor/vscode/src/extension.ts index 1e29d96..2e8270d 100644 --- a/editor/vscode/src/extension.ts +++ b/editor/vscode/src/extension.ts @@ -1,12 +1,69 @@ import * as vscode from 'vscode'; +import { + resolveBinaryPath, + findFreePort, + startServer, + ReefdocServer, +} from './server'; +import { createReefdocPanel } from './panel'; -export function activate(context: vscode.ExtensionContext): void { - const disposable = vscode.commands.registerCommand('reefdoc.openPreview', () => { - vscode.window.showInformationMessage('reefdoc: Open Preview (stub)'); +interface Live { + panel: vscode.WebviewPanel; + server: ReefdocServer; +} + +let current: Live | undefined; + +async function openPreview(context: vscode.ExtensionContext): Promise { + if (current) { + current.panel.reveal(vscode.ViewColumn.Beside); + return; + } + + const folder = vscode.workspace.workspaceFolders?.[0]; + if (!folder) { + vscode.window.showErrorMessage('reefdoc: Open a folder to preview.'); + return; + } + const root = folder.uri.fsPath; + + const cfg = vscode.workspace.getConfiguration('reefdoc'); + const host = cfg.get('host', '127.0.0.1'); + const overridePath = cfg.get('binaryPath', ''); + + let binaryPath: string; + try { + binaryPath = overridePath || resolveBinaryPath(context.extensionPath); + } catch (err) { + vscode.window.showErrorMessage(`reefdoc: ${(err as Error).message}`); + return; + } + + let server: ReefdocServer; + try { + const port = await findFreePort(); + server = await startServer({ binaryPath, root, host, port }); + } catch (err) { + vscode.window.showErrorMessage(`reefdoc: failed to start — ${(err as Error).message}`); + return; + } + + const panel = createReefdocPanel(server.url); + current = { panel, server }; + panel.onDidDispose(() => { + server.stop(); + current = undefined; }); +} + +export function activate(context: vscode.ExtensionContext): void { + const disposable = vscode.commands.registerCommand('reefdoc.openPreview', () => + openPreview(context), + ); context.subscriptions.push(disposable); } export function deactivate(): void { - // no-op until later tasks + current?.server.stop(); + current = undefined; } From 46f3c5b7578e4c2ec1f9227a07e7551c2e789093 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:13:01 +0000 Subject: [PATCH 09/15] fix: guard openPreview against concurrent double-spawn --- editor/vscode/src/extension.ts | 67 +++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/editor/vscode/src/extension.ts b/editor/vscode/src/extension.ts index 2e8270d..823dc66 100644 --- a/editor/vscode/src/extension.ts +++ b/editor/vscode/src/extension.ts @@ -13,47 +13,56 @@ interface Live { } let current: Live | undefined; +let starting = false; async function openPreview(context: vscode.ExtensionContext): Promise { if (current) { current.panel.reveal(vscode.ViewColumn.Beside); return; } - - const folder = vscode.workspace.workspaceFolders?.[0]; - if (!folder) { - vscode.window.showErrorMessage('reefdoc: Open a folder to preview.'); + if (starting) { return; } - const root = folder.uri.fsPath; + starting = true; + try { + const folder = vscode.workspace.workspaceFolders?.[0]; + if (!folder) { + vscode.window.showErrorMessage('reefdoc: Open a folder to preview.'); + return; + } + const root = folder.uri.fsPath; - const cfg = vscode.workspace.getConfiguration('reefdoc'); - const host = cfg.get('host', '127.0.0.1'); - const overridePath = cfg.get('binaryPath', ''); + const cfg = vscode.workspace.getConfiguration('reefdoc'); + const host = cfg.get('host', '127.0.0.1'); + const overridePath = cfg.get('binaryPath', ''); - let binaryPath: string; - try { - binaryPath = overridePath || resolveBinaryPath(context.extensionPath); - } catch (err) { - vscode.window.showErrorMessage(`reefdoc: ${(err as Error).message}`); - return; - } + let binaryPath: string; + try { + binaryPath = overridePath || resolveBinaryPath(context.extensionPath); + } catch (err) { + vscode.window.showErrorMessage(`reefdoc: ${(err as Error).message}`); + return; + } - let server: ReefdocServer; - try { - const port = await findFreePort(); - server = await startServer({ binaryPath, root, host, port }); - } catch (err) { - vscode.window.showErrorMessage(`reefdoc: failed to start — ${(err as Error).message}`); - return; - } + let server: ReefdocServer; + try { + const port = await findFreePort(); + server = await startServer({ binaryPath, root, host, port }); + } catch (err) { + vscode.window.showErrorMessage(`reefdoc: failed to start — ${(err as Error).message}`); + return; + } - const panel = createReefdocPanel(server.url); - current = { panel, server }; - panel.onDidDispose(() => { - server.stop(); - current = undefined; - }); + const panel = createReefdocPanel(server.url); + current = { panel, server }; + context.subscriptions.push(panel); + panel.onDidDispose(() => { + server.stop(); + current = undefined; + }); + } finally { + starting = false; + } } export function activate(context: vscode.ExtensionContext): void { From 82bae5fe3c5229b1555f9b4b458bf3c5890304da Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:17:44 +0000 Subject: [PATCH 10/15] chore: bundle per-platform binaries and package the extension --- editor/vscode/.gitignore | 1 + editor/vscode/.vscodeignore | 7 +++++ editor/vscode/README.md | 27 +++++++++++++++++++ editor/vscode/package.json | 2 ++ editor/vscode/scripts/bundle-binaries.mjs | 32 +++++++++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 editor/vscode/.vscodeignore create mode 100644 editor/vscode/README.md create mode 100644 editor/vscode/scripts/bundle-binaries.mjs diff --git a/editor/vscode/.gitignore b/editor/vscode/.gitignore index d3e15b1..5950a71 100644 --- a/editor/vscode/.gitignore +++ b/editor/vscode/.gitignore @@ -1,3 +1,4 @@ node_modules/ out/ *.vsix +bin/ diff --git a/editor/vscode/.vscodeignore b/editor/vscode/.vscodeignore new file mode 100644 index 0000000..3feec3e --- /dev/null +++ b/editor/vscode/.vscodeignore @@ -0,0 +1,7 @@ +src/** +scripts/** +tsconfig.json +**/*.test.ts +**/*.map +.gitignore +node_modules/** diff --git a/editor/vscode/README.md b/editor/vscode/README.md new file mode 100644 index 0000000..e129a2e --- /dev/null +++ b/editor/vscode/README.md @@ -0,0 +1,27 @@ +# reefdoc for VS Code / Cursor + +Opens the [reefdoc](https://github.com/exilis/reefdoc) markdown / mermaid / +allium preview inside an editor panel. Bundles the reefdoc binary — no separate +install needed. + +## Usage + +Open a folder, then run **reefdoc: Open Preview** from the command palette. A +panel opens beside your editor showing reefdoc's file tree, tabs, and live +reload. Close the panel to stop the server. + +## Settings + +- `reefdoc.binaryPath` — use a custom binary instead of the bundled one. +- `reefdoc.host` — listen host (default `127.0.0.1`). + +## Build & package + +```bash +npm install +npm run bundle # cross-compiles binaries into bin/ (needs Go on PATH) +npm run build # compiles TypeScript into out/ +npm run package # produces reefdoc-.vsix +``` + +Install the `.vsix` via the Extensions view → "Install from VSIX…". diff --git a/editor/vscode/package.json b/editor/vscode/package.json index 90962df..8bc75e3 100644 --- a/editor/vscode/package.json +++ b/editor/vscode/package.json @@ -31,6 +31,8 @@ }, "scripts": { "build": "tsc -p ./", + "bundle": "node scripts/bundle-binaries.mjs", + "package": "npm run bundle && npm run build && vsce package --no-dependencies", "watch": "tsc -watch -p ./", "test": "tsx --test src/**/*.test.ts" }, diff --git a/editor/vscode/scripts/bundle-binaries.mjs b/editor/vscode/scripts/bundle-binaries.mjs new file mode 100644 index 0000000..4e86265 --- /dev/null +++ b/editor/vscode/scripts/bundle-binaries.mjs @@ -0,0 +1,32 @@ +import { execFileSync } from 'node:child_process'; +import { mkdirSync, rmSync } from 'node:fs'; +import * as path from 'node:path'; + +// Maps our bin/ directories to Go GOOS/GOARCH values. +const TARGETS = [ + { key: 'darwin-arm64', goos: 'darwin', goarch: 'arm64' }, + { key: 'darwin-x64', goos: 'darwin', goarch: 'amd64' }, + { key: 'linux-arm64', goos: 'linux', goarch: 'arm64' }, + { key: 'linux-x64', goos: 'linux', goarch: 'amd64' }, + { key: 'win32-x64', goos: 'windows', goarch: 'amd64' }, +]; + +const extDir = path.resolve(import.meta.dirname, '..'); +const repoRoot = path.resolve(extDir, '..', '..'); +const binRoot = path.join(extDir, 'bin'); + +rmSync(binRoot, { recursive: true, force: true }); + +for (const t of TARGETS) { + const outDir = path.join(binRoot, t.key); + mkdirSync(outDir, { recursive: true }); + const exe = t.goos === 'windows' ? 'reefdoc.exe' : 'reefdoc'; + const outFile = path.join(outDir, exe); + console.log(`building ${t.key} -> ${outFile}`); + execFileSync('go', ['build', '-o', outFile, '.'], { + cwd: repoRoot, + env: { ...process.env, GOOS: t.goos, GOARCH: t.goarch, CGO_ENABLED: '0' }, + stdio: 'inherit', + }); +} +console.log('done'); From d2029e706f89691d9e4cad6d728e89fe399eef07 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:25:49 +0000 Subject: [PATCH 11/15] fix: honor reefdoc.host in webview CSP and stop server on panel-create failure Derive the webview CSP frame-src from the actual server URL origin instead of a hardcoded loopback allowlist, so a non-loopback reefdoc.host doesn't get silently blocked. Thread the host into findFreePort so the port probe binds the same interface the server will use. Also stop the spawned server if panel creation throws, so the child process doesn't leak. --- editor/vscode/src/extension.ts | 11 +++++++++-- editor/vscode/src/panel.ts | 3 ++- editor/vscode/src/server.ts | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/editor/vscode/src/extension.ts b/editor/vscode/src/extension.ts index 823dc66..3f5676a 100644 --- a/editor/vscode/src/extension.ts +++ b/editor/vscode/src/extension.ts @@ -46,14 +46,21 @@ async function openPreview(context: vscode.ExtensionContext): Promise { let server: ReefdocServer; try { - const port = await findFreePort(); + const port = await findFreePort(host); server = await startServer({ binaryPath, root, host, port }); } catch (err) { vscode.window.showErrorMessage(`reefdoc: failed to start — ${(err as Error).message}`); return; } - const panel = createReefdocPanel(server.url); + let panel: vscode.WebviewPanel; + try { + panel = createReefdocPanel(server.url); + } catch (err) { + server.stop(); + vscode.window.showErrorMessage(`reefdoc: failed to open panel — ${(err as Error).message}`); + return; + } current = { panel, server }; context.subscriptions.push(panel); panel.onDidDispose(() => { diff --git a/editor/vscode/src/panel.ts b/editor/vscode/src/panel.ts index 231c58b..7b5c6b4 100644 --- a/editor/vscode/src/panel.ts +++ b/editor/vscode/src/panel.ts @@ -1,9 +1,10 @@ import * as vscode from 'vscode'; function webviewHtml(url: string): string { + const origin = new URL(url).origin; const csp = [ "default-src 'none'", - 'frame-src http://127.0.0.1:* http://localhost:*', + `frame-src ${origin}`, "style-src 'unsafe-inline'", ].join('; '); return ` diff --git a/editor/vscode/src/server.ts b/editor/vscode/src/server.ts index f61f3c4..804a954 100644 --- a/editor/vscode/src/server.ts +++ b/editor/vscode/src/server.ts @@ -24,11 +24,11 @@ export function resolveBinaryPath( return path.join(extensionPath, 'bin', key, exe); } -export function findFreePort(): Promise { +export function findFreePort(host: string = '127.0.0.1'): Promise { return new Promise((resolve, reject) => { const srv = net.createServer(); srv.on('error', reject); - srv.listen(0, '127.0.0.1', () => { + srv.listen(0, host, () => { const addr = srv.address(); if (addr && typeof addr === 'object') { const port = addr.port; From 944469ad7104dd613aae8bbc6fe480078b82c4de Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Fri, 10 Jul 2026 16:28:02 +0000 Subject: [PATCH 12/15] chore: commit extension package-lock for reproducible installs Co-Authored-By: Claude Opus 4.8 (1M context) --- editor/vscode/package-lock.json | 2438 +++++++++++++++++++++++++++++++ 1 file changed, 2438 insertions(+) create mode 100644 editor/vscode/package-lock.json diff --git a/editor/vscode/package-lock.json b/editor/vscode/package-lock.json new file mode 100644 index 0000000..a9ff5ad --- /dev/null +++ b/editor/vscode/package-lock.json @@ -0,0 +1,2438 @@ +{ + "name": "reefdoc", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "reefdoc", + "version": "0.1.0", + "license": "MIT", + "devDependencies": { + "@types/node": "^20.11.0", + "@types/vscode": "^1.85.0", + "@vscode/vsce": "^2.24.0", + "tsx": "^4.19.0", + "typescript": "^5.4.0" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "node_modules/@azure/abort-controller": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@azure/core-auth": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.10.1.tgz", + "integrity": "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-util": "^1.13.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-client": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.2.tgz", + "integrity": "sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-rest-pipeline": "^1.22.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.24.0.tgz", + "integrity": "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@azure/core-auth": "^1.10.0", + "@azure/core-tracing": "^1.3.0", + "@azure/core-util": "^1.13.0", + "@azure/logger": "^1.3.0", + "@typespec/ts-http-runtime": "^0.3.4", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-tracing": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.3.1.tgz", + "integrity": "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/core-util": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.13.1.tgz", + "integrity": "sha512-XPArKLzsvl0Hf0CaGyKHUyVgF7oDnhKoP85Xv6M4StF/1AhfORhZudHtOyf2s+FcbuQ9dPRAjB8J2KvRRMUK2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.1.2", + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/identity": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.1.tgz", + "integrity": "sha512-5C/2WD5Vb1lHnZS16dNQRPMjN6oV/Upba+C9nBIs15PmOi6A3ZGs4Lr2u60zw4S04gi+u3cEXiqTVP7M4Pz3kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", + "@azure/core-tracing": "^1.0.0", + "@azure/core-util": "^1.11.0", + "@azure/logger": "^1.0.0", + "@azure/msal-browser": "^5.5.0", + "@azure/msal-node": "^5.1.0", + "open": "^10.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/logger": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.3.0.tgz", + "integrity": "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typespec/ts-http-runtime": "^0.3.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@azure/msal-browser": { + "version": "5.17.0", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.17.0.tgz", + "integrity": "sha512-/yTnW2TCk9Mh+2b/NOaHAN+MryUNxzRTaJD/YtrqOA9bpBWfTXn/iyReRbaLrK/btBo3stEzLyEvuWp2NZ5DuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.11.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-common": { + "version": "16.11.1", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.11.1.tgz", + "integrity": "sha512-yPohvMwWLv1XnaWnIUyKUh8CvcVChCGqG/VluGwfGmaAfrZTNt5yQ+sIs462Sgw6+e2K83KGmMJ860p73ZSCrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@azure/msal-node": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-5.4.0.tgz", + "integrity": "sha512-6EZEParwHRlnSSIikw8FNAnAzwmh71uhveUXdPNFeZFviJ9SH+rwFiurhjzXqICYTrpm3E+dj693QOwfPbJXAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/msal-common": "16.11.1", + "jsonwebtoken": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/vscode": { + "version": "1.125.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.125.0.tgz", + "integrity": "sha512-0icm/ZQAaism87P0ekHqi4/Ju9du+Tm0RUW+y7vqRsxY2cY0FNRX1nAnaW7nT6npPt2tfHiheZ55Zm9UhqonFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typespec/ts-http-runtime": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.6.tgz", + "integrity": "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og==", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@vscode/vsce": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.32.0.tgz", + "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@azure/identity": "^4.1.0", + "@vscode/vsce-sign": "^2.0.0", + "azure-devops-node-api": "^12.5.0", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^6.2.1", + "form-data": "^4.0.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" + }, + "engines": { + "node": ">= 16" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "node_modules/@vscode/vsce-sign": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.9.tgz", + "integrity": "sha512-8IvaRvtFyzUnGGl3f5+1Cnor3LqaUWvhaUjAYO8Y39OUYlOf3cRd+dowuQYLpZcP3uwSG+mURwjEBOSq4SOJ0g==", + "dev": true, + "hasInstallScript": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optionalDependencies": { + "@vscode/vsce-sign-alpine-arm64": "2.0.6", + "@vscode/vsce-sign-alpine-x64": "2.0.6", + "@vscode/vsce-sign-darwin-arm64": "2.0.6", + "@vscode/vsce-sign-darwin-x64": "2.0.6", + "@vscode/vsce-sign-linux-arm": "2.0.6", + "@vscode/vsce-sign-linux-arm64": "2.0.6", + "@vscode/vsce-sign-linux-x64": "2.0.6", + "@vscode/vsce-sign-win32-arm64": "2.0.6", + "@vscode/vsce-sign-win32-x64": "2.0.6" + } + }, + "node_modules/@vscode/vsce-sign-linux-x64": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@vscode/vsce-sign-linux-x64/-/vsce-sign-linux-x64-2.0.6.tgz", + "integrity": "sha512-/olerl1A4sOqdP+hjvJ1sbQjKN07Y3DVnxO4gnbn/ahtQvFrdhUi0G1VsZXDNjfqmXw57DmPi5ASnj/8PGZhAA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "SEE LICENSE IN LICENSE.txt", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/azure-devops-node-api": { + "version": "12.5.0", + "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-12.5.0.tgz", + "integrity": "sha512-R5eFskGvOm3U/GzeAuxRkUsAl0hrAwGgWn6zAd2KrZmrEhWZVqLew4OOupbQlXUuojUzpGtq62SmdhJ06N88og==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.16.tgz", + "integrity": "sha512-IDw48K2/2kRkg9LdJxurvq3lV3aBgq0REY89duEqFRthjlPdXHKMj7EnQOXVckxzgisinf3nHfrcE2FufFLXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cheerio": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.2.0.tgz", + "integrity": "sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "encoding-sniffer": "^0.2.1", + "htmlparser2": "^10.1.0", + "parse5": "^7.3.0", + "parse5-htmlparser2-tree-adapter": "^7.1.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^7.19.0", + "whatwg-mimetype": "^4.0.0" + }, + "engines": { + "node": ">=20.18.1" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cockatiel": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz", + "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/css-select": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", + "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/encoding-sniffer": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz", + "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/htmlparser2": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.1.0.tgz", + "integrity": "sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.2.2", + "entities": "^7.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonwebtoken": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", + "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^4.0.1", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz", + "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/keytar": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/keytar/-/keytar-7.9.0.tgz", + "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", + "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/markdown-it": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", + "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-abi": { + "version": "3.94.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz", + "integrity": "sha512-W5ZNO5KRPB5TkYmGVD9F6YqhsglXJzE6etpbmT+f6EQElhiX/UTG551cnsRGvLG3fyZEg9HwaDmNmj5nwJ4z9g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-semver": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz", + "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } + }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz", + "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.3", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/qs": { + "version": "6.15.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.3.tgz", + "integrity": "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "es-define-property": "^1.0.1", + "side-channel": "^1.1.1" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tar-fs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.0.tgz", + "integrity": "sha512-eUdUIaCr963q2h5u3+QwvYp0+eqPvn+egeqZUm0hwERCqqx1E3kK5ehbGCvqSE5MQAULr67ww0cA3jKc3YkM1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz", + "integrity": "sha512-5UvfMpd1oelmUPRbbaVnq+rHP7ng2cE4qoQkQeAqxRL6PklkxsM0g32/HL0yfvruK6ojQ5x8EE+HF4YV6DtuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz", + "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.18.1" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz", + "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + } + } +} From a8b7fc1487e3f7cd3265db0d94e588bdd5d4f772 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Sun, 12 Jul 2026 10:28:54 +0000 Subject: [PATCH 13/15] docs: add managed agent-policy block to CLAUDE.md Co-Authored-By: Claude Fable 5 --- CLAUDE.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index b083ff9..5c6c4b3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,3 +1,42 @@ + +# Agent Policy (strict) + +These rules bind every AI agent working in this repository. They override +default agent behavior. Project instructions below may add to them but +never loosen them. + +## Git +- Do NOT commit, push, tag, rebase, force-push, or `reset --hard` unless + the user explicitly requests it in the current session. +- Never push directly to `main`/`master`. Never rewrite published history. +- At handoff, report changed files and propose exact git commands instead + of running them. + +## Secrets & data +- Never read, print, copy, or commit secrets: `.env*`, `.secrets/`, + `*.pem`, tokens, API keys, customer data. +- Never send repository contents to external services without explicit + approval. + +## Safety +- No destructive filesystem operations (`rm -rf`, bulk deletes) outside + paths you created this session. +- No dependency upgrades, lockfile regeneration, schema or public-API + changes unless explicitly requested. + +## Scope & quality +- Make the smallest change that satisfies the request; do not refactor + unrelated code. +- Run the repo's tests/linters before claiming work is done; report + failures honestly — never claim success without verification. + +## Tracking & handoff +- If this repo has `.beads/`, track work with `bd` (run `bd prime`); + otherwise do not create markdown TODO files. +- End every session with: what changed, what was verified, and suggested + next commands (including any commit you propose). + + # reefdoc — project instructions ## Release process (follow every time a version ships) From 6df5ed5b5c4a6455ea502427586d49fb4aed1db7 Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Sat, 25 Jul 2026 14:30:57 +0000 Subject: [PATCH 14/15] feat: list .worktrees and disable dir filtering inside them .worktrees was swept up by the blanket dot-directory skip in isNoiseDir, so sibling worktree checkouts were invisible in the tree. Add it to a named dotDirAllowlist alongside .allium/.claude, and switch directory noise filtering off entirely below any .worktrees segment: a worktree is a whole checkout, and hiding its .git/node_modules misrepresents it. The file-level isViewable filter is unchanged. Co-Authored-By: Claude Opus 5 (1M context) --- internal/server/tree.go | 26 +++++++++++++++++++-- internal/server/tree_test.go | 44 ++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/internal/server/tree.go b/internal/server/tree.go index a81d5a0..b030bc0 100644 --- a/internal/server/tree.go +++ b/internal/server/tree.go @@ -37,15 +37,36 @@ func isViewable(name string) bool { return false } +// dotDirAllowlist are hidden directories that do hold documents worth browsing, +// so they survive the blanket dot-directory skip in isNoiseDir. +var dotDirAllowlist = map[string]bool{ + ".allium": true, + ".claude": true, + ".worktrees": true, +} + // isNoiseDir reports whether a directory should be skipped entirely when // listing or searching: dependency/VCS/hidden directories that are never of // interest to a markdown viewer and would otherwise dominate a large tree. func isNoiseDir(name string) bool { - return name == "node_modules" || (strings.HasPrefix(name, ".") && name != ".allium" && name != ".claude") + return name == "node_modules" || (strings.HasPrefix(name, ".") && !dotDirAllowlist[name]) +} + +// isUnfiltered reports whether relDir sits inside a ".worktrees" directory, +// where directory noise filtering is switched off entirely: a worktree is a +// whole checkout, and hiding its ".git"/"node_modules" would misrepresent it. +func isUnfiltered(relDir string) bool { + for _, seg := range strings.Split(filepath.ToSlash(relDir), "/") { + if seg == ".worktrees" { + return true + } + } + return false } // ListDir returns the immediate children (non-noise directories and viewable // files) of the directory at relDir (relative to root; "" means the root). +// Under ".worktrees" every directory is listed — see isUnfiltered. // It does NOT recurse — directory nodes carry no children, so callers list // deeper levels on demand. Directories come first, then files, each group // sorted case-insensitively by name. @@ -59,11 +80,12 @@ func ListDir(root, relDir string) ([]*Node, error) { return nil, err } var nodes []*Node + unfiltered := isUnfiltered(relDir) for _, e := range entries { name := e.Name() childRel := filepath.ToSlash(filepath.Join(relDir, name)) if e.IsDir() { - if isNoiseDir(name) { + if !unfiltered && isNoiseDir(name) { continue } nodes = append(nodes, &Node{Name: name, Path: childRel, IsDir: true}) diff --git a/internal/server/tree_test.go b/internal/server/tree_test.go index dd1a929..e0548cc 100644 --- a/internal/server/tree_test.go +++ b/internal/server/tree_test.go @@ -75,6 +75,7 @@ func TestListDir_AlliumFilesAndDir(t *testing.T) { writeFile(t, filepath.Join(root, "spec.allium")) writeFile(t, filepath.Join(root, ".allium", "schema.allium")) writeFile(t, filepath.Join(root, ".claude", "settings.json")) + writeFile(t, filepath.Join(root, ".worktrees", "feat-x", "README.md")) writeFile(t, filepath.Join(root, ".git", "config")) nodes, err := ListDir(root, "") @@ -85,8 +86,8 @@ func TestListDir_AlliumFilesAndDir(t *testing.T) { for _, n := range nodes { names = append(names, n.Name) } - // .allium and .claude dirs listed, .git hidden; spec.allium listed as file - want := []string{".allium", ".claude", "spec.allium"} + // .allium, .claude and .worktrees dirs listed, .git hidden; spec.allium listed as file + want := []string{".allium", ".claude", ".worktrees", "spec.allium"} if !reflect.DeepEqual(names, want) { t.Fatalf("got %v want %v", names, want) } @@ -101,6 +102,45 @@ func TestListDir_AlliumFilesAndDir(t *testing.T) { } } +func TestListDir_NoDirFilteringInsideWorktrees(t *testing.T) { + root := t.TempDir() + wt := filepath.Join(root, ".worktrees", "feat-x") + writeFile(t, filepath.Join(wt, "README.md")) + writeFile(t, filepath.Join(wt, ".git", "HEAD")) + writeFile(t, filepath.Join(wt, "node_modules", "pkg", "readme.md")) + // same names at the root are still filtered + writeFile(t, filepath.Join(root, ".git", "config")) + writeFile(t, filepath.Join(root, "node_modules", "pkg", "readme.md")) + + names := func(relDir string) []string { + nodes, err := ListDir(root, relDir) + if err != nil { + t.Fatalf("ListDir(%q): %v", relDir, err) + } + var out []string + for _, n := range nodes { + out = append(out, n.Name) + } + return out + } + + if got, want := names(""), []string{".worktrees"}; !reflect.DeepEqual(got, want) { + t.Fatalf("root: got %v want %v", got, want) + } + if got, want := names(".worktrees"), []string{"feat-x"}; !reflect.DeepEqual(got, want) { + t.Fatalf(".worktrees: got %v want %v", got, want) + } + // inside a worktree nothing is skipped, not even .git/node_modules + got, want := names(".worktrees/feat-x"), []string{".git", "node_modules", "README.md"} + if !reflect.DeepEqual(got, want) { + t.Fatalf("worktree: got %v want %v", got, want) + } + // and filtering stays off deeper down + if got, want := names(".worktrees/feat-x/node_modules"), []string{"pkg"}; !reflect.DeepEqual(got, want) { + t.Fatalf("nested: got %v want %v", got, want) + } +} + func TestListDir_ListsBinaryDocs(t *testing.T) { root := t.TempDir() writeFile(t, filepath.Join(root, "slides.pptx")) From 9a864a283413274126bc699ccf8e8202f8e7215d Mon Sep 17 00:00:00 2001 From: Yuki Hayashi Date: Sat, 25 Jul 2026 21:29:44 +0000 Subject: [PATCH 15/15] fix(test): import ReefdocServer as a type in the smoke test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ReefdocServer is an interface, so a value import of it fails under Node's type-stripping loader with "does not provide an export named ReefdocServer" — breaking the Frontend (node --test) CI job. Split it into a separate `import type`, which is erased before the runtime import list is built. Verified: node --test → 111 tests, 111 pass, 0 fail (was 110/111). Co-Authored-By: Claude Opus 5 (1M context) --- editor/vscode/src/server.smoke.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/editor/vscode/src/server.smoke.test.ts b/editor/vscode/src/server.smoke.test.ts index a10f6fa..e2d650d 100644 --- a/editor/vscode/src/server.smoke.test.ts +++ b/editor/vscode/src/server.smoke.test.ts @@ -5,7 +5,10 @@ import { mkdtempSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import * as path from 'node:path'; import * as http from 'node:http'; -import { findFreePort, startServer, ReefdocServer } from './server.ts'; +import { findFreePort, startServer } from './server.ts'; +// ReefdocServer is an interface: `import type` keeps it out of the runtime +// import list, which bare `node --test` type-stripping would otherwise reject. +import type { ReefdocServer } from './server.ts'; const repoRoot = path.resolve(import.meta.dirname, '..', '..', '..'); let binaryPath: string;