From 3ee595a23e4c7be2c2c09a5049c60763a4ad37a1 Mon Sep 17 00:00:00 2001
From: Chris Campbell
Date: Thu, 3 Sep 2026 16:45:18 -0700
Subject: [PATCH 1/4] fix: replace live-server dependency with custom local dev
server
---
packages/docs-builder/bin/cli.js | 22 +-
packages/docs-builder/package.json | 5 +-
packages/docs-builder/src/dev-server.spec.ts | 173 +++++
packages/docs-builder/src/dev-server.ts | 153 ++++
packages/docs-builder/src/gen-html.ts | 7 +-
packages/docs-builder/src/index.ts | 2 +
pnpm-lock.yaml | 722 ++++---------------
7 files changed, 506 insertions(+), 578 deletions(-)
create mode 100644 packages/docs-builder/src/dev-server.spec.ts
create mode 100644 packages/docs-builder/src/dev-server.ts
diff --git a/packages/docs-builder/bin/cli.js b/packages/docs-builder/bin/cli.js
index f56e8ee..beb596d 100755
--- a/packages/docs-builder/bin/cli.js
+++ b/packages/docs-builder/bin/cli.js
@@ -3,10 +3,10 @@
import fs from 'node:fs'
import path from 'node:path'
-import liveServer from '@compodoc/live-server'
import chokidar from 'chokidar'
+import open from 'open'
-import { buildDocs, prepareOutDir, writeOutputFile } from '../dist/index.js'
+import { buildDocs, prepareOutDir, startDevServer, writeOutputFile } from '../dist/index.js'
// TODO: For now assume the current directory is the root; need to make this configurable
const rootDir = process.cwd()
@@ -158,13 +158,19 @@ async function main() {
watch()
// Start local server
- liveServer.start({
- port: 8100,
- // TODO: Make this configurable
- open: '/public/en/latest/index.html',
- watch: 'timestamp',
- logLevel: 0
+ const port = 8100
+ // TODO: Make this configurable
+ const openPath = '/public/en/latest/index.html'
+ await startDevServer({
+ rootDir,
+ port,
+ watchPath: 'timestamp'
})
+
+ // Open the docs in the default browser
+ const url = `http://localhost:${port}${openPath}`
+ console.log(`\nLocal server running at ${url}`)
+ await open(url)
} else {
// Build once
await build({
diff --git a/packages/docs-builder/package.json b/packages/docs-builder/package.json
index bbddb31..35fe9a5 100644
--- a/packages/docs-builder/package.json
+++ b/packages/docs-builder/package.json
@@ -34,7 +34,6 @@
"ci:build": "run-s clean lint prettier:check type-check test:ci build"
},
"dependencies": {
- "@compodoc/live-server": "^1.2.3",
"chokidar": "^5.0.0",
"find-up": "^6.3.0",
"gettext-parser": "^5.0.0",
@@ -43,17 +42,19 @@
"lunr-languages": "^1.9.0",
"mark.js": "^8.11.1",
"marked": "^4.0.10",
+ "open": "^11.0.2",
"postcss": "^8.5.6",
"postcss-rtlcss": "^5.7.1",
"puppeteer": "^24.0.0",
"rev-hash": "^3.0.0",
"semver-compare": "^1.0.0",
+ "sirv": "^3.0.2",
"tinyglobby": "^0.2.15"
},
"devDependencies": {
"@types/lunr": "^2.3.4",
"@types/marked": "^4.0.1",
- "@types/node": "^20.11.20"
+ "@types/node": "^22.20.1"
},
"author": "Climate Interactive",
"license": "MIT",
diff --git a/packages/docs-builder/src/dev-server.spec.ts b/packages/docs-builder/src/dev-server.spec.ts
new file mode 100644
index 0000000..aad4f62
--- /dev/null
+++ b/packages/docs-builder/src/dev-server.spec.ts
@@ -0,0 +1,173 @@
+// Copyright (c) 2026 Climate Interactive / New Venture Fund. All rights reserved.
+
+import { mkdtempSync, rmSync, writeFileSync } from 'fs'
+import { get as httpGet } from 'http'
+import { tmpdir } from 'os'
+import { join as joinPath } from 'path'
+
+import { afterEach, beforeEach, describe, expect, it } from 'vitest'
+
+import type { DevServer } from './dev-server'
+import {
+ devReloadScriptTag,
+ injectDevReloadScript,
+ reloadEventPath,
+ startDevServer
+} from './dev-server'
+
+let rootDir: string
+let server: DevServer | undefined
+
+/** An open connection to the server-sent event stream. */
+interface EventStream {
+ /** The value of the `Content-Type` response header. */
+ contentType: string | undefined
+ /** Read the next chunk of text sent by the server. */
+ next(): Promise
+ /** Close the connection. */
+ close(): void
+}
+
+/**
+ * Open a connection to the given server-sent event stream.
+ *
+ * This uses the `http` module rather than `fetch` so that each stream is given its
+ * own connection; the pool used by `fetch` can otherwise make a second request wait
+ * on the first, which never completes.
+ *
+ * @param url The URL of the event stream.
+ * @returns A promise that is resolved with the open stream once the response headers
+ * have been received.
+ */
+function openEventStream(url: string): Promise {
+ // Hold on to any chunks that arrive before they are requested, so that no event
+ // is missed between calls to `next`
+ const chunks: string[] = []
+ const pending: ((chunk: string) => void)[] = []
+
+ return new Promise((resolve, reject) => {
+ const request = httpGet(url, response => {
+ response.setEncoding('utf8')
+ response.on('data', (chunk: string) => {
+ const waiting = pending.shift()
+ if (waiting) {
+ waiting(chunk)
+ } else {
+ chunks.push(chunk)
+ }
+ })
+ resolve({
+ contentType: response.headers['content-type'],
+ next: () => {
+ const chunk = chunks.shift()
+ if (chunk !== undefined) {
+ return Promise.resolve(chunk)
+ }
+ return new Promise(resolveChunk => pending.push(resolveChunk))
+ },
+ close: () => request.destroy()
+ })
+ })
+ request.on('error', reject)
+ })
+}
+
+beforeEach(() => {
+ rootDir = mkdtempSync(joinPath(tmpdir(), 'docs-builder-dev-server-'))
+ writeFileSync(joinPath(rootDir, 'timestamp'), 'initial')
+})
+
+afterEach(async () => {
+ await server?.close()
+ server = undefined
+ rmSync(rootDir, { recursive: true, force: true })
+})
+
+describe('startDevServer', () => {
+ it('should serve a static file from the root directory', async () => {
+ writeFileSync(joinPath(rootDir, 'index.html'), 'hello')
+ server = await startDevServer({ rootDir, port: 0, watchPath: 'timestamp' })
+
+ const response = await fetch(`http://localhost:${server.port}/index.html`)
+ expect(response.status).toBe(200)
+ expect(response.headers.get('content-type')).toContain('text/html')
+ expect(await response.text()).toBe('hello')
+ })
+
+ it('should return a 404 status for a file that does not exist', async () => {
+ server = await startDevServer({ rootDir, port: 0, watchPath: 'timestamp' })
+
+ const response = await fetch(`http://localhost:${server.port}/nope.html`)
+ expect(response.status).toBe(404)
+ })
+
+ it('should send a reload event when the watched file is changed', async () => {
+ server = await startDevServer({ rootDir, port: 0, watchPath: 'timestamp' })
+
+ const stream = await openEventStream(`http://localhost:${server.port}${reloadEventPath}`)
+ expect(stream.contentType).toContain('text/event-stream')
+
+ // The server sends a comment as soon as the stream is opened, so that the
+ // browser treats the connection as established
+ expect(await stream.next()).toContain(': connected')
+
+ // Simulate the builder finishing a build
+ writeFileSync(joinPath(rootDir, 'timestamp'), 'updated')
+ expect(await stream.next()).toContain('data: reload')
+
+ stream.close()
+ })
+
+ it('should send a reload event to each connected client', async () => {
+ server = await startDevServer({ rootDir, port: 0, watchPath: 'timestamp' })
+
+ const url = `http://localhost:${server.port}${reloadEventPath}`
+ const streams = [await openEventStream(url), await openEventStream(url)]
+ for (const stream of streams) {
+ expect(await stream.next()).toContain(': connected')
+ }
+
+ writeFileSync(joinPath(rootDir, 'timestamp'), 'updated')
+ for (const stream of streams) {
+ expect(await stream.next()).toContain('data: reload')
+ stream.close()
+ }
+ })
+
+ it('should stop accepting connections after being closed', async () => {
+ server = await startDevServer({ rootDir, port: 0, watchPath: 'timestamp' })
+ const port = server.port
+
+ await server.close()
+ server = undefined
+
+ await expect(fetch(`http://localhost:${port}/index.html`)).rejects.toThrow()
+ })
+})
+
+describe('devReloadScriptTag', () => {
+ it('should connect to the path that the server listens on', () => {
+ expect(devReloadScriptTag).toContain(`new EventSource('${reloadEventPath}')`)
+ expect(devReloadScriptTag).toContain('location.reload()')
+ })
+})
+
+describe('injectDevReloadScript', () => {
+ it('should insert the script before the closing body tag', () => {
+ const html = '\n\nhello
\n\n\n'
+ const result = injectDevReloadScript(html)
+ expect(result).toBe(`\n\nhello
\n${devReloadScriptTag}\n\n\n`)
+ })
+
+ it('should insert the script before the last closing body tag', () => {
+ const html = '</body>
'
+ const result = injectDevReloadScript(html)
+ expect(result.indexOf(devReloadScriptTag)).toBeGreaterThan(result.indexOf(''))
+ expect(result.lastIndexOf('
')).toBeGreaterThan(result.indexOf(devReloadScriptTag))
+ })
+
+ it('should append the script if there is no closing body tag', () => {
+ const html = '
fragment
'
+ expect(injectDevReloadScript(html)).toBe(`
fragment
\n${devReloadScriptTag}\n`)
+ })
+})
diff --git a/packages/docs-builder/src/dev-server.ts b/packages/docs-builder/src/dev-server.ts
new file mode 100644
index 0000000..0735153
--- /dev/null
+++ b/packages/docs-builder/src/dev-server.ts
@@ -0,0 +1,153 @@
+// Copyright (c) 2026 Climate Interactive / New Venture Fund
+
+import type { Server, ServerResponse } from 'http'
+import { createServer } from 'http'
+import { resolve as resolvePath } from 'path'
+
+import chokidar from 'chokidar'
+import sirv from 'sirv'
+
+/**
+ * The path that the injected client script connects to in order to listen for
+ * reload events.
+ */
+export const reloadEventPath = '/__docs_builder_reload'
+
+/**
+ * The script that is added to the `
` of each generated page when building in
+ * development mode.
+ *
+ * The browser reconnects to an `EventSource` automatically if the connection is
+ * dropped, so the page will reattach on its own if the dev server is restarted.
+ */
+export const devReloadScriptTag = ``
+
+/**
+ * Add the reload script to the given HTML page.
+ *
+ * The script is inserted just before the closing `body` tag, which is where a page
+ * expects trailing scripts to appear. If the content does not contain a closing
+ * `body` tag, the script is appended instead.
+ *
+ * @param html The HTML content of the page.
+ * @returns The HTML content with the reload script included.
+ */
+export function injectDevReloadScript(html: string): string {
+ const closingTag = ''
+ const index = html.lastIndexOf(closingTag)
+ if (index < 0) {
+ return `${html}\n${devReloadScriptTag}\n`
+ }
+ return `${html.slice(0, index)}${devReloadScriptTag}\n${html.slice(index)}`
+}
+
+/** The options for starting the local development server. */
+export interface DevServerOptions {
+ /** The absolute path of the directory that is served. */
+ rootDir: string
+ /** The port to listen on. Use zero to listen on an arbitrary free port. */
+ port: number
+ /** The path (relative to `rootDir`) of the file that triggers a reload when changed. */
+ watchPath: string
+}
+
+/** A running local development server. */
+export interface DevServer {
+ /** The port that the server is listening on. */
+ port: number
+
+ /**
+ * Stop watching for changes and close the server.
+ *
+ * @returns A promise that is resolved once the server has been closed.
+ */
+ close(): Promise
+}
+
+/**
+ * Start a local development server that serves the given directory and reloads
+ * connected browser tabs whenever the watched file is changed.
+ *
+ * The builder writes the watched file once all output files are in place, so a
+ * reload is never triggered midway through a build.
+ *
+ * Reload notifications are delivered using server-sent events, which are supported
+ * natively by the browser, so no WebSocket library is needed.
+ *
+ * @param options The dev server options.
+ * @returns A promise that is resolved with the running server once it is listening
+ * and watching for changes.
+ */
+export function startDevServer(options: DevServerOptions): Promise {
+ // Keep track of the connected browser tabs so that each one can be notified
+ // when a build finishes
+ const clients: Set = new Set()
+
+ const serve = sirv(options.rootDir, { dev: true, etag: true })
+
+ const server: Server = createServer((req, res) => {
+ if (req.url === reloadEventPath) {
+ res.writeHead(200, {
+ 'Content-Type': 'text/event-stream',
+ 'Cache-Control': 'no-cache',
+ Connection: 'keep-alive'
+ })
+ // Send a comment as soon as the stream is opened so that the browser
+ // treats the connection as established
+ res.write(': connected\n\n')
+ clients.add(res)
+ req.on('close', () => {
+ clients.delete(res)
+ })
+ return
+ }
+ serve(req, res)
+ })
+
+ // Watch the single file that the builder writes at the end of each build
+ const watcher = chokidar.watch(resolvePath(options.rootDir, options.watchPath), {
+ ignoreInitial: true
+ })
+ watcher.on('change', () => {
+ for (const client of clients) {
+ client.write('data: reload\n\n')
+ }
+ })
+
+ async function close(): Promise {
+ await watcher.close()
+ // End the open event streams, otherwise the server will not finish closing
+ for (const client of clients) {
+ client.end()
+ }
+ clients.clear()
+ const closed = new Promise((resolve, reject) => {
+ server.close(err => (err ? reject(err) : resolve()))
+ })
+ // Drop any idle keep-alive connections, which would otherwise hold the
+ // server open until the browser times them out
+ server.closeAllConnections()
+ await closed
+ }
+
+ // Wait for the server and the watcher to be ready before resolving, so that a
+ // build that finishes immediately after startup is not missed
+ return new Promise((resolve, reject) => {
+ server.on('error', reject)
+ watcher.on('error', reject)
+ watcher.on('ready', () => {
+ server.listen(options.port, () => {
+ const address = server.address()
+ const port = typeof address === 'object' && address !== null ? address.port : options.port
+ resolve({ port, close })
+ })
+ })
+ })
+}
diff --git a/packages/docs-builder/src/gen-html.ts b/packages/docs-builder/src/gen-html.ts
index 8a3ca43..b6d2e70 100644
--- a/packages/docs-builder/src/gen-html.ts
+++ b/packages/docs-builder/src/gen-html.ts
@@ -6,6 +6,7 @@ import { marked } from 'marked'
import type { Assets } from './assets'
import type { Context } from './context'
+import { injectDevReloadScript } from './dev-server'
import { readTextFile, writeOutputFile } from './fs'
import { plainTextFromTokens } from './parse'
import type { TocPageItem, TocSection } from './toc'
@@ -411,9 +412,13 @@ export function writeHtmlFile(
}
})
+ // In development mode, add the script that reloads the page when the local dev
+ // server sees that a build has finished
+ const finalHtml = context.config.mode === 'development' ? injectDevReloadScript(html) : html
+
// Write the HTML file
const htmlPath = resolvePath(context.outDir, htmlPage.relPath)
- writeOutputFile(htmlPath, html)
+ writeOutputFile(htmlPath, finalHtml)
}
export function writeCompleteHtmlFile(
diff --git a/packages/docs-builder/src/index.ts b/packages/docs-builder/src/index.ts
index e7e9484..d210de4 100644
--- a/packages/docs-builder/src/index.ts
+++ b/packages/docs-builder/src/index.ts
@@ -3,4 +3,6 @@
export type { BuildOptions } from './build'
export { buildDocs } from './build'
export type { BuildMode } from './config'
+export type { DevServer, DevServerOptions } from './dev-server'
+export { startDevServer } from './dev-server'
export { prepareOutDir, writeOutputFile } from './fs'
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 58e5edf..00f9bf3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -40,7 +40,7 @@ importers:
version: 5.3.3
vitest:
specifier: ^4.0.17
- version: 4.0.17
+ version: 4.0.17(@types/node@22.20.1)
examples/sample-docs:
devDependencies:
@@ -50,9 +50,6 @@ importers:
packages/docs-builder:
dependencies:
- '@compodoc/live-server':
- specifier: ^1.2.3
- version: 1.2.3
chokidar:
specifier: ^5.0.0
version: 5.0.0
@@ -77,6 +74,9 @@ importers:
marked:
specifier: ^4.0.10
version: 4.0.18
+ open:
+ specifier: ^11.0.2
+ version: 11.0.2
postcss:
specifier: ^8.5.6
version: 8.5.6
@@ -92,6 +92,9 @@ importers:
semver-compare:
specifier: ^1.0.0
version: 1.0.0
+ sirv:
+ specifier: ^3.0.2
+ version: 3.0.2
tinyglobby:
specifier: ^0.2.15
version: 0.2.15
@@ -103,8 +106,8 @@ importers:
specifier: ^4.0.1
version: 4.0.3
'@types/node':
- specifier: ^20.11.20
- version: 20.11.20
+ specifier: ^22.20.1
+ version: 22.20.1
packages:
@@ -120,11 +123,6 @@ packages:
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'}
- '@compodoc/live-server@1.2.3':
- resolution: {integrity: sha512-hDmntVCyjjaxuJzPzBx68orNZ7TW4BtHWMnXlIVn5dqhK7vuFF/11hspO1cMmc+2QTYgqde1TBcb3127S7Zrow==}
- engines: {node: '>=0.10.0'}
- hasBin: true
-
'@esbuild/aix-ppc64@0.27.2':
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
engines: {node: '>=18'}
@@ -351,6 +349,9 @@ packages:
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
engines: {node: '>=14'}
+ '@polka/url@1.0.0-next.29':
+ resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
+
'@puppeteer/browsers@2.11.1':
resolution: {integrity: sha512-YmhAxs7XPuxN0j7LJloHpfD1ylhDuFmmwMvfy/+6nBSrETT2ycL53LrhgPtR+f+GcPSybQVuQ5inWWu5MrWCpA==}
engines: {node: '>=18'}
@@ -390,66 +391,79 @@ packages:
resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==}
cpu: [arm]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.55.1':
resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==}
cpu: [arm]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.55.1':
resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==}
cpu: [arm64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.55.1':
resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==}
cpu: [arm64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.55.1':
resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==}
cpu: [loong64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.55.1':
resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==}
cpu: [loong64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.55.1':
resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==}
cpu: [ppc64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.55.1':
resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==}
cpu: [ppc64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.55.1':
resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==}
cpu: [riscv64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.55.1':
resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==}
cpu: [riscv64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.55.1':
resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==}
cpu: [s390x]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.55.1':
resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==}
cpu: [x64]
os: [linux]
+ libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.55.1':
resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==}
cpu: [x64]
os: [linux]
+ libc: [musl]
'@rollup/rollup-openbsd-x64@4.55.1':
resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==}
@@ -511,6 +525,9 @@ packages:
'@types/node@20.11.20':
resolution: {integrity: sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==}
+ '@types/node@22.20.1':
+ resolution: {integrity: sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==}
+
'@types/semver@7.5.7':
resolution: {integrity: sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg==}
@@ -607,10 +624,6 @@ packages:
'@vitest/utils@4.0.17':
resolution: {integrity: sha512-RG6iy+IzQpa9SB8HAFHJ9Y+pTzI+h8553MrciN9eC6TFBErqrQaTas4vG+MVj8S4uKk8uTT2p0vgZPnTdxd96w==}
- accepts@1.3.8:
- resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
- engines: {node: '>= 0.6'}
-
acorn-jsx@5.3.2:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
@@ -656,18 +669,6 @@ packages:
any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
- anymatch@3.1.2:
- resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
- engines: {node: '>= 8'}
-
- apache-crypt@1.2.5:
- resolution: {integrity: sha512-ICnYQH+DFVmw+S4Q0QY2XRXD8Ne8ewh8HgbuFH4K7022zCxgHM0Hz1xkRnUlEfAXNbwp1Cnhbedu60USIfDxvg==}
- engines: {node: '>=8'}
-
- apache-md5@1.1.7:
- resolution: {integrity: sha512-JtHjzZmJxtzfTSjsCyHgPR155HBe5WGyUyHTaEkfy46qhwCFKx1Epm6nAxgUG3WfUZP1dWhGqj9Z2NOBeZ+uBw==}
- engines: {node: '>=8'}
-
argparse@1.0.10:
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
@@ -735,24 +736,10 @@ packages:
bare-url@2.3.2:
resolution: {integrity: sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==}
- basic-auth@2.0.1:
- resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==}
- engines: {node: '>= 0.8'}
-
basic-ftp@5.1.0:
resolution: {integrity: sha512-RkaJzeJKDbaDWTIPiJwubyljaEPwpVWkm9Rt5h9Nd6h7tEXTJ3VB4qxdZBioV7JO5yLUaOKwz7vDOzlncUsegw==}
engines: {node: '>=10.0.0'}
- batch@0.6.1:
- resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==}
-
- bcryptjs@2.4.3:
- resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==}
-
- binary-extensions@2.2.0:
- resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
- engines: {node: '>=8'}
-
brace-expansion@1.1.11:
resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
@@ -766,6 +753,10 @@ packages:
buffer-crc32@0.2.13:
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+ bundle-name@4.1.0:
+ resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==}
+ engines: {node: '>=18'}
+
bundle-require@5.1.0:
resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
@@ -795,10 +786,6 @@ packages:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
- chokidar@3.5.3:
- resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
- engines: {node: '>= 8.10.0'}
-
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
@@ -829,10 +816,6 @@ packages:
color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
- colors@1.4.0:
- resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==}
- engines: {node: '>=0.1.90'}
-
commander@4.1.1:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
@@ -843,10 +826,6 @@ packages:
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
- connect@3.7.0:
- resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==}
- engines: {node: '>= 0.10.0'}
-
consola@3.4.2:
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
engines: {node: ^14.18.0 || >=16.10.0}
@@ -855,10 +834,6 @@ packages:
resolution: {integrity: sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==}
engines: {node: '>= 0.6'}
- cors@2.8.5:
- resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
- engines: {node: '>= 0.10'}
-
cosmiconfig@9.0.0:
resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==}
engines: {node: '>=14'}
@@ -880,14 +855,6 @@ packages:
resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==}
engines: {node: '>= 14'}
- debug@2.6.9:
- resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
- peerDependencies:
- supports-color: '*'
- peerDependenciesMeta:
- supports-color:
- optional: true
-
debug@4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -918,9 +885,17 @@ packages:
deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
- define-lazy-prop@2.0.0:
- resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
- engines: {node: '>=8'}
+ default-browser-id@5.0.1:
+ resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==}
+ engines: {node: '>=18'}
+
+ default-browser@5.5.1:
+ resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==}
+ engines: {node: '>=18'}
+
+ define-lazy-prop@3.0.0:
+ resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==}
+ engines: {node: '>=12'}
define-properties@1.1.4:
resolution: {integrity: sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==}
@@ -930,14 +905,6 @@ packages:
resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==}
engines: {node: '>= 14'}
- depd@1.1.2:
- resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==}
- engines: {node: '>= 0.6'}
-
- depd@2.0.0:
- resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
- engines: {node: '>= 0.8'}
-
devtools-protocol@0.0.1534754:
resolution: {integrity: sha512-26T91cV5dbOYnXdJi5qQHoTtUoNEqwkHcAyu/IKtjIAxiEqPMrDiRkDOPWVsGfNZGmlQVHQbZRSjD8sxagWVsQ==}
@@ -949,29 +916,15 @@ packages:
resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
engines: {node: '>=6.0.0'}
- duplexer@0.1.2:
- resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
-
eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
- ee-first@1.1.1:
- resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
-
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
- encodeurl@1.0.2:
- resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
- engines: {node: '>= 0.8'}
-
- encodeurl@2.0.0:
- resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
- engines: {node: '>= 0.8'}
-
encoding@0.1.13:
resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==}
@@ -1005,9 +958,6 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
- escape-html@1.0.3:
- resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
-
escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
@@ -1074,13 +1024,6 @@ packages:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'}
- etag@1.8.1:
- resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
- engines: {node: '>= 0.6'}
-
- event-stream@4.0.1:
- resolution: {integrity: sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==}
-
events-universal@1.0.1:
resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==}
@@ -1116,10 +1059,6 @@ packages:
fastq@1.13.0:
resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==}
- faye-websocket@0.11.4:
- resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
- engines: {node: '>=0.8.0'}
-
fd-slicer@1.1.0:
resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
@@ -1140,10 +1079,6 @@ packages:
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
engines: {node: '>=8'}
- finalhandler@1.1.2:
- resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==}
- engines: {node: '>= 0.8'}
-
find-up@5.0.0:
resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
engines: {node: '>=10'}
@@ -1166,13 +1101,6 @@ packages:
resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==}
engines: {node: '>=14'}
- fresh@2.0.0:
- resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
- engines: {node: '>= 0.8'}
-
- from@0.1.7:
- resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
-
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@@ -1276,25 +1204,6 @@ packages:
hosted-git-info@2.8.9:
resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
- http-auth-connect@1.0.5:
- resolution: {integrity: sha512-zykAOKpVAXyzhOLm6+xyB/RtRcfN3uDfH4Al73DIfeSb6B7nr0WToLI6UyyM6ohtcLmbBPksWXzVbEDStz8ObQ==}
- engines: {node: '>=8'}
-
- http-auth@4.1.9:
- resolution: {integrity: sha512-kvPYxNGc9EKGTXvOMnTBQw2RZfuiSihK/mLw/a4pbtRueTE45S55Lw/3k5CktIf7Ak0veMKEIteDj4YkNmCzmQ==}
- engines: {node: '>=8'}
-
- http-errors@1.6.3:
- resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==}
- engines: {node: '>= 0.6'}
-
- http-errors@2.0.1:
- resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==}
- engines: {node: '>= 0.8'}
-
- http-parser-js@0.5.8:
- resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==}
-
http-proxy-agent@7.0.2:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
@@ -1331,9 +1240,6 @@ packages:
inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
- inherits@2.0.3:
- resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==}
-
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
@@ -1351,10 +1257,6 @@ packages:
is-bigint@1.0.4:
resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==}
- is-binary-path@2.1.0:
- resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
- engines: {node: '>=8'}
-
is-boolean-object@1.1.2:
resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
engines: {node: '>= 0.4'}
@@ -1370,9 +1272,9 @@ packages:
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
engines: {node: '>= 0.4'}
- is-docker@2.2.1:
- resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
- engines: {node: '>=8'}
+ is-docker@3.0.0:
+ resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
hasBin: true
is-extendable@0.1.1:
@@ -1391,6 +1293,15 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
+ is-in-ssh@1.0.0:
+ resolution: {integrity: sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==}
+ engines: {node: '>=20'}
+
+ is-inside-container@1.0.0:
+ resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==}
+ engines: {node: '>=14.16'}
+ hasBin: true
+
is-negative-zero@2.0.2:
resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==}
engines: {node: '>= 0.4'}
@@ -1425,9 +1336,9 @@ packages:
is-weakref@1.0.2:
resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==}
- is-wsl@2.2.0:
- resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==}
- engines: {node: '>=8'}
+ is-wsl@3.1.1:
+ resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==}
+ engines: {node: '>=16'}
isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
@@ -1518,9 +1429,6 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
- map-stream@0.0.7:
- resolution: {integrity: sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==}
-
mark.js@8.11.1:
resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==}
@@ -1541,22 +1449,6 @@ packages:
resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
engines: {node: '>=8.6'}
- mime-db@1.52.0:
- resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
- engines: {node: '>= 0.6'}
-
- mime-db@1.54.0:
- resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
- engines: {node: '>= 0.6'}
-
- mime-types@2.1.35:
- resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
- engines: {node: '>= 0.6'}
-
- mime-types@3.0.2:
- resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==}
- engines: {node: '>=18'}
-
minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@@ -1574,12 +1466,9 @@ packages:
mlly@1.8.0:
resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==}
- morgan@1.10.0:
- resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==}
- engines: {node: '>= 0.8.0'}
-
- ms@2.0.0:
- resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+ mrmime@2.0.1:
+ resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
+ engines: {node: '>=10'}
ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
@@ -1598,10 +1487,6 @@ packages:
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
- negotiator@0.6.3:
- resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==}
- engines: {node: '>= 0.6'}
-
netmask@2.0.2:
resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==}
engines: {node: '>= 0.4.0'}
@@ -1612,10 +1497,6 @@ packages:
normalize-package-data@2.5.0:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
- normalize-path@3.0.0:
- resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
- engines: {node: '>=0.10.0'}
-
npm-run-all@4.1.5:
resolution: {integrity: sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==}
engines: {node: '>= 4'}
@@ -1639,24 +1520,12 @@ packages:
obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
- on-finished@2.3.0:
- resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==}
- engines: {node: '>= 0.8'}
-
- on-finished@2.4.1:
- resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
- engines: {node: '>= 0.8'}
-
- on-headers@1.0.2:
- resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
- engines: {node: '>= 0.8'}
-
once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
- open@8.4.0:
- resolution: {integrity: sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==}
- engines: {node: '>=12'}
+ open@11.0.2:
+ resolution: {integrity: sha512-RWqF+pBSkqecEvCKOn8QYhaNdRMJDZRIrlS/7rTDdLHaPcfXGCZ/h8zb413NfvdeAV0MR7T1yJcA34/q+CSm1Q==}
+ engines: {node: '>=20'}
optionator@0.9.3:
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
@@ -1698,10 +1567,6 @@ packages:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
- parseurl@1.3.3:
- resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
- engines: {node: '>= 0.8'}
-
path-exists@4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
@@ -1740,9 +1605,6 @@ packages:
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
- pause-stream@0.0.11:
- resolution: {integrity: sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=}
-
pend@1.2.0:
resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
@@ -1804,6 +1666,14 @@ packages:
resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
engines: {node: ^10 || ^12 || >=14}
+ powershell-utils@0.1.0:
+ resolution: {integrity: sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==}
+ engines: {node: '>=20'}
+
+ powershell-utils@0.2.1:
+ resolution: {integrity: sha512-C+y9x90UElAddDZmV4qOx9W53B61PO7cIqWz2dQsWlwswuq4mr8NEwytdGKboYbQlGZ3awrkTeNvcZiZNHnQ8A==}
+ engines: {node: '>=20'}
+
prelude-ls@1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
engines: {node: '>= 0.8.0'}
@@ -1824,10 +1694,6 @@ packages:
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
- proxy-middleware@0.15.0:
- resolution: {integrity: sha512-EGCG8SeoIRVMhsqHQUdDigB2i7qU7fCsWASwn54+nPutYO8n4q6EiwMzyfWlC+dzRFExP+kvcnDFdBDHoZBU7Q==}
- engines: {node: '>=0.8.0'}
-
pump@3.0.0:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
@@ -1847,10 +1713,6 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
- range-parser@1.2.1:
- resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
- engines: {node: '>= 0.6'}
-
read-pkg@3.0.0:
resolution: {integrity: sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==}
engines: {node: '>=4'}
@@ -1859,10 +1721,6 @@ packages:
resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
engines: {node: '>= 6'}
- readdirp@3.6.0:
- resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
- engines: {node: '>=8.10.0'}
-
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
@@ -1913,12 +1771,13 @@ packages:
engines: {node: '>=12.0.0'}
hasBin: true
+ run-applescript@7.1.0:
+ resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==}
+ engines: {node: '>=18'}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
- safe-buffer@5.1.2:
- resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
-
safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@@ -1946,20 +1805,6 @@ packages:
engines: {node: '>=10'}
hasBin: true
- send@1.2.1:
- resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==}
- engines: {node: '>= 18'}
-
- serve-index@1.9.1:
- resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==}
- engines: {node: '>= 0.8.0'}
-
- setprototypeof@1.1.0:
- resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==}
-
- setprototypeof@1.2.0:
- resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
-
shebang-command@1.2.0:
resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==}
engines: {node: '>=0.10.0'}
@@ -1989,6 +1834,10 @@ packages:
resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==}
engines: {node: '>=14'}
+ sirv@3.0.2:
+ resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==}
+ engines: {node: '>=18'}
+
slash@3.0.0:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
@@ -2029,29 +1878,15 @@ packages:
spdx-license-ids@3.0.11:
resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==}
- split@1.0.1:
- resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==}
-
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
- statuses@1.5.0:
- resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==}
- engines: {node: '>= 0.6'}
-
- statuses@2.0.2:
- resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
- engines: {node: '>= 0.8'}
-
std-env@3.10.0:
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
- stream-combiner@0.2.2:
- resolution: {integrity: sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==}
-
streamx@2.23.0:
resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==}
@@ -2132,9 +1967,6 @@ packages:
thenify@3.3.1:
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
- through@2.3.8:
- resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
-
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@@ -2157,9 +1989,9 @@ packages:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
- toidentifier@1.0.1:
- resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
- engines: {node: '>=0.6'}
+ totalist@3.0.1:
+ resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
+ engines: {node: '>=6'}
tree-kill@1.2.2:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
@@ -2221,12 +2053,8 @@ packages:
undici-types@5.26.5:
resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
- unix-crypt-td-js@1.1.4:
- resolution: {integrity: sha512-8rMeVYWSIyccIJscb9NdCfZKSRBKYTeVnwmiRYT2ulE3qd1RaDQ0xQDP+rI3ccIWbhu/zuo5cgN8z73belNZgw==}
-
- unpipe@1.0.0:
- resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
- engines: {node: '>= 0.8'}
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
@@ -2234,21 +2062,9 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
- utils-merge@1.0.1:
- resolution: {integrity: sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=}
- engines: {node: '>= 0.4.0'}
-
- uuid@8.3.2:
- resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
- hasBin: true
-
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
- vary@1.1.2:
- resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
- engines: {node: '>= 0.8'}
-
vite@7.3.1:
resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -2326,14 +2142,6 @@ packages:
webdriver-bidi-protocol@0.3.10:
resolution: {integrity: sha512-5LAE43jAVLOhB/QqX4bwSiv0Hg1HBfMmOuwBSXHdvg4GMGu9Y0lIq7p4R/yySu6w74WmaR4GM4H9t2IwLW7hgw==}
- websocket-driver@0.7.4:
- resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==}
- engines: {node: '>=0.8.0'}
-
- websocket-extensions@0.1.4:
- resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==}
- engines: {node: '>=0.8.0'}
-
which-boxed-primitive@1.0.2:
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
@@ -2374,6 +2182,10 @@ packages:
utf-8-validate:
optional: true
+ wsl-utils@1.0.0:
+ resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==}
+ engines: {node: '>=20'}
+
y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
@@ -2415,25 +2227,6 @@ snapshots:
'@babel/helper-validator-identifier@7.28.5': {}
- '@compodoc/live-server@1.2.3':
- dependencies:
- chokidar: 3.5.3
- colors: 1.4.0
- connect: 3.7.0
- cors: 2.8.5
- event-stream: 4.0.1
- faye-websocket: 0.11.4
- http-auth: 4.1.9
- http-auth-connect: 1.0.5
- morgan: 1.10.0
- object-assign: 4.1.1
- open: 8.4.0
- proxy-middleware: 0.15.0
- send: 1.2.1
- serve-index: 1.9.1
- transitivePeerDependencies:
- - supports-color
-
'@esbuild/aix-ppc64@0.27.2':
optional: true
@@ -2590,6 +2383,8 @@ snapshots:
'@pkgjs/parseargs@0.11.0':
optional: true
+ '@polka/url@1.0.0-next.29': {}
+
'@puppeteer/browsers@2.11.1':
dependencies:
debug: 4.4.3
@@ -2704,6 +2499,11 @@ snapshots:
'@types/node@20.11.20':
dependencies:
undici-types: 5.26.5
+ optional: true
+
+ '@types/node@22.20.1':
+ dependencies:
+ undici-types: 6.21.0
'@types/semver@7.5.7': {}
@@ -2809,13 +2609,13 @@ snapshots:
chai: 6.2.2
tinyrainbow: 3.0.3
- '@vitest/mocker@4.0.17(vite@7.3.1)':
+ '@vitest/mocker@4.0.17(vite@7.3.1(@types/node@22.20.1))':
dependencies:
'@vitest/spy': 4.0.17
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 7.3.1
+ vite: 7.3.1(@types/node@22.20.1)
'@vitest/pretty-format@4.0.17':
dependencies:
@@ -2839,11 +2639,6 @@ snapshots:
'@vitest/pretty-format': 4.0.17
tinyrainbow: 3.0.3
- accepts@1.3.8:
- dependencies:
- mime-types: 2.1.35
- negotiator: 0.6.3
-
acorn-jsx@5.3.2(acorn@8.11.3):
dependencies:
acorn: 8.11.3
@@ -2877,17 +2672,6 @@ snapshots:
any-promise@1.3.0: {}
- anymatch@3.1.2:
- dependencies:
- normalize-path: 3.0.0
- picomatch: 2.3.1
-
- apache-crypt@1.2.5:
- dependencies:
- unix-crypt-td-js: 1.1.4
-
- apache-md5@1.1.7: {}
-
argparse@1.0.10:
dependencies:
sprintf-js: 1.0.3
@@ -2943,18 +2727,8 @@ snapshots:
bare-path: 3.0.0
optional: true
- basic-auth@2.0.1:
- dependencies:
- safe-buffer: 5.1.2
-
basic-ftp@5.1.0: {}
- batch@0.6.1: {}
-
- bcryptjs@2.4.3: {}
-
- binary-extensions@2.2.0: {}
-
brace-expansion@1.1.11:
dependencies:
balanced-match: 1.0.2
@@ -2970,6 +2744,10 @@ snapshots:
buffer-crc32@0.2.13: {}
+ bundle-name@4.1.0:
+ dependencies:
+ run-applescript: 7.1.0
+
bundle-require@5.1.0(esbuild@0.27.2):
dependencies:
esbuild: 0.27.2
@@ -2997,18 +2775,6 @@ snapshots:
ansi-styles: 4.3.0
supports-color: 7.2.0
- chokidar@3.5.3:
- dependencies:
- anymatch: 3.1.2
- braces: 3.0.2
- glob-parent: 5.1.2
- is-binary-path: 2.1.0
- is-glob: 4.0.3
- normalize-path: 3.0.0
- readdirp: 3.6.0
- optionalDependencies:
- fsevents: 2.3.3
-
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
@@ -3041,32 +2807,16 @@ snapshots:
color-name@1.1.4: {}
- colors@1.4.0: {}
-
commander@4.1.1: {}
concat-map@0.0.1: {}
confbox@0.1.8: {}
- connect@3.7.0:
- dependencies:
- debug: 2.6.9
- finalhandler: 1.1.2
- parseurl: 1.3.3
- utils-merge: 1.0.1
- transitivePeerDependencies:
- - supports-color
-
consola@3.4.2: {}
content-type@1.0.4: {}
- cors@2.8.5:
- dependencies:
- object-assign: 4.1.1
- vary: 1.1.2
-
cosmiconfig@9.0.0(typescript@5.3.3):
dependencies:
env-paths: 2.2.1
@@ -3092,10 +2842,6 @@ snapshots:
data-uri-to-buffer@6.0.2: {}
- debug@2.6.9:
- dependencies:
- ms: 2.0.0
-
debug@4.3.4:
dependencies:
ms: 2.1.2
@@ -3110,7 +2856,14 @@ snapshots:
deep-is@0.1.4: {}
- define-lazy-prop@2.0.0: {}
+ default-browser-id@5.0.1: {}
+
+ default-browser@5.5.1:
+ dependencies:
+ bundle-name: 4.1.0
+ default-browser-id: 5.0.1
+
+ define-lazy-prop@3.0.0: {}
define-properties@1.1.4:
dependencies:
@@ -3123,10 +2876,6 @@ snapshots:
escodegen: 2.1.0
esprima: 4.0.1
- depd@1.1.2: {}
-
- depd@2.0.0: {}
-
devtools-protocol@0.0.1534754: {}
dir-glob@3.0.1:
@@ -3137,20 +2886,12 @@ snapshots:
dependencies:
esutils: 2.0.3
- duplexer@0.1.2: {}
-
eastasianwidth@0.2.0: {}
- ee-first@1.1.1: {}
-
emoji-regex@8.0.0: {}
emoji-regex@9.2.2: {}
- encodeurl@1.0.2: {}
-
- encodeurl@2.0.0: {}
-
encoding@0.1.13:
dependencies:
iconv-lite: 0.6.3
@@ -3230,8 +2971,6 @@ snapshots:
escalade@3.2.0: {}
- escape-html@1.0.3: {}
-
escape-string-regexp@1.0.5: {}
escape-string-regexp@4.0.0: {}
@@ -3328,18 +3067,6 @@ snapshots:
esutils@2.0.3: {}
- etag@1.8.1: {}
-
- event-stream@4.0.1:
- dependencies:
- duplexer: 0.1.2
- from: 0.1.7
- map-stream: 0.0.7
- pause-stream: 0.0.11
- split: 1.0.1
- stream-combiner: 0.2.2
- through: 2.3.8
-
events-universal@1.0.1:
dependencies:
bare-events: 2.8.2
@@ -3382,10 +3109,6 @@ snapshots:
dependencies:
reusify: 1.0.4
- faye-websocket@0.11.4:
- dependencies:
- websocket-driver: 0.7.4
-
fd-slicer@1.1.0:
dependencies:
pend: 1.2.0
@@ -3402,18 +3125,6 @@ snapshots:
dependencies:
to-regex-range: 5.0.1
- finalhandler@1.1.2:
- dependencies:
- debug: 2.6.9
- encodeurl: 1.0.2
- escape-html: 1.0.3
- on-finished: 2.3.0
- parseurl: 1.3.3
- statuses: 1.5.0
- unpipe: 1.0.0
- transitivePeerDependencies:
- - supports-color
-
find-up@5.0.0:
dependencies:
locate-path: 6.0.0
@@ -3442,10 +3153,6 @@ snapshots:
cross-spawn: 7.0.3
signal-exit: 4.1.0
- fresh@2.0.0: {}
-
- from@0.1.7: {}
-
fs.realpath@1.0.0: {}
fsevents@2.3.3:
@@ -3565,32 +3272,6 @@ snapshots:
hosted-git-info@2.8.9: {}
- http-auth-connect@1.0.5: {}
-
- http-auth@4.1.9:
- dependencies:
- apache-crypt: 1.2.5
- apache-md5: 1.1.7
- bcryptjs: 2.4.3
- uuid: 8.3.2
-
- http-errors@1.6.3:
- dependencies:
- depd: 1.1.2
- inherits: 2.0.3
- setprototypeof: 1.1.0
- statuses: 1.5.0
-
- http-errors@2.0.1:
- dependencies:
- depd: 2.0.0
- inherits: 2.0.4
- setprototypeof: 1.2.0
- statuses: 2.0.2
- toidentifier: 1.0.1
-
- http-parser-js@0.5.8: {}
-
http-proxy-agent@7.0.2:
dependencies:
agent-base: 7.1.4
@@ -3627,8 +3308,6 @@ snapshots:
once: 1.4.0
wrappy: 1.0.2
- inherits@2.0.3: {}
-
inherits@2.0.4: {}
internal-slot@1.0.3:
@@ -3645,10 +3324,6 @@ snapshots:
dependencies:
has-bigints: 1.0.2
- is-binary-path@2.1.0:
- dependencies:
- binary-extensions: 2.2.0
-
is-boolean-object@1.1.2:
dependencies:
call-bind: 1.0.2
@@ -3664,7 +3339,7 @@ snapshots:
dependencies:
has-tostringtag: 1.0.0
- is-docker@2.2.1: {}
+ is-docker@3.0.0: {}
is-extendable@0.1.1: {}
@@ -3676,6 +3351,12 @@ snapshots:
dependencies:
is-extglob: 2.1.1
+ is-in-ssh@1.0.0: {}
+
+ is-inside-container@1.0.0:
+ dependencies:
+ is-docker: 3.0.0
+
is-negative-zero@2.0.2: {}
is-number-object@1.0.7:
@@ -3707,9 +3388,9 @@ snapshots:
dependencies:
call-bind: 1.0.2
- is-wsl@2.2.0:
+ is-wsl@3.1.1:
dependencies:
- is-docker: 2.2.1
+ is-inside-container: 1.0.0
isexe@2.0.0: {}
@@ -3786,8 +3467,6 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
- map-stream@0.0.7: {}
-
mark.js@8.11.1: {}
marked@4.0.18: {}
@@ -3801,18 +3480,6 @@ snapshots:
braces: 3.0.2
picomatch: 2.3.1
- mime-db@1.52.0: {}
-
- mime-db@1.54.0: {}
-
- mime-types@2.1.35:
- dependencies:
- mime-db: 1.52.0
-
- mime-types@3.0.2:
- dependencies:
- mime-db: 1.54.0
-
minimatch@3.1.2:
dependencies:
brace-expansion: 1.1.11
@@ -3832,17 +3499,7 @@ snapshots:
pkg-types: 1.3.1
ufo: 1.6.3
- morgan@1.10.0:
- dependencies:
- basic-auth: 2.0.1
- debug: 2.6.9
- depd: 2.0.0
- on-finished: 2.3.0
- on-headers: 1.0.2
- transitivePeerDependencies:
- - supports-color
-
- ms@2.0.0: {}
+ mrmime@2.0.1: {}
ms@2.1.2: {}
@@ -3858,8 +3515,6 @@ snapshots:
natural-compare@1.4.0: {}
- negotiator@0.6.3: {}
-
netmask@2.0.2: {}
nice-try@1.0.5: {}
@@ -3871,8 +3526,6 @@ snapshots:
semver: 5.7.1
validate-npm-package-license: 3.0.4
- normalize-path@3.0.0: {}
-
npm-run-all@4.1.5:
dependencies:
ansi-styles: 3.2.1
@@ -3900,25 +3553,18 @@ snapshots:
obug@2.1.1: {}
- on-finished@2.3.0:
- dependencies:
- ee-first: 1.1.1
-
- on-finished@2.4.1:
- dependencies:
- ee-first: 1.1.1
-
- on-headers@1.0.2: {}
-
once@1.4.0:
dependencies:
wrappy: 1.0.2
- open@8.4.0:
+ open@11.0.2:
dependencies:
- define-lazy-prop: 2.0.0
- is-docker: 2.2.1
- is-wsl: 2.2.0
+ default-browser: 5.5.1
+ define-lazy-prop: 3.0.0
+ is-in-ssh: 1.0.0
+ is-inside-container: 1.0.0
+ powershell-utils: 0.2.1
+ wsl-utils: 1.0.0
optionator@0.9.3:
dependencies:
@@ -3979,8 +3625,6 @@ snapshots:
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
- parseurl@1.3.3: {}
-
path-exists@4.0.0: {}
path-exists@5.0.0: {}
@@ -4006,10 +3650,6 @@ snapshots:
pathe@2.0.3: {}
- pause-stream@0.0.11:
- dependencies:
- through: 2.3.8
-
pend@1.2.0: {}
picocolors@1.0.0: {}
@@ -4049,6 +3689,10 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ powershell-utils@0.1.0: {}
+
+ powershell-utils@0.2.1: {}
+
prelude-ls@1.2.1: {}
prettier@3.8.0: {}
@@ -4070,8 +3714,6 @@ snapshots:
proxy-from-env@1.1.0: {}
- proxy-middleware@0.15.0: {}
-
pump@3.0.0:
dependencies:
end-of-stream: 1.4.4
@@ -4115,8 +3757,6 @@ snapshots:
queue-microtask@1.2.3: {}
- range-parser@1.2.1: {}
-
read-pkg@3.0.0:
dependencies:
load-json-file: 4.0.0
@@ -4129,10 +3769,6 @@ snapshots:
string_decoder: 1.3.0
util-deprecate: 1.0.2
- readdirp@3.6.0:
- dependencies:
- picomatch: 2.3.1
-
readdirp@4.1.2: {}
readdirp@5.0.0: {}
@@ -4201,12 +3837,12 @@ snapshots:
postcss: 8.5.6
strip-json-comments: 3.1.1
+ run-applescript@7.1.0: {}
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
- safe-buffer@5.1.2: {}
-
safe-buffer@5.2.1: {}
safer-buffer@2.1.2: {}
@@ -4226,38 +3862,6 @@ snapshots:
semver@7.7.3: {}
- send@1.2.1:
- dependencies:
- debug: 4.4.3
- encodeurl: 2.0.0
- escape-html: 1.0.3
- etag: 1.8.1
- fresh: 2.0.0
- http-errors: 2.0.1
- mime-types: 3.0.2
- ms: 2.1.3
- on-finished: 2.4.1
- range-parser: 1.2.1
- statuses: 2.0.2
- transitivePeerDependencies:
- - supports-color
-
- serve-index@1.9.1:
- dependencies:
- accepts: 1.3.8
- batch: 0.6.1
- debug: 2.6.9
- escape-html: 1.0.3
- http-errors: 1.6.3
- mime-types: 2.1.35
- parseurl: 1.3.3
- transitivePeerDependencies:
- - supports-color
-
- setprototypeof@1.1.0: {}
-
- setprototypeof@1.2.0: {}
-
shebang-command@1.2.0:
dependencies:
shebang-regex: 1.0.0
@@ -4282,6 +3886,12 @@ snapshots:
signal-exit@4.1.0: {}
+ sirv@3.0.2:
+ dependencies:
+ '@polka/url': 1.0.0-next.29
+ mrmime: 2.0.1
+ totalist: 3.0.1
+
slash@3.0.0: {}
smart-buffer@4.2.0: {}
@@ -4320,25 +3930,12 @@ snapshots:
spdx-license-ids@3.0.11: {}
- split@1.0.1:
- dependencies:
- through: 2.3.8
-
sprintf-js@1.0.3: {}
stackback@0.0.2: {}
- statuses@1.5.0: {}
-
- statuses@2.0.2: {}
-
std-env@3.10.0: {}
- stream-combiner@0.2.2:
- dependencies:
- duplexer: 0.1.2
- through: 2.3.8
-
streamx@2.23.0:
dependencies:
events-universal: 1.0.1
@@ -4453,8 +4050,6 @@ snapshots:
dependencies:
any-promise: 1.3.0
- through@2.3.8: {}
-
tinybench@2.9.0: {}
tinyexec@0.3.2: {}
@@ -4472,7 +4067,7 @@ snapshots:
dependencies:
is-number: 7.0.0
- toidentifier@1.0.1: {}
+ totalist@3.0.1: {}
tree-kill@1.2.2: {}
@@ -4531,11 +4126,10 @@ snapshots:
has-symbols: 1.0.3
which-boxed-primitive: 1.0.2
- undici-types@5.26.5: {}
-
- unix-crypt-td-js@1.1.4: {}
+ undici-types@5.26.5:
+ optional: true
- unpipe@1.0.0: {}
+ undici-types@6.21.0: {}
uri-js@4.4.1:
dependencies:
@@ -4543,18 +4137,12 @@ snapshots:
util-deprecate@1.0.2: {}
- utils-merge@1.0.1: {}
-
- uuid@8.3.2: {}
-
validate-npm-package-license@3.0.4:
dependencies:
spdx-correct: 3.1.1
spdx-expression-parse: 3.0.1
- vary@1.1.2: {}
-
- vite@7.3.1:
+ vite@7.3.1(@types/node@22.20.1):
dependencies:
esbuild: 0.27.2
fdir: 6.5.0(picomatch@4.0.3)
@@ -4563,12 +4151,13 @@ snapshots:
rollup: 4.55.1
tinyglobby: 0.2.15
optionalDependencies:
+ '@types/node': 22.20.1
fsevents: 2.3.3
- vitest@4.0.17:
+ vitest@4.0.17(@types/node@22.20.1):
dependencies:
'@vitest/expect': 4.0.17
- '@vitest/mocker': 4.0.17(vite@7.3.1)
+ '@vitest/mocker': 4.0.17(vite@7.3.1(@types/node@22.20.1))
'@vitest/pretty-format': 4.0.17
'@vitest/runner': 4.0.17
'@vitest/snapshot': 4.0.17
@@ -4585,8 +4174,10 @@ snapshots:
tinyexec: 1.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
- vite: 7.3.1
+ vite: 7.3.1(@types/node@22.20.1)
why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 22.20.1
transitivePeerDependencies:
- jiti
- less
@@ -4602,14 +4193,6 @@ snapshots:
webdriver-bidi-protocol@0.3.10: {}
- websocket-driver@0.7.4:
- dependencies:
- http-parser-js: 0.5.8
- safe-buffer: 5.2.1
- websocket-extensions: 0.1.4
-
- websocket-extensions@0.1.4: {}
-
which-boxed-primitive@1.0.2:
dependencies:
is-bigint: 1.0.4
@@ -4647,6 +4230,11 @@ snapshots:
ws@8.19.0: {}
+ wsl-utils@1.0.0:
+ dependencies:
+ is-wsl: 3.1.1
+ powershell-utils: 0.1.0
+
y18n@5.0.8: {}
yallist@4.0.0: {}
From 2353efe425a51c57a8aab476ab2206ae9856e33c Mon Sep 17 00:00:00 2001
From: Chris Campbell
Date: Thu, 3 Sep 2026 16:59:18 -0700
Subject: [PATCH 2/4] fix: use a different port if default port is in use
---
packages/docs-builder/bin/cli.js | 17 +-
packages/docs-builder/src/dev-server.spec.ts | 136 +++++++++++++++-
packages/docs-builder/src/dev-server.ts | 159 +++++++++++++++++--
3 files changed, 292 insertions(+), 20 deletions(-)
diff --git a/packages/docs-builder/bin/cli.js b/packages/docs-builder/bin/cli.js
index beb596d..54403f9 100755
--- a/packages/docs-builder/bin/cli.js
+++ b/packages/docs-builder/bin/cli.js
@@ -157,18 +157,23 @@ async function main() {
// Set up a file watcher so that we rebuild any time a source file is changed
watch()
- // Start local server
- const port = 8100
- // TODO: Make this configurable
+ // Start local server. Note that if the preferred port is already in use (for
+ // example, when a dev server is already running for a different project), the
+ // server will listen on the next available port, so use the port that it reports.
+ // TODO: Make the port and the path configurable
+ const preferredPort = 8100
const openPath = '/public/en/latest/index.html'
- await startDevServer({
+ const devServer = await startDevServer({
rootDir,
- port,
+ port: preferredPort,
watchPath: 'timestamp'
})
+ if (devServer.port !== preferredPort) {
+ console.log(`\nPort ${preferredPort} is already in use; using port ${devServer.port} instead`)
+ }
// Open the docs in the default browser
- const url = `http://localhost:${port}${openPath}`
+ const url = `http://localhost:${devServer.port}${openPath}`
console.log(`\nLocal server running at ${url}`)
await open(url)
} else {
diff --git a/packages/docs-builder/src/dev-server.spec.ts b/packages/docs-builder/src/dev-server.spec.ts
index aad4f62..527ae83 100644
--- a/packages/docs-builder/src/dev-server.spec.ts
+++ b/packages/docs-builder/src/dev-server.spec.ts
@@ -1,7 +1,9 @@
// Copyright (c) 2026 Climate Interactive / New Venture Fund. All rights reserved.
import { mkdtempSync, rmSync, writeFileSync } from 'fs'
-import { get as httpGet } from 'http'
+import type { Server } from 'http'
+import { createServer, get as httpGet } from 'http'
+import type { AddressInfo } from 'net'
import { tmpdir } from 'os'
import { join as joinPath } from 'path'
@@ -17,6 +19,7 @@ import {
let rootDir: string
let server: DevServer | undefined
+let otherServers: Server[]
/** An open connection to the server-sent event stream. */
interface EventStream {
@@ -72,14 +75,102 @@ function openEventStream(url: string): Promise {
})
}
+/**
+ * Start a plain server that listens on the given port.
+ *
+ * @param port The port to listen on, or zero to listen on an arbitrary free port.
+ * @param host The address to listen on, or undefined to listen on all addresses.
+ * @returns A promise that is resolved with the server once it is listening, or rejected
+ * if the port is not available.
+ */
+function listenOnPort(port: number, host?: string): Promise {
+ return new Promise((resolve, reject) => {
+ const other = createServer()
+ other.on('error', reject)
+ const listening = () => resolve(other)
+ if (host !== undefined) {
+ other.listen(port, host, listening)
+ } else {
+ other.listen(port, listening)
+ }
+ })
+}
+
+/**
+ * Close the given server.
+ *
+ * @param other The server to close.
+ * @returns A promise that is resolved once the server has been closed.
+ */
+function closeServer(other: Server): Promise {
+ return new Promise(resolve => other.close(() => resolve()))
+}
+
+/**
+ * Return the port that the given server is listening on.
+ *
+ * @param other The server.
+ * @returns The port.
+ */
+function portOf(other: Server): number {
+ return (other.address() as AddressInfo).port
+}
+
+/**
+ * Find a range of consecutive ports that are currently unused.
+ *
+ * The operating system only hands out one arbitrary free port at a time, so the ports
+ * that follow it are claimed as well to confirm that the whole range is available.
+ *
+ * @param count The number of consecutive ports needed.
+ * @returns A promise that is resolved with the first port in the range.
+ */
+async function findFreePortRange(count: number): Promise {
+ for (let attempt = 0; attempt < 20; attempt++) {
+ const servers: Server[] = []
+ let firstPort = 0
+ try {
+ const first = await listenOnPort(0)
+ servers.push(first)
+ firstPort = portOf(first)
+ for (let offset = 1; offset < count; offset++) {
+ servers.push(await listenOnPort(firstPort + offset))
+ }
+ } catch {
+ // One of the ports that follows is in use, so try a different range
+ firstPort = 0
+ }
+ await Promise.all(servers.map(closeServer))
+ if (firstPort > 0) {
+ return firstPort
+ }
+ }
+ throw new Error(`Failed to find ${count} consecutive free ports`)
+}
+
+/**
+ * Start a plain server that holds the given port open, so that the dev server sees the
+ * port as unavailable.
+ *
+ * @param port The port to hold open.
+ * @param host The address to hold open, or undefined to hold open all addresses.
+ * @returns A promise that is resolved once the server is listening.
+ */
+async function occupyPort(port: number, host?: string): Promise {
+ otherServers.push(await listenOnPort(port, host))
+}
+
beforeEach(() => {
rootDir = mkdtempSync(joinPath(tmpdir(), 'docs-builder-dev-server-'))
writeFileSync(joinPath(rootDir, 'timestamp'), 'initial')
+ otherServers = []
})
afterEach(async () => {
await server?.close()
server = undefined
+ await Promise.all(otherServers.map(closeServer))
+ otherServers = []
rmSync(rootDir, { recursive: true, force: true })
})
@@ -134,6 +225,49 @@ describe('startDevServer', () => {
}
})
+ it('should use the next port if the requested port is already in use', async () => {
+ const port = await findFreePortRange(2)
+ await occupyPort(port)
+
+ writeFileSync(joinPath(rootDir, 'index.html'), 'hello