From 82192d705fa8a093aa8f43b1cf180ee12b0bcd51 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 28 Mar 2025 17:38:17 +0100 Subject: [PATCH 01/22] feat!: support libp2p over http/websockets and http/websockets over libp2p Supports running libp2p streams over HTTPm, as well as HTTP requests over libp2p. Also supports upgrading HTTP-over-libp2p requests to WebSockets, as well as libp2p-over-HTTP requests so you can do full-duplex libp2p things and aren't limited to simple request/response protocols. As a bonus, it also supports accepting HTTP & WebSocket requests in browsers without having to polyfill and Node.js internals. BREAKING CHANGE: the API has change significantly, this module has been renamed `@libp2p/http` since it now does much more than fetch --- .aegir.js | 132 +- README.md | 2883 +- examples/express-server-over-libp2p/client.js | 61 + examples/express-server-over-libp2p/server.js | 54 + package-lock.json | 25579 ---------------- package.json | 54 +- src/auth/client.ts | 2 +- src/constants.ts | 2 +- src/fetch.ts | 373 + src/fetch/body/blob.ts | 6 + src/fetch/body/bytes.ts | 13 + src/fetch/body/form-data.ts | 116 + src/fetch/body/readable-stream.ts | 26 + src/fetch/body/string.ts | 13 + src/fetch/index.ts | 417 +- src/fetch/read-response.ts | 85 + src/fetch/send-request.ts | 102 + src/http.browser.ts | 332 + src/http.ts | 108 + src/http/incoming-message.ts | 71 + src/http/index.browser.ts | 38 + src/http/index.ts | 1 + src/http/server-response.ts | 310 + src/http/server.ts | 156 + src/index.ts | 543 +- src/ping.ts | 64 - src/ping/index.ts | 26 + src/ping/ping.ts | 132 + src/registrar.ts | 157 + src/servers/fetch.ts | 24 + src/servers/node.ts | 110 + src/stream-to-socket.ts | 200 + src/utils.ts | 238 + src/websocket/events.ts | 13 + src/websocket/index.ts | 102 + src/websocket/message.ts | 236 + src/websocket/server.ts | 37 + src/websocket/utils.ts | 166 + src/websocket/websocket.ts | 412 + src/well-known-handler.ts | 24 +- src/whatwg-fetch-service.ts | 265 - test/auth.spec.ts | 111 + test/fetch.spec.ts | 257 + test/fetch/index.spec.ts | 5 +- test/fixtures/create-express.ts | 38 + test/fixtures/create-fastify-http.ts | 54 + test/fixtures/create-fastify-websocket.ts | 48 + test/fixtures/create-http.ts | 27 + test/fixtures/create-websocket-server.ts | 42 + test/fixtures/create-wss.ts | 43 + test/fixtures/get-libp2p-over-http-handler.ts | 74 + test/fixtures/get-libp2p.ts | 58 + test/fixtures/get-server.ts | 26 + test/fixtures/to-websocket.ts | 32 + test/index.spec.ts | 109 - test/node.ts | 99 - test/ping.spec.ts | 318 + test/websocket/message.spec.ts | 113 + test/websockets.spec.ts | 155 + 59 files changed, 8641 insertions(+), 26651 deletions(-) create mode 100644 examples/express-server-over-libp2p/client.js create mode 100644 examples/express-server-over-libp2p/server.js delete mode 100644 package-lock.json create mode 100644 src/fetch.ts create mode 100644 src/fetch/body/blob.ts create mode 100644 src/fetch/body/bytes.ts create mode 100644 src/fetch/body/form-data.ts create mode 100644 src/fetch/body/readable-stream.ts create mode 100644 src/fetch/body/string.ts create mode 100644 src/fetch/read-response.ts create mode 100644 src/fetch/send-request.ts create mode 100644 src/http.browser.ts create mode 100644 src/http.ts create mode 100644 src/http/incoming-message.ts create mode 100644 src/http/index.browser.ts create mode 100644 src/http/index.ts create mode 100644 src/http/server-response.ts create mode 100644 src/http/server.ts delete mode 100644 src/ping.ts create mode 100644 src/ping/index.ts create mode 100644 src/ping/ping.ts create mode 100644 src/registrar.ts create mode 100644 src/servers/fetch.ts create mode 100644 src/servers/node.ts create mode 100644 src/stream-to-socket.ts create mode 100644 src/utils.ts create mode 100644 src/websocket/events.ts create mode 100644 src/websocket/index.ts create mode 100644 src/websocket/message.ts create mode 100644 src/websocket/server.ts create mode 100644 src/websocket/utils.ts create mode 100644 src/websocket/websocket.ts delete mode 100644 src/whatwg-fetch-service.ts create mode 100644 test/auth.spec.ts create mode 100644 test/fetch.spec.ts create mode 100644 test/fixtures/create-express.ts create mode 100644 test/fixtures/create-fastify-http.ts create mode 100644 test/fixtures/create-fastify-websocket.ts create mode 100644 test/fixtures/create-http.ts create mode 100644 test/fixtures/create-websocket-server.ts create mode 100644 test/fixtures/create-wss.ts create mode 100644 test/fixtures/get-libp2p-over-http-handler.ts create mode 100644 test/fixtures/get-libp2p.ts create mode 100644 test/fixtures/get-server.ts create mode 100644 test/fixtures/to-websocket.ts delete mode 100644 test/index.spec.ts delete mode 100644 test/node.ts create mode 100644 test/ping.spec.ts create mode 100644 test/websocket/message.spec.ts create mode 100644 test/websockets.spec.ts diff --git a/.aegir.js b/.aegir.js index 9a48402..1640c72 100644 --- a/.aegir.js +++ b/.aegir.js @@ -1,12 +1,132 @@ +import { stop } from '@libp2p/interface' +import http from 'node:http' -/** @type {import('aegir/types').PartialOptions} */ +function stoppableServer (server) { + return { + start: () => {}, + stop: () => { + server.close() + server.closeAllConnections() + } + } +} + +async function startHTTPServer (server) { + return new Promise((resolve, reject) => { + server.on('listening', () => { + const address = server.address() + + if (address == null || typeof address === 'string') { + reject(new Error('Did not listen on port')) + return + } + + resolve(address.port) + }) + server.on('error', err => { + reject(err) + }) + server.listen(0) + }) +} + +/** @type {import('aegir').PartialOptions} */ export default { build: { - bundlesizeMax: '18kB' + bundlesizeMax: '24kB' }, - dependencyCheck: { - ignore: [ - 'undici' // required by http-cookie-agent - ] + test: { + before: async () => { + const { createServer } = await import('./dist/src/http/index.js') + const { nodeServer } = await import('./dist/src/servers/node.js') + const { getListener } = await import('./dist/test/fixtures/get-libp2p.js') + const { createHttp } = await import('./dist/test/fixtures/create-http.js') + const { createFastifyHTTP } = await import('./dist/test/fixtures/create-fastify-http.js') + const { createExpress } = await import('./dist/test/fixtures/create-express.js') + const { createWss } = await import('./dist/test/fixtures/create-wss.js') + const { createFastifyWebSocket } = await import('./dist/test/fixtures/create-fastify-websocket.js') + const { getLibp2pOverHttpHandler } = await import('./dist/test/fixtures/get-libp2p-over-http-handler.js') + + // --- http-over-libp2p + const jsHttpListener = await getListener(nodeServer(createHttp(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpListener = await getListener(nodeServer(createHttp(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const jsExpressListener = await getListener(nodeServer(createExpress(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpExpressListener = await getListener(nodeServer(createExpress(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const jsFastifyListener = await getListener(nodeServer(await createFastifyHTTP(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpFastifyListener = await getListener(nodeServer(await createFastifyHTTP(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + + // --- ws-over-libp2p + const jsWssListener = await getListener(nodeServer(createWss(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpWssListener = await getListener(nodeServer(createWss(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const jsFastifyWsListener = await getListener(nodeServer(await createFastifyWebSocket(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpFastifyWsListener = await getListener(nodeServer(await createFastifyWebSocket(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + + // --- libp2p-over-http + const libp2pOverHttpHandler = await getLibp2pOverHttpHandler() + const express = createExpress(http.createServer(), libp2pOverHttpHandler.http) + const nodeHttp = createHttp(http.createServer(), libp2pOverHttpHandler.http) + const fastify = await createFastifyHTTP(http.createServer(), libp2pOverHttpHandler.http) + + // --- libp2p-over-ws + const wss = createWss(http.createServer(), libp2pOverHttpHandler.http, libp2pOverHttpHandler.ws) + const fastifyWs = await createFastifyWebSocket(http.createServer(), libp2pOverHttpHandler.http, libp2pOverHttpHandler.ws) + + return { + // http-over-libp2p + jsHttpListener, + nodeHttpListener, + jsExpressListener, + nodeHttpExpressListener, + jsFastifyListener, + nodeHttpFastifyListener, + + // ws-over-libp2p + jsWssListener, + nodeHttpWssListener, + jsFastifyWsListener, + nodeHttpFastifyWsListener, + + // libp2p-over-http + libp2pOverHttpHandler: libp2pOverHttpHandler.libp2p, + nodeHttp: stoppableServer(nodeHttp), + express: stoppableServer(express), + fastify: stoppableServer(fastify), + + // libp2p-over-ws + wss: stoppableServer(wss), + fastifyWs: stoppableServer(fastifyWs), + + env: { + // http-over-libp2p + LIBP2P_JS_HTTP_MULTIADDR: jsHttpListener.getMultiaddrs()[0], + LIBP2P_NODE_HTTP_MULTIADDR: nodeHttpListener.getMultiaddrs()[0], + LIBP2P_JS_EXPRESS_MULTIADDR: jsExpressListener.getMultiaddrs()[0], + LIBP2P_NODE_EXPRESS_MULTIADDR: nodeHttpExpressListener.getMultiaddrs()[0], + LIBP2P_JS_FASTIFY_MULTIADDR: jsFastifyListener.getMultiaddrs()[0], + LIBP2P_NODE_FASTIFY_MULTIADDR: nodeHttpFastifyListener.getMultiaddrs()[0], + + // ws-over-libp2p + LIBP2P_JS_WSS_MULTIADDR: jsWssListener.getMultiaddrs()[0], + LIBP2P_NODE_WSS_MULTIADDR: nodeHttpWssListener.getMultiaddrs()[0], + LIBP2P_JS_FASTIFY_WS_MULTIADDR: jsFastifyWsListener.getMultiaddrs()[0], + LIBP2P_NODE_FASTIFY_WS_MULTIADDR: nodeHttpFastifyWsListener.getMultiaddrs()[0], + + // libp2p-over-http + HTTP_PEER_ID: `${libp2pOverHttpHandler.libp2p.peerId}`, + HTTP_NODE_HTTP_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(nodeHttp)}/http`, + HTTP_EXPRESS_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(express)}/http`, + HTTP_FASTIFY_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(fastify)}/http`, + + // libp2p-over-ws + WS_WSS_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(wss)}/http`, + WS_FASTIFY_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(fastifyWs)}/http` + } + } + }, + after: async (_, before) => { + await stop( + ...Object.values(before) + ) + } } } diff --git a/README.md b/README.md index 04c65b8..21c6d89 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http-fetch.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http-fetch) [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http-fetch/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http-fetch/actions/workflows/js-test-and-release.yml?query=branch%3Amain) -> Implementation of the WHATWG Fetch API on libp2p streams +> Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP # About @@ -24,36 +24,2875 @@ repo and examine the changes made. --> -http implements the WHATWG [Fetch -api](https://fetch.spec.whatwg.org). It can be used as a drop in replacement -for the browser's fetch function. It supports http, https, and multiaddr -URIs. Use HTTP in p2p networks. +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). -## Example +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). -See the `examples/` for full examples of how to use the HTTP service. +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +(based on the [ws](https://www.npmjs.com/package/ws) module API in the +absence of a native Node.js API to emulate) in browsers to truly realize the +power of the distributed web. -```typescript +Instead of the regular "host:port" addressing, it uses a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@libp2p/http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import { multiaddr } from '@multiformats/multiaddr' + +const client = await createLibp2p({ + // ...other options + services: { + http: http() + } +}) + +const peerId = peerIdFromString('12DKoo') +const ma = multiaddr(`/p2p/${peerId}/http`) +const response = await client.services.httpClient.fetch(ma, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@libp2p/http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@libp2p/http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import { multiaddr } from '@multiformats/multiaddr' + +const client = await createLibp2p({ + // ...other options + services: { + http: http() + } +}) + +const peerId = peerIdFromString('12DKoo') +const ma = multiaddr(`/p2p/${peerId}/http`) +const response = await client.services.httpClient.fetch(ma, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@libp2p/http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server)) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server)) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http-fetch' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' -const node = await createLibp2p({ - // other options ... - services: { - http: http() - } +const server = createServer((req, res) => { + req.end('Hello world!') }) -await node.start() +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@libp2p/libp2p-http' +import { nodeServer } from '@libp2p/libp2p-http/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: httpServer({ server: nodeServer(server) }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - ws WebSocket server + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@ipshipyard/libp2p-http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' -// Make an http request to a libp2p peer -let resp = await node.services.http.fetch('multiaddr:/dns4/localhost/tcp/1234') -// Or a traditional HTTP request -resp = await node.services.http.fetch('multiaddr:/dns4/example.com/tcp/443/tls/http') -// And of course, you can use the fetch API as you normally would -resp = await node.services.http.fetch('https://example.com') +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const response = await client.services.httpClient.fetch(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@ipshipyard/libp2p-http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@ipshipyard/libp2p-http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' -// This gives you the accessibility of the fetch API with the flexibility of using a p2p network. +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) ``` # Install diff --git a/examples/express-server-over-libp2p/client.js b/examples/express-server-over-libp2p/client.js new file mode 100644 index 0000000..91dd32a --- /dev/null +++ b/examples/express-server-over-libp2p/client.js @@ -0,0 +1,61 @@ +/* eslint-disable no-console */ + +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { http } from '@libp2p/http-fetch' +import { sendPing } from '@libp2p/http-fetch/ping' +import { tcp } from '@libp2p/tcp' +import { multiaddr } from '@multiformats/multiaddr' +import { createLibp2p } from 'libp2p' + +const node = await createLibp2p({ + // libp2p nodes are started by default, pass false to override this + start: false, + addresses: { + listen: [] + }, + transports: [tcp()], + connectionEncrypters: [noise()], + streamMuxers: [yamux()], + services: { http: http() } +}) + +// start libp2p +await node.start() +console.error('libp2p has started') + +// Read server multiaddr from the command line +const serverAddr = process.argv[2] +if (!serverAddr) { + console.error('Please provide the server multiaddr as an argument') + process.exit(1) +} + +let serverMA = multiaddr(serverAddr) + +const isHTTPTransport = serverMA.protos().find(p => p.name === 'http') // check if this is an http transport multiaddr +if (!isHTTPTransport && serverMA.getPeerId() === null) { + // Learn the peer id of the server. This lets us reuse the connection for all our HTTP requests. + // Otherwise js-libp2p will open a new connection for each request. + const conn = await node.dial(serverMA) + serverMA = serverMA.encapsulate(`/p2p/${conn.remotePeer.toString()}`) +} + +console.error('Making request to', `${serverMA.toString()}`) +try { + const resp = await node.services.http.fetch(new Request(`multiaddr:${serverMA}` + `/http-path/${encodeURIComponent('my-app')}`)) + const respBody = await resp.text() + if (resp.status !== 200) { + throw new Error(`Unexpected status code: ${resp.status}`) + } + if (respBody !== 'Hono!') { + throw new Error(`Unexpected response body: ${respBody}`) + } + + const start = new Date().getTime() + await sendPing(node, serverMA) + const end = new Date().getTime() + console.error('HTTP Ping took', end - start, 'ms') +} finally { + await node.stop() +} diff --git a/examples/express-server-over-libp2p/server.js b/examples/express-server-over-libp2p/server.js new file mode 100644 index 0000000..b18ab77 --- /dev/null +++ b/examples/express-server-over-libp2p/server.js @@ -0,0 +1,54 @@ +/* eslint-disable no-console */ + +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { http } from '@libp2p/http-fetch' +import { PING_PROTOCOL_ID, servePing } from '@libp2p/http-fetch/ping' +import { tcp } from '@libp2p/tcp' +import express from 'express' +import { createLibp2p } from 'libp2p' + +const app = express() + +const node = await createLibp2p({ + addresses: { + listen: ['/ip4/127.0.0.1/tcp/8000'] + }, + transports: [tcp()], + connectionEncrypters: [noise()], + streamMuxers: [yamux()], + services: { + http: http() + } +}) + +node.services.http.registerProtocol(PING_PROTOCOL_ID, '/ping') + +// start libp2p +await node.start() +console.error('libp2p has started') + +// Also listen on a standard http transport +const server = servePing({ + fetch: app.fetch, + port: 8001, + hostname: '127.0.0.1' +}) + +const listenAddrs = node.getMultiaddrs() +console.error('libp2p is listening on the following addresses:') +console.log('/ip4/127.0.0.1/tcp/8001/http') +for (const addr of listenAddrs) { + console.log(addr.toString()) +} +console.log('') // Empty line to signal we have no more addresses (for test runner) + +// wait for SIGINT +await new Promise(resolve => process.on('SIGINT', resolve)) + +// Stop the http server +server.close() + +// stop libp2p +node.stop() +console.error('libp2p has stopped') diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d61ac74..0000000 --- a/package-lock.json +++ /dev/null @@ -1,25579 +0,0 @@ -{ - "name": "@libp2p/http-fetch", - "version": "2.2.2", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@libp2p/http-fetch", - "version": "2.2.2", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@achingbrain/http-parser-js": "^0.5.8", - "@libp2p/crypto": "^5.0.6", - "@libp2p/interface": "^2.2.0", - "@libp2p/interface-internal": "^2.0.10", - "@libp2p/peer-id": "^5.0.7", - "@multiformats/multiaddr": "^12.3.0", - "@multiformats/multiaddr-to-uri": "^11.0.0", - "http-cookie-agent": "^6.0.7", - "p-defer": "^4.0.1", - "tough-cookie": "^5.0.0", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0", - "undici": "^6.21.0" - }, - "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.1.8", - "@libp2p/logger": "^5.1.3", - "aegir": "^45.0.0", - "it-pair": "^2.0.6", - "libp2p": "^2.2.1", - "sinon-ts": "^2.0.0" - } - }, - "node_modules/@achingbrain/http-parser-js": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@achingbrain/http-parser-js/-/http-parser-js-0.5.8.tgz", - "integrity": "sha512-7P8ukzL4jyh8Fho5tSfPBTzWJUZ0D7DxaW7ObObT5HTcljhjq9NN/qFg1yzPxq0VWRI/8qPnSUa1ofzzH/R9eQ==", - "license": "MIT", - "dependencies": { - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@arr/every": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@arr/every/-/every-1.0.1.tgz", - "integrity": "sha512-UQFQ6SgyJ6LX42W8rHCs8KVc0JS0tzVL9ct4XYedJukskYVWTo49tNiMEK9C2HTyarbNiT/RVIRSY82vH+6sTg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", - "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", - "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/helper-compilation-targets": "^7.26.5", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/traverse": "^7.26.10", - "@babel/types": "^7.26.10", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", - "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", - "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", - "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.26.8", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", - "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/helper-replace-supers": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.27.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", - "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", - "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", - "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.24.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", - "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", - "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", - "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", - "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.25.9", - "@babel/helper-optimise-call-expression": "^7.25.9", - "@babel/traverse": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", - "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-export-default-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.25.9.tgz", - "integrity": "sha512-ykqgwNfSnNOB+C8fV5X4mG3AVmvu+WVxcaU9xHHtBb7PCrPeweMmPjGsn8eMaeJg6SJuoUuZENeeSWaarWqonQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-export-default-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.25.9.tgz", - "integrity": "sha512-9MhJ/SMTsVqsd69GyQg89lYR4o9T+oDGv5F6IsigxxqFVOyR/IflDLYP8WDI1l8fkhNGGktqkvL5qwNCtGEpgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-flow": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", - "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", - "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", - "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", - "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/plugin-syntax-flow": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", - "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", - "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-assign": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.25.9.tgz", - "integrity": "sha512-I/Vl1aQnPsrrn837oLbo+VQtkNcjuuiATqwmuweg4fTauwHHQoxyjmjjOVKyO8OaTxgqYTKW3LuQsykXjDf5Ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz", - "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz", - "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", - "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.10.tgz", - "integrity": "sha512-NWaL2qG6HRpONTnj4JvDU6th4jYeZOJgu3QhmFTCihib0ermtOJqktA5BduGm3suhhVe9EMP9c9+mfJ/I9slqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.26.5", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.11.0", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", - "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.26.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typescript": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz", - "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.27.0", - "@babel/helper-plugin-utils": "^7.26.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-syntax-typescript": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", - "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.27.0", - "@babel/parser": "^7.27.0", - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", - "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@chainsafe/is-ip": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.1.0.tgz", - "integrity": "sha512-KIjt+6IfysQ4GCv66xihEitBjvhU/bixbbbFxdJ1sqCp4uJ0wuZiYBPhksZoy4lfaF0k9cwNzY5upEW/VWdw3w==", - "license": "MIT" - }, - "node_modules/@chainsafe/netmask": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@chainsafe/netmask/-/netmask-2.0.0.tgz", - "integrity": "sha512-I3Z+6SWUoaljh3TBzCnCxjlUyN8tA+NAk5L6m9IxvCf1BENQTePzPMis97CoN/iMW1St3WN+AWCCRp+TTBRiDg==", - "license": "MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cspell/cspell-bundled-dicts": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.17.5.tgz", - "integrity": "sha512-b/Ntabar+g4gsRNwOct909cvatO/auHhNvBzJZfyFQzryI1nqHMaSFuDsrrtzbhQkGJ4GiMAKCXZC2EOdHMgmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/dict-ada": "^4.1.0", - "@cspell/dict-al": "^1.1.0", - "@cspell/dict-aws": "^4.0.9", - "@cspell/dict-bash": "^4.2.0", - "@cspell/dict-companies": "^3.1.14", - "@cspell/dict-cpp": "^6.0.4", - "@cspell/dict-cryptocurrencies": "^5.0.4", - "@cspell/dict-csharp": "^4.0.6", - "@cspell/dict-css": "^4.0.17", - "@cspell/dict-dart": "^2.3.0", - "@cspell/dict-data-science": "^2.0.7", - "@cspell/dict-django": "^4.1.4", - "@cspell/dict-docker": "^1.1.12", - "@cspell/dict-dotnet": "^5.0.9", - "@cspell/dict-elixir": "^4.0.7", - "@cspell/dict-en_us": "^4.3.33", - "@cspell/dict-en-common-misspellings": "^2.0.9", - "@cspell/dict-en-gb": "1.1.33", - "@cspell/dict-filetypes": "^3.0.11", - "@cspell/dict-flutter": "^1.1.0", - "@cspell/dict-fonts": "^4.0.4", - "@cspell/dict-fsharp": "^1.1.0", - "@cspell/dict-fullstack": "^3.2.5", - "@cspell/dict-gaming-terms": "^1.1.0", - "@cspell/dict-git": "^3.0.4", - "@cspell/dict-golang": "^6.0.18", - "@cspell/dict-google": "^1.0.8", - "@cspell/dict-haskell": "^4.0.5", - "@cspell/dict-html": "^4.0.11", - "@cspell/dict-html-symbol-entities": "^4.0.3", - "@cspell/dict-java": "^5.0.11", - "@cspell/dict-julia": "^1.1.0", - "@cspell/dict-k8s": "^1.0.10", - "@cspell/dict-kotlin": "^1.1.0", - "@cspell/dict-latex": "^4.0.3", - "@cspell/dict-lorem-ipsum": "^4.0.4", - "@cspell/dict-lua": "^4.0.7", - "@cspell/dict-makefile": "^1.0.4", - "@cspell/dict-markdown": "^2.0.9", - "@cspell/dict-monkeyc": "^1.0.10", - "@cspell/dict-node": "^5.0.6", - "@cspell/dict-npm": "^5.1.27", - "@cspell/dict-php": "^4.0.14", - "@cspell/dict-powershell": "^5.0.14", - "@cspell/dict-public-licenses": "^2.0.13", - "@cspell/dict-python": "^4.2.15", - "@cspell/dict-r": "^2.1.0", - "@cspell/dict-ruby": "^5.0.7", - "@cspell/dict-rust": "^4.0.11", - "@cspell/dict-scala": "^5.0.7", - "@cspell/dict-shell": "^1.1.0", - "@cspell/dict-software-terms": "^4.2.5", - "@cspell/dict-sql": "^2.2.0", - "@cspell/dict-svelte": "^1.0.6", - "@cspell/dict-swift": "^2.0.5", - "@cspell/dict-terraform": "^1.1.0", - "@cspell/dict-typescript": "^3.2.0", - "@cspell/dict-vue": "^3.0.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/cspell-json-reporter": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.17.5.tgz", - "integrity": "sha512-+eVFCdnda74Frv8hguHYwDtxvqDuJJ/luFRl4dC5oknPMRab0JCHM1DDYjp3NzsehTex0HmcxplxqVW6QoDosg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-types": "8.17.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/cspell-pipe": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.17.5.tgz", - "integrity": "sha512-VOIfFdIo3FYQFcSpIyGkqHupOx0LgfBrWs79IKnTT1II27VUHPF+0oGq0WWf4c2Zpd8tzdHvS3IUhGarWZq69g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/cspell-resolver": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.17.5.tgz", - "integrity": "sha512-5MhYInligPbGctWxoklAKxtg+sxvtJCuRKGSQHHA0JlCOLSsducypl780P6zvpjLK59XmdfC+wtFONxSmRbsuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-directory": "^4.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/cspell-service-bus": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.17.5.tgz", - "integrity": "sha512-Ur3IK0R92G/2J6roopG9cU/EhoYAMOx2um7KYlq93cdrly8RBAK2NCcGCL7DbjQB6C9RYEAV60ueMUnQ45RrCQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/cspell-types": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.17.5.tgz", - "integrity": "sha512-91y2+0teunRSRZj940ORDA3kdjyenrUiM+4j6nQQH24sAIAJdRmQl2LG3eUTmeaSReJGkZIpnToQ6DyU5cC88Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/dict-ada": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.0.tgz", - "integrity": "sha512-7SvmhmX170gyPd+uHXrfmqJBY5qLcCX8kTGURPVeGxmt8XNXT75uu9rnZO+jwrfuU2EimNoArdVy5GZRGljGNg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-al": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.1.0.tgz", - "integrity": "sha512-PtNI1KLmYkELYltbzuoztBxfi11jcE9HXBHCpID2lou/J4VMYKJPNqe4ZjVzSI9NYbMnMnyG3gkbhIdx66VSXg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-aws": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.9.tgz", - "integrity": "sha512-bDYdnnJGwSkIZ4gzrauu7qzOs/ZAY/FnU4k11LgdMI8BhwMfsbsy2EI1iS+sD/BI5ZnNT9kU5YR3WADeNOmhRg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-bash": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.0.tgz", - "integrity": "sha512-HOyOS+4AbCArZHs/wMxX/apRkjxg6NDWdt0jF9i9XkvJQUltMwEhyA2TWYjQ0kssBsnof+9amax2lhiZnh3kCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/dict-shell": "1.1.0" - } - }, - "node_modules/@cspell/dict-companies": { - "version": "3.1.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.1.14.tgz", - "integrity": "sha512-iqo1Ce4L7h0l0GFSicm2wCLtfuymwkvgFGhmu9UHyuIcTbdFkDErH+m6lH3Ed+QuskJlpQ9dM7puMIGqUlVERw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-cpp": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.6.tgz", - "integrity": "sha512-HMV1chsExuZt5IL9rYBW7GmhNZDVdQJEd1WtFgOO6jqiNxbpTG3Is3Pkldl7FpusBQQZr4BdjMit5bnPpVRy3A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-cryptocurrencies": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.4.tgz", - "integrity": "sha512-6iFu7Abu+4Mgqq08YhTKHfH59mpMpGTwdzDB2Y8bbgiwnGFCeoiSkVkgLn1Kel2++hYcZ8vsAW/MJS9oXxuMag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-csharp": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.6.tgz", - "integrity": "sha512-w/+YsqOknjQXmIlWDRmkW+BHBPJZ/XDrfJhZRQnp0wzpPOGml7W0q1iae65P2AFRtTdPKYmvSz7AL5ZRkCnSIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-css": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.0.17.tgz", - "integrity": "sha512-2EisRLHk6X/PdicybwlajLGKF5aJf4xnX2uuG5lexuYKt05xV/J/OiBADmi8q9obhxf1nesrMQbqAt+6CsHo/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-dart": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.3.0.tgz", - "integrity": "sha512-1aY90lAicek8vYczGPDKr70pQSTQHwMFLbmWKTAI6iavmb1fisJBS1oTmMOKE4ximDf86MvVN6Ucwx3u/8HqLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-data-science": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.7.tgz", - "integrity": "sha512-XhAkK+nSW6zmrnWzusmZ1BpYLc62AWYHZc2p17u4nE2Z9XG5DleG55PCZxXQTKz90pmwlhFM9AfpkJsYaBWATA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-django": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.4.tgz", - "integrity": "sha512-fX38eUoPvytZ/2GA+g4bbdUtCMGNFSLbdJJPKX2vbewIQGfgSFJKY56vvcHJKAvw7FopjvgyS/98Ta9WN1gckg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-docker": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.12.tgz", - "integrity": "sha512-6d25ZPBnYZaT9D9An/x6g/4mk542R8bR3ipnby3QFCxnfdd6xaWiTcwDPsCgwN2aQZIQ1jX/fil9KmBEqIK/qA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-dotnet": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.9.tgz", - "integrity": "sha512-JGD6RJW5sHtO5lfiJl11a5DpPN6eKSz5M1YBa1I76j4dDOIqgZB6rQexlDlK1DH9B06X4GdDQwdBfnpAB0r2uQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-elixir": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.7.tgz", - "integrity": "sha512-MAUqlMw73mgtSdxvbAvyRlvc3bYnrDqXQrx5K9SwW8F7fRYf9V4vWYFULh+UWwwkqkhX9w03ZqFYRTdkFku6uA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-en_us": { - "version": "4.3.35", - "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.3.35.tgz", - "integrity": "sha512-HF6QNyPHkxeo/SosaZXRQlnKDUTjIzrGKyqfbw/fPPlPYrXefAZZ40ofheb5HnbUicR7xqV/lsc/HQfqYshGIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-en-common-misspellings": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.0.10.tgz", - "integrity": "sha512-80mXJLtr0tVEtzowrI7ycVae/ULAYImZUlr0kUTpa8i57AUk7Zy3pYBs44EYIKW7ZC9AHu4Qjjfq4vriAtyTDQ==", - "dev": true, - "license": "CC BY-SA 4.0" - }, - "node_modules/@cspell/dict-en-gb": { - "version": "1.1.33", - "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz", - "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-filetypes": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.11.tgz", - "integrity": "sha512-bBtCHZLo7MiSRUqx5KEiPdGOmXIlDGY+L7SJEtRWZENpAKE+96rT7hj+TUUYWBbCzheqHr0OXZJFEKDgsG/uZg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-flutter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.1.0.tgz", - "integrity": "sha512-3zDeS7zc2p8tr9YH9tfbOEYfopKY/srNsAa+kE3rfBTtQERAZeOhe5yxrnTPoufctXLyuUtcGMUTpxr3dO0iaA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-fonts": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.4.tgz", - "integrity": "sha512-cHFho4hjojBcHl6qxidl9CvUb492IuSk7xIf2G2wJzcHwGaCFa2o3gRcxmIg1j62guetAeDDFELizDaJlVRIOg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-fsharp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.1.0.tgz", - "integrity": "sha512-oguWmHhGzgbgbEIBKtgKPrFSVAFtvGHaQS0oj+vacZqMObwkapcTGu7iwf4V3Bc2T3caf0QE6f6rQfIJFIAVsw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-fullstack": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.6.tgz", - "integrity": "sha512-cSaq9rz5RIU9j+0jcF2vnKPTQjxGXclntmoNp4XB7yFX2621PxJcekGjwf/lN5heJwVxGLL9toR0CBlGKwQBgA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-gaming-terms": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.0.tgz", - "integrity": "sha512-46AnDs9XkgJ2f1Sqol1WgfJ8gOqp60fojpc9Wxch7x+BA63g4JfMV5/M5x0sI0TLlLY8EBSglcr8wQF/7C80AQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-git": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.0.4.tgz", - "integrity": "sha512-C44M+m56rYn6QCsLbiKiedyPTMZxlDdEYAsPwwlL5bhMDDzXZ3Ic8OCQIhMbiunhCOJJT+er4URmOmM+sllnjg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-golang": { - "version": "6.0.19", - "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.19.tgz", - "integrity": "sha512-VS+oinB2/CbgmHE06kMJlj52OVMZM0S2EEXph3oaroNTgTuclSwdFylQmOEjquZi55kW+n3FM9MyWXiitB7Dtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-google": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.8.tgz", - "integrity": "sha512-BnMHgcEeaLyloPmBs8phCqprI+4r2Jb8rni011A8hE+7FNk7FmLE3kiwxLFrcZnnb7eqM0agW4zUaNoB0P+z8A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-haskell": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.5.tgz", - "integrity": "sha512-s4BG/4tlj2pPM9Ha7IZYMhUujXDnI0Eq1+38UTTCpatYLbQqDwRFf2KNPLRqkroU+a44yTUAe0rkkKbwy4yRtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-html": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.11.tgz", - "integrity": "sha512-QR3b/PB972SRQ2xICR1Nw/M44IJ6rjypwzA4jn+GH8ydjAX9acFNfc+hLZVyNe0FqsE90Gw3evLCOIF0vy1vQw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-html-symbol-entities": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.3.tgz", - "integrity": "sha512-aABXX7dMLNFdSE8aY844X4+hvfK7977sOWgZXo4MTGAmOzR8524fjbJPswIBK7GaD3+SgFZ2yP2o0CFvXDGF+A==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-java": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.11.tgz", - "integrity": "sha512-T4t/1JqeH33Raa/QK/eQe26FE17eUCtWu+JsYcTLkQTci2dk1DfcIKo8YVHvZXBnuM43ATns9Xs0s+AlqDeH7w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-julia": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.1.0.tgz", - "integrity": "sha512-CPUiesiXwy3HRoBR3joUseTZ9giFPCydSKu2rkh6I2nVjXnl5vFHzOMLXpbF4HQ1tH2CNfnDbUndxD+I+7eL9w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-k8s": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.10.tgz", - "integrity": "sha512-313haTrX9prep1yWO7N6Xw4D6tvUJ0Xsx+YhCP+5YrrcIKoEw5Rtlg8R4PPzLqe6zibw6aJ+Eqq+y76Vx5BZkw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-kotlin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-kotlin/-/dict-kotlin-1.1.0.tgz", - "integrity": "sha512-vySaVw6atY7LdwvstQowSbdxjXG6jDhjkWVWSjg1XsUckyzH1JRHXe9VahZz1i7dpoFEUOWQrhIe5B9482UyJQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-latex": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.3.tgz", - "integrity": "sha512-2KXBt9fSpymYHxHfvhUpjUFyzrmN4c4P8mwIzweLyvqntBT3k0YGZJSriOdjfUjwSygrfEwiuPI1EMrvgrOMJw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-lorem-ipsum": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.4.tgz", - "integrity": "sha512-+4f7vtY4dp2b9N5fn0za/UR0kwFq2zDtA62JCbWHbpjvO9wukkbl4rZg4YudHbBgkl73HRnXFgCiwNhdIA1JPw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-lua": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.7.tgz", - "integrity": "sha512-Wbr7YSQw+cLHhTYTKV6cAljgMgcY+EUAxVIZW3ljKswEe4OLxnVJ7lPqZF5JKjlXdgCjbPSimsHqyAbC5pQN/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-makefile": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.4.tgz", - "integrity": "sha512-E4hG/c0ekPqUBvlkrVvzSoAA+SsDA9bLi4xSV3AXHTVru7Y2bVVGMPtpfF+fI3zTkww/jwinprcU1LSohI3ylw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-markdown": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.9.tgz", - "integrity": "sha512-j2e6Eg18BlTb1mMP1DkyRFMM/FLS7qiZjltpURzDckB57zDZbUyskOFdl4VX7jItZZEeY0fe22bSPOycgS1Z5A==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@cspell/dict-css": "^4.0.17", - "@cspell/dict-html": "^4.0.11", - "@cspell/dict-html-symbol-entities": "^4.0.3", - "@cspell/dict-typescript": "^3.2.0" - } - }, - "node_modules/@cspell/dict-monkeyc": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.10.tgz", - "integrity": "sha512-7RTGyKsTIIVqzbvOtAu6Z/lwwxjGRtY5RkKPlXKHEoEAgIXwfDxb5EkVwzGQwQr8hF/D3HrdYbRT8MFBfsueZw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-node": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.6.tgz", - "integrity": "sha512-CEbhPCpxGvRNByGolSBTrXXW2rJA4bGqZuTx1KKO85mwR6aadeOmUE7xf/8jiCkXSy+qvr9aJeh+jlfXcsrziQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-npm": { - "version": "5.1.31", - "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.1.31.tgz", - "integrity": "sha512-Oh9nrhgNV4UD1hlbgO3TFQqQRKziwc7qXKoQiC4oqOYIhMs2WL9Ezozku7FY1e7o5XbCIZX9nRH0ymNx/Rwj6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-php": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.0.14.tgz", - "integrity": "sha512-7zur8pyncYZglxNmqsRycOZ6inpDoVd4yFfz1pQRe5xaRWMiK3Km4n0/X/1YMWhh3e3Sl/fQg5Axb2hlN68t1g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-powershell": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.14.tgz", - "integrity": "sha512-ktjjvtkIUIYmj/SoGBYbr3/+CsRGNXGpvVANrY0wlm/IoGlGywhoTUDYN0IsGwI2b8Vktx3DZmQkfb3Wo38jBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-public-licenses": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.13.tgz", - "integrity": "sha512-1Wdp/XH1ieim7CadXYE7YLnUlW0pULEjVl9WEeziZw3EKCAw8ZI8Ih44m4bEa5VNBLnuP5TfqC4iDautAleQzQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-python": { - "version": "4.2.16", - "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.16.tgz", - "integrity": "sha512-LkQssFt1hPOWXIQiD8ScTkz/41RL7Ti0V/2ytUzEW82dc0atIEksrBg8MuOjWXktp0Dk5tDwRLgmIvhV3CFFOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/dict-data-science": "^2.0.7" - } - }, - "node_modules/@cspell/dict-r": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.1.0.tgz", - "integrity": "sha512-k2512wgGG0lTpTYH9w5Wwco+lAMf3Vz7mhqV8+OnalIE7muA0RSuD9tWBjiqLcX8zPvEJr4LdgxVju8Gk3OKyA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-ruby": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.0.8.tgz", - "integrity": "sha512-ixuTneU0aH1cPQRbWJvtvOntMFfeQR2KxT8LuAv5jBKqQWIHSxzGlp+zX3SVyoeR0kOWiu64/O5Yn836A5yMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-rust": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.0.11.tgz", - "integrity": "sha512-OGWDEEzm8HlkSmtD8fV3pEcO2XBpzG2XYjgMCJCRwb2gRKvR+XIm6Dlhs04N/K2kU+iH8bvrqNpM8fS/BFl0uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-scala": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.7.tgz", - "integrity": "sha512-yatpSDW/GwulzO3t7hB5peoWwzo+Y3qTc0pO24Jf6f88jsEeKmDeKkfgPbYuCgbE4jisGR4vs4+jfQZDIYmXPA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-shell": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.1.0.tgz", - "integrity": "sha512-D/xHXX7T37BJxNRf5JJHsvziFDvh23IF/KvkZXNSh8VqcRdod3BAz9VGHZf6VDqcZXr1VRqIYR3mQ8DSvs3AVQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-software-terms": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-4.2.5.tgz", - "integrity": "sha512-CaRzkWti3AgcXoxuRcMijaNG7YUk/MH1rHjB8VX34v3UdCxXXeqvRyElRKnxhFeVLB/robb2UdShqh/CpskxRg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-sql": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.2.0.tgz", - "integrity": "sha512-MUop+d1AHSzXpBvQgQkCiok8Ejzb+nrzyG16E8TvKL2MQeDwnIvMe3bv90eukP6E1HWb+V/MA/4pnq0pcJWKqQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-svelte": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.6.tgz", - "integrity": "sha512-8LAJHSBdwHCoKCSy72PXXzz7ulGROD0rP1CQ0StOqXOOlTUeSFaJJlxNYjlONgd2c62XBQiN2wgLhtPN+1Zv7Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-swift": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.5.tgz", - "integrity": "sha512-3lGzDCwUmnrfckv3Q4eVSW3sK3cHqqHlPprFJZD4nAqt23ot7fic5ALR7J4joHpvDz36nHX34TgcbZNNZOC/JA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-terraform": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.1.tgz", - "integrity": "sha512-07KFDwCU7EnKl4hOZLsLKlj6Zceq/IsQ3LRWUyIjvGFfZHdoGtFdCp3ZPVgnFaAcd/DKv+WVkrOzUBSYqHopQQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-typescript": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.0.tgz", - "integrity": "sha512-Pk3zNePLT8qg51l0M4g1ISowYAEGxTuNfZlgkU5SvHa9Cu7x/BWoyYq9Fvc3kAyoisCjRPyvWF4uRYrPitPDFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dict-vue": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.4.tgz", - "integrity": "sha512-0dPtI0lwHcAgSiQFx8CzvqjdoXROcH+1LyqgROCpBgppommWpVhbQ0eubnKotFEXgpUCONVkeZJ6Ql8NbTEu+w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@cspell/dynamic-import": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.17.5.tgz", - "integrity": "sha512-tY+cVkRou+0VKvH+K1NXv8/R7mOlW3BDGSs9fcgvhatj0m00Yf8blFC7tE4VVI9Qh2bkC/KDFqM24IqZbuwXUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/url": "8.17.5", - "import-meta-resolve": "^4.1.0" - }, - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@cspell/filetypes": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.17.5.tgz", - "integrity": "sha512-Fj6py2Rl+FEnMiXhRQUM1A5QmyeCLxi6dY/vQ0qfH6tp6KSaBiaC8wuPUKhr8hKyTd3+8lkUbobDhUf6xtMEXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/strong-weak-map": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.17.5.tgz", - "integrity": "sha512-Z4eo+rZJr1086wZWycBiIG/n7gGvVoqn28I7ZicS8xedRYu/4yp2loHgLn4NpxG3e46+dNWs4La6vinod+UydQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@cspell/url": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.17.5.tgz", - "integrity": "sha512-GNQqST7zI85dAFVyao6oiTeg5rNhO9FH1ZAd397qQhvwfxrrniNfuoewu8gPXyP0R4XBiiaCwhBL7w9S/F5guw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@electron/get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-3.1.0.tgz", - "integrity": "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/@electron/get/node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@electron/get/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@electron/get/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/get/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@electron/get/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.46.0", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", - "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "comment-parser": "1.4.1", - "esquery": "^1.6.0", - "jsdoc-type-pratt-parser": "~4.0.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", - "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", - "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", - "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", - "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", - "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", - "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", - "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", - "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", - "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", - "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", - "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", - "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", - "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", - "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", - "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", - "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", - "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", - "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", - "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", - "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", - "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", - "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", - "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", - "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", - "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", - "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/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/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@leichtgewicht/ip-codec": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", - "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", - "license": "MIT" - }, - "node_modules/@libp2p/crypto": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/@libp2p/crypto/-/crypto-5.0.15.tgz", - "integrity": "sha512-28xYMOn3fs8flsNgCVVxp27gEmDTtZHbz+qEVv3v7cWfGRipaVhNXFV9tQJHWXHQ8mN8v/PQvgcfCcWu5jkrTg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "@noble/curves": "^1.7.0", - "@noble/hashes": "^1.6.1", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/echo": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/@libp2p/echo/-/echo-2.1.18.tgz", - "integrity": "sha512-EBUgi7XPPeHDTLp4VlttzesIi4MbVxFq0uDYiBkLyjqsqxjKsrYwmUw9aakbWsujpN+fGp8TtAm+NeQw/Xmtcg==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "@libp2p/interface-internal": "^2.3.9", - "@multiformats/multiaddr": "^12.3.3", - "it-byte-stream": "^1.1.0", - "it-pipe": "^3.0.1" - } - }, - "node_modules/@libp2p/interface": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@libp2p/interface/-/interface-2.7.0.tgz", - "integrity": "sha512-lWmfIGzbSaw//yoEWWJh8dXNDGSCwUyXwC7P1Q6jCFWNoEtCaB1pvwOGBtri7Db/aNFZryMzN5covoq5ulldnA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.3.3", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "multiformats": "^13.3.1", - "progress-events": "^1.0.1", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/interface-compliance-tests": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@libp2p/interface-compliance-tests/-/interface-compliance-tests-6.4.2.tgz", - "integrity": "sha512-LsiOEFKvw4bIyQOC2kdbKP8/+7QoZBXR0Se45EM9YBDPWWnHnLxbRzGfqZRI3xL+WfG7vtEU4suqTk9cjr6efQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.15", - "@libp2p/echo": "^2.1.18", - "@libp2p/interface": "^2.7.0", - "@libp2p/interface-internal": "^2.3.9", - "@libp2p/logger": "^5.1.13", - "@libp2p/memory": "^1.1.4", - "@libp2p/multistream-select": "^6.0.20", - "@libp2p/peer-collections": "^6.0.25", - "@libp2p/peer-id": "^5.1.0", - "@libp2p/plaintext": "^2.0.20", - "@libp2p/utils": "^6.6.0", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "abortable-iterator": "^5.1.0", - "aegir": "^45.1.1", - "any-signal": "^4.1.1", - "delay": "^6.0.0", - "it-all": "^3.0.6", - "it-byte-stream": "^1.1.0", - "it-drain": "^3.0.7", - "it-map": "^3.1.1", - "it-ndjson": "^1.0.7", - "it-pair": "^2.0.6", - "it-pipe": "^3.0.1", - "it-protobuf-stream": "^1.1.5", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "it-to-buffer": "^4.0.7", - "libp2p": "^2.8.2", - "merge-options": "^3.0.4", - "p-defer": "^4.0.1", - "p-event": "^6.0.1", - "p-limit": "^6.1.0", - "p-retry": "^6.2.1", - "p-wait-for": "^5.0.2", - "protons-runtime": "^5.5.0", - "race-signal": "^1.1.0", - "sinon": "^19.0.2", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/interface-compliance-tests/node_modules/sinon": { - "version": "19.0.5", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.5.tgz", - "integrity": "sha512-r15s9/s+ub/d4bxNXqIUmwp6imVSdTorIRaxoecYjqTVLZ8RuoXr/4EDGwIBo6Waxn7f2gnURX9zuhAfCwaF6Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "nise": "^6.1.1", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/@libp2p/interface-internal": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@libp2p/interface-internal/-/interface-internal-2.3.9.tgz", - "integrity": "sha512-1hW/yHktO3txc+r4ASmVA9GbNN6ZoGnH8Bt9VrYwY580BT53TP3eipn3Bo1XyGBDtmV6bpQiKhFK5AYVbhnz0g==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "@libp2p/peer-collections": "^6.0.25", - "@multiformats/multiaddr": "^12.3.3", - "progress-events": "^1.0.1" - } - }, - "node_modules/@libp2p/logger": { - "version": "5.1.13", - "resolved": "https://registry.npmjs.org/@libp2p/logger/-/logger-5.1.13.tgz", - "integrity": "sha512-JKyMlySG8T+LpItsj9Vma57yap/A0HqJ8ZdaHvgdoThhSOfqcRs8oRWO/2EG0Q5hUXugw//EAT+Ptj8MyNdbjQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "multiformats": "^13.3.1", - "weald": "^1.0.4" - } - }, - "node_modules/@libp2p/memory": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@libp2p/memory/-/memory-1.1.4.tgz", - "integrity": "sha512-DOSrdjsZMiRrYcOMlfDWeH8ln5/9SpURUe3h5XP17O+Ojcer4eQu8sRm9csS47xoaOyrmurMhmrdovZS93G54g==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "@multiformats/multiaddr": "^12.3.3", - "@multiformats/multiaddr-matcher": "^1.6.0", - "@types/sinon": "^17.0.3", - "delay": "^6.0.0", - "it-map": "^3.1.1", - "it-pushable": "^3.2.3", - "nanoid": "^5.0.9", - "race-signal": "^1.1.3", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/@libp2p/multistream-select": { - "version": "6.0.20", - "resolved": "https://registry.npmjs.org/@libp2p/multistream-select/-/multistream-select-6.0.20.tgz", - "integrity": "sha512-DHObPodBZXNUFiMzMX0KSnkbDM6am4G8GfkfYPpmx+yuleuutiJrmN95Xt9ximhn9m+YtEZWB2Je8+Lb0bwIYQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "it-length-prefixed": "^10.0.1", - "it-length-prefixed-stream": "^1.2.0", - "it-stream-types": "^2.0.2", - "p-defer": "^4.0.1", - "race-signal": "^1.1.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/peer-collections": { - "version": "6.0.25", - "resolved": "https://registry.npmjs.org/@libp2p/peer-collections/-/peer-collections-6.0.25.tgz", - "integrity": "sha512-sU6mjwANQvVPgTgslRZvxZ6cYzQJ66QmNHm6mrM0cx03Yf1heWnvL28N/P781nGsUjo1cJD7xB5ctAGk6A/lXw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/interface": "^2.7.0", - "@libp2p/peer-id": "^5.1.0", - "@libp2p/utils": "^6.6.0", - "multiformats": "^13.3.1" - } - }, - "node_modules/@libp2p/peer-id": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-5.1.0.tgz", - "integrity": "sha512-9Xob9DDg1uBboM2QvJ5nyPbsjxsNS9obmGAYeAtLSx5aHAIC4AweJQFHssUUCfW7mufkzX/s3zyR62XPR4SYyQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "multiformats": "^13.3.1", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/peer-record": { - "version": "8.0.25", - "resolved": "https://registry.npmjs.org/@libp2p/peer-record/-/peer-record-8.0.25.tgz", - "integrity": "sha512-IFuAhxzMS/NlXZS7+vn7tTJY32ODtKN/aFBRd1wekAw5DebGtvqkt9mN3UbeXJPesu9w87e4Q8GSarD0URXRlw==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "@libp2p/peer-id": "^5.1.0", - "@libp2p/utils": "^6.6.0", - "@multiformats/multiaddr": "^12.3.3", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/peer-store": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/@libp2p/peer-store/-/peer-store-11.1.2.tgz", - "integrity": "sha512-2egfDs6j+uvreBrzChf5xwNe0kQgYhuaOBx3rVgCAHxuJyXK6/lK+PpEH3Cfgad+if388mII58MU5gzpbawsaw==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "@libp2p/peer-id": "^5.1.0", - "@libp2p/peer-record": "^8.0.25", - "@multiformats/multiaddr": "^12.3.3", - "interface-datastore": "^8.3.1", - "it-all": "^3.0.6", - "mortice": "^3.0.6", - "multiformats": "^13.3.1", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/plaintext": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/@libp2p/plaintext/-/plaintext-2.0.20.tgz", - "integrity": "sha512-nkmoELzjaLisOZ4ok3PUyj+RuJUhD+9Chp9fOENpdEFiFDex9mqH62tZ5Hw1ZKrN4F3jDMY9pDbQk0yHS3MlwA==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "@libp2p/peer-id": "^5.1.0", - "it-protobuf-stream": "^1.1.5", - "it-stream-types": "^2.0.2", - "protons-runtime": "^5.5.0", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@libp2p/utils": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/@libp2p/utils/-/utils-6.6.0.tgz", - "integrity": "sha512-QjS1+r+jInOxULjdATBc1N/gorUWUoJqEKxpqTcB2wOwCipzB58RYR3n3QPeoRHj1mVMhZujE1dTbmK/Nafhqg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@chainsafe/netmask": "^2.0.0", - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "@libp2p/logger": "^5.1.13", - "@multiformats/multiaddr": "^12.3.3", - "@sindresorhus/fnv1a": "^3.1.0", - "any-signal": "^4.1.1", - "delay": "^6.0.0", - "get-iterator": "^2.0.1", - "is-loopback-addr": "^2.0.2", - "it-foreach": "^2.1.1", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "it-stream-types": "^2.0.2", - "netmask": "^2.0.2", - "p-defer": "^4.0.1", - "race-event": "^1.3.0", - "race-signal": "^1.1.2", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/@multiformats/dns": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@multiformats/dns/-/dns-1.0.6.tgz", - "integrity": "sha512-nt/5UqjMPtyvkG9BQYdJ4GfLK3nMqGpFZOzf4hAmIa0sJh2LlS9YKXZ4FgwBDsaHvzZqR/rUFIywIc7pkHNNuw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@types/dns-packet": "^5.6.5", - "buffer": "^6.0.3", - "dns-packet": "^5.6.1", - "hashlru": "^2.3.0", - "p-queue": "^8.0.1", - "progress-events": "^1.0.0", - "uint8arrays": "^5.0.2" - } - }, - "node_modules/@multiformats/multiaddr": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr/-/multiaddr-12.4.0.tgz", - "integrity": "sha512-FL7yBTLijJ5JkO044BGb2msf+uJLrwpD6jD6TkXlbjA9N12+18HT40jvd4o5vL4LOJMc86dPX6tGtk/uI9kYKg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@chainsafe/netmask": "^2.0.0", - "@multiformats/dns": "^1.0.3", - "multiformats": "^13.0.0", - "uint8-varint": "^2.0.1", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/@multiformats/multiaddr-matcher": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-matcher/-/multiaddr-matcher-1.6.0.tgz", - "integrity": "sha512-E77lLvQR+50kTAfvjV3g4wr9qCu77Z+6yT0s1hgfh8B4sAXZ8u/YdQJGhjgstgW1kmGy7BXPppROKYijqQsesQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.1", - "@multiformats/multiaddr": "^12.0.0", - "multiformats": "^13.0.0" - } - }, - "node_modules/@multiformats/multiaddr-to-uri": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@multiformats/multiaddr-to-uri/-/multiaddr-to-uri-11.0.0.tgz", - "integrity": "sha512-9RNmlIGwZbBLsHekT50dbt4o4u8Iciw9kGjv+WHiGxQdsJ6xKKjU1+C0Vbas6RilMbaVOAOnEyfNcXbUmTkLxQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@multiformats/multiaddr": "^12.3.0" - } - }, - "node_modules/@noble/curves": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", - "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.7.1" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", - "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/auth-token": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz", - "integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/core": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.4.tgz", - "integrity": "sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^5.0.0", - "@octokit/graphql": "^8.1.2", - "@octokit/request": "^9.2.1", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2", - "before-after-hook": "^3.0.2", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/endpoint": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz", - "integrity": "sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^13.6.2", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/graphql": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.1.tgz", - "integrity": "sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request": "^9.2.2", - "@octokit/types": "^13.8.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "24.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", - "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "11.6.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz", - "integrity": "sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^13.10.0" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-retry": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.0.tgz", - "integrity": "sha512-psMbEYb/Fh+V+ZaFo8J16QiFz4sVTv3GntCSU+hYqzHiMdc3P+hhHLVv+dJt0PGIPAGoIA5u+J2DCJdK6lEPsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-throttling": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-9.6.0.tgz", - "integrity": "sha512-zn7m1N3vpJDaVzLqjCRdJ0cRzNiekHEWPi8Ww9xyPNrDt5PStHvVE0eR8wy4RSU8Eg7YO8MHyvn6sv25EGVhhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^13.7.0", - "bottleneck": "^2.15.3" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "@octokit/core": "^6.1.3" - } - }, - "node_modules/@octokit/request": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz", - "integrity": "sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^10.1.3", - "@octokit/request-error": "^6.1.7", - "@octokit/types": "^13.6.2", - "fast-content-type-parse": "^2.0.0", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/request-error": { - "version": "6.1.7", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", - "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^13.6.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@octokit/types": { - "version": "13.10.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", - "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^24.2.0" - } - }, - "node_modules/@phenomnomnominal/tsquery": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz", - "integrity": "sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esquery": "^1.4.0" - }, - "peerDependencies": { - "typescript": "^3 || ^4 || ^5" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", - "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "4.2.10" - }, - "engines": { - "node": ">=12.22.0" - } - }, - "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "dev": true, - "license": "ISC" - }, - "node_modules/@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@polka/send-type": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/@polka/send-type/-/send-type-0.5.2.tgz", - "integrity": "sha512-jGXalKihnhGQmMQ+xxfxrRfI2cWs38TIZuwgYpnbQDD4r9TkOiU3ocjAS+6CqqMNQNAu9Ul2iHU5YFRDODak2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@polka/url": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-0.5.0.tgz", - "integrity": "sha512-oZLYFEAzUKyi3SKnXvj32ZCEGH6RDnao7COuCVhDydMS9NrCSVXhM79VaKyP5+Zc33m0QXEd2DN3UkU7OsHcfw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@samverschueren/stream-to-observable": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", - "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-observable": "^0.3.0" - }, - "engines": { - "node": ">=6" - }, - "peerDependenciesMeta": { - "rxjs": { - "optional": true - }, - "zen-observable": { - "optional": true - } - } - }, - "node_modules/@sec-ant/readable-stream": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", - "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@semantic-release/changelog": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.3.tgz", - "integrity": "sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "fs-extra": "^11.0.0", - "lodash": "^4.17.4" - }, - "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "semantic-release": ">=18.0.0" - } - }, - "node_modules/@semantic-release/commit-analyzer": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-13.0.1.tgz", - "integrity": "sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-changelog-angular": "^8.0.0", - "conventional-changelog-writer": "^8.0.0", - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.0.0", - "debug": "^4.0.0", - "import-from-esm": "^2.0.0", - "lodash-es": "^4.17.21", - "micromatch": "^4.0.2" - }, - "engines": { - "node": ">=20.8.1" - }, - "peerDependencies": { - "semantic-release": ">=20.1.0" - } - }, - "node_modules/@semantic-release/error": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", - "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.17" - } - }, - "node_modules/@semantic-release/git": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", - "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@semantic-release/error": "^3.0.0", - "aggregate-error": "^3.0.0", - "debug": "^4.0.0", - "dir-glob": "^3.0.0", - "execa": "^5.0.0", - "lodash": "^4.17.4", - "micromatch": "^4.0.0", - "p-reduce": "^2.0.0" - }, - "engines": { - "node": ">=14.17" - }, - "peerDependencies": { - "semantic-release": ">=18.0.0" - } - }, - "node_modules/@semantic-release/git/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@semantic-release/git/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/git/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/@semantic-release/git/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/git/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/git/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@semantic-release/git/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/git/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/@semantic-release/git/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@semantic-release/github": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.1.tgz", - "integrity": "sha512-Z9cr0LgU/zgucbT9cksH0/pX9zmVda9hkDPcgIE0uvjMQ8w/mElDivGjx1w1pEQ+MuQJ5CBq3VCF16S6G4VH3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/core": "^6.0.0", - "@octokit/plugin-paginate-rest": "^11.0.0", - "@octokit/plugin-retry": "^7.0.0", - "@octokit/plugin-throttling": "^9.0.0", - "@semantic-release/error": "^4.0.0", - "aggregate-error": "^5.0.0", - "debug": "^4.3.4", - "dir-glob": "^3.0.1", - "globby": "^14.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.0", - "issue-parser": "^7.0.0", - "lodash-es": "^4.17.21", - "mime": "^4.0.0", - "p-filter": "^4.0.0", - "url-join": "^5.0.0" - }, - "engines": { - "node": ">=20.8.1" - }, - "peerDependencies": { - "semantic-release": ">=24.1.0" - } - }, - "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", - "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@semantic-release/github/node_modules/aggregate-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", - "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^5.2.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/github/node_modules/clean-stack": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", - "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/github/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/github/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-12.0.1.tgz", - "integrity": "sha512-/6nntGSUGK2aTOI0rHPwY3ZjgY9FkXmEHbW9Kr+62NVOsyqpKKeP0lrCH+tphv+EsNdJNmqqwijTEnVWUMQ2Nw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@semantic-release/error": "^4.0.0", - "aggregate-error": "^5.0.0", - "execa": "^9.0.0", - "fs-extra": "^11.0.0", - "lodash-es": "^4.17.21", - "nerf-dart": "^1.0.0", - "normalize-url": "^8.0.0", - "npm": "^10.5.0", - "rc": "^1.2.8", - "read-pkg": "^9.0.0", - "registry-auth-token": "^5.0.0", - "semver": "^7.1.2", - "tempy": "^3.0.0" - }, - "engines": { - "node": ">=20.8.1" - }, - "peerDependencies": { - "semantic-release": ">=20.1.0" - } - }, - "node_modules/@semantic-release/npm/node_modules/@semantic-release/error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", - "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@semantic-release/npm/node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/aggregate-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", - "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^5.2.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/clean-stack": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", - "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/execa": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.3", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.0", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/@semantic-release/npm/node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/human-signals": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", - "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@semantic-release/npm/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/npm/node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@semantic-release/release-notes-generator": { - "version": "14.0.3", - "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.3.tgz", - "integrity": "sha512-XxAZRPWGwO5JwJtS83bRdoIhCiYIx8Vhr+u231pQAsdFIAbm19rSVJLdnBN+Avvk7CKvNQE/nJ4y7uqKH6WTiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-changelog-angular": "^8.0.0", - "conventional-changelog-writer": "^8.0.0", - "conventional-commits-filter": "^5.0.0", - "conventional-commits-parser": "^6.0.0", - "debug": "^4.0.0", - "get-stream": "^7.0.0", - "import-from-esm": "^2.0.0", - "into-stream": "^7.0.0", - "lodash-es": "^4.17.21", - "read-package-up": "^11.0.0" - }, - "engines": { - "node": ">=20.8.1" - }, - "peerDependencies": { - "semantic-release": ">=20.1.0" - } - }, - "node_modules/@sindresorhus/fnv1a": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/fnv1a/-/fnv1a-3.1.0.tgz", - "integrity": "sha512-KV321z5m/0nuAg83W1dPLy85HpHDk7Sdi4fJbwvacWsEhAh+rZUW4ZfGcXmUIvjZg4ss2bcwNlRhJ7GBEUG08w==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/commons/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", - "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/chai": { - "version": "4.3.20", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", - "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/chai-as-promised": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", - "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/chai": "*" - } - }, - "node_modules/@types/chai-string": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@types/chai-string/-/chai-string-1.4.5.tgz", - "integrity": "sha512-IecXRMSnpUvRnTztdpSdjcmcW7EdNme65bfDCQMi7XrSEPGmyDYYTEfc5fcactWDA6ioSm8o7NUqg9QxjBCCEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/chai": "*" - } - }, - "node_modules/@types/chai-subset": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.6.tgz", - "integrity": "sha512-m8lERkkQj+uek18hXOZuec3W/fCRTrU4hrnXjH3qhHy96ytuPaPiWGgu7sJb7tZxZonO75vYAjCvpe/e4VUwRw==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/chai": "<5.2.0" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/dns-packet": { - "version": "5.6.5", - "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.6.5.tgz", - "integrity": "sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.13.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.13.tgz", - "integrity": "sha512-ClsL5nMwKaBRwPcCvH8E7+nU4GxHVx1axNvMZTFHMEfNI7oahimt26P5zjVCRrjiIWj6YFXfE1v3dEp94wLcGQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/parse-json": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", - "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/retry": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", - "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sinon": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.4.tgz", - "integrity": "sha512-RHnIrhfPO3+tJT0s7cFaXGZvsL4bbR3/k7z3P312qMS4JaS2Tk+KiwiLx1S0rQ56ERj00u1/BtdyVd0FY+Pdew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/sinonjs__fake-timers": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", - "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/strip-json-comments": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz", - "integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", - "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/utils": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true, - "license": "ISC" - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", - "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.13", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", - "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.13", - "@vue/shared": "3.5.13" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", - "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.13", - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.48", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", - "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/shared": "3.5.13" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", - "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/abort-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/abort-error/-/abort-error-1.0.1.tgz", - "integrity": "sha512-fxqCblJiIPdSXIUrxI0PL+eJG49QdP9SQ70qtB65MVAoMr2rASlOyAbJFOylfB467F/f+5BCLJJq58RYi7mGfg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/abortable-iterator": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/abortable-iterator/-/abortable-iterator-5.1.0.tgz", - "integrity": "sha512-a3nRG0GOGw3IPFA2hdhrZU+QuD3mA6i+5f4YM/Obe+D5lYccxScI32rAIHAW5ttFV7+beiof09gHav4qUEZDwg==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "get-iterator": "^2.0.0", - "it-stream-types": "^2.0.1" - } - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-loose": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/acorn-loose/-/acorn-loose-8.4.0.tgz", - "integrity": "sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", - "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn": "^8.11.0" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/aegir": { - "version": "45.1.4", - "resolved": "https://registry.npmjs.org/aegir/-/aegir-45.1.4.tgz", - "integrity": "sha512-xS+AW251ok7GySAii4flQpQL3qdoGJdr2VJ3j5De84iAuDMPVi/eVxlVP3AmtQ22xcujUhUD3UgbZqgq7QlkCQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@electron/get": "^3.0.0", - "@polka/send-type": "^0.5.2", - "@semantic-release/changelog": "^6.0.1", - "@semantic-release/commit-analyzer": "^13.0.0", - "@semantic-release/git": "^10.0.1", - "@semantic-release/github": "^11.0.0", - "@semantic-release/npm": "^12.0.0", - "@semantic-release/release-notes-generator": "^14.0.0", - "@types/chai": "^4.2.16", - "@types/chai-as-promised": "^7.1.3", - "@types/chai-string": "^1.4.2", - "@types/chai-subset": "^1.3.3", - "@types/mocha": "^10.0.0", - "@types/node": "^22.10.7", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "buffer": "^6.0.3", - "bytes": "^3.1.0", - "c8": "^10.1.2", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.1", - "chai-bites": "^0.1.2", - "chai-parentheses": "^0.0.2", - "chai-string": "^1.5.0", - "chai-subset": "^1.6.0", - "conventional-changelog-conventionalcommits": "^8.0.0", - "cors": "^2.8.5", - "cspell": "^8.17.5", - "depcheck": "^1.4.3", - "diff": "^7.0.0", - "electron-mocha": "^13.0.0", - "env-paths": "^3.0.0", - "esbuild": "^0.25.0", - "eslint": "^8.31.0", - "eslint-config-ipfs": "^7.0.0", - "eslint-plugin-etc": "^2.0.2", - "eslint-plugin-import": "^2.18.0", - "eslint-plugin-jsdoc": "^48.9.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^6.1.1", - "execa": "^8.0.1", - "extract-zip": "^2.0.1", - "fast-glob": "^3.3.2", - "fs-extra": "^11.1.0", - "gh-pages": "^6.0.0", - "globby": "^14.0.0", - "is-plain-obj": "^4.1.0", - "kleur": "^4.1.4", - "latest-version": "^9.0.0", - "lilconfig": "^3.0.0", - "listr": "~0.14.2", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm": "^3.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-extension-gfm": "^3.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.1", - "mocha": "^11.0.1", - "npm-package-json-lint": "^8.0.0", - "nyc": "^17.0.0", - "p-map": "^7.0.1", - "p-queue": "^8.0.1", - "p-retry": "^6.0.0", - "pascalcase": "^2.0.0", - "path": "^0.12.7", - "playwright-test": "^14.0.0", - "polka": "^0.5.2", - "prompt": "^1.2.2", - "proper-lockfile": "^4.1.2", - "react-native-test-runner": "^5.0.0", - "read-pkg-up": "^11.0.0", - "rimraf": "^6.0.1", - "semantic-release": "^24.0.0", - "semantic-release-monorepo": "^8.0.2", - "semver": "^7.3.8", - "source-map-support": "^0.5.20", - "strip-bom": "^5.0.0", - "strip-json-comments": "^5.0.0", - "strong-log-transformer": "^2.1.0", - "tempy": "^3.1.0", - "typedoc": "^0.25.0", - "typedoc-plugin-mdn-links": "^3.0.3", - "typedoc-plugin-missing-exports": "^2.0.0", - "typescript": "^5.1.6", - "typescript-docs-verifier": "^2.5.0", - "wherearewe": "^2.0.1", - "yargs": "^17.1.1", - "yargs-parser": "^21.1.1" - }, - "bin": { - "aegir": "src/index.js" - } - }, - "node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": ">=5.0.0" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-sequence-parser": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.3.tgz", - "integrity": "sha512-+fksAx9eG3Ab6LDnLs3ZqZa8KVJ/jYnX+D4Qe1azX+LFGFAXqynCQLOdLpNYN/l9e7l6hMWwZbrnctqr6eSQSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/any-observable/-/any-observable-0.3.0.tgz", - "integrity": "sha512-/FQM1EDkTsf63Ub2C6O7GuYFDsSXUwsaZDurV0np41ocwq0jthUAYCmhBX9f+KwlaCgIuWyr/4WlUQUBfKfZog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/any-signal": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/any-signal/-/any-signal-4.1.1.tgz", - "integrity": "sha512-iADenERppdC+A2YKbOXXB2WUeABLaM6qnpZ70kZbPZ1cZMMJ7eF+3CaYm+/PhBizgkzlvssC7QuHS30oOiQYWA==", - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true, - "license": "MIT" - }, - "node_modules/are-docs-informative": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", - "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/argv-formatter": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", - "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-differ": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", - "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-timsort": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", - "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/array.prototype.findlastindex": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", - "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-shim-unscopables": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/assert": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", - "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.2", - "is-nan": "^1.3.2", - "object-is": "^1.1.5", - "object.assign": "^4.1.4", - "util": "^0.12.5" - } - }, - "node_modules/assert/node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", - "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.4", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", - "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3", - "core-js-compat": "^3.40.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", - "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.4" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-transform-inline-environment-variables": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-environment-variables/-/babel-plugin-transform-inline-environment-variables-0.4.4.tgz", - "integrity": "sha512-bJILBtn5a11SmtR2j/3mBOjX4K3weC6cq+NNZ7hG22wCAqpc3qtj/iN7dSe9HDiS46lgp1nHsQgeYrea/RUe+g==", - "dev": true, - "license": "MIT" - }, - "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==", - "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/before-after-hook": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz", - "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bl/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", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/bl/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", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/bottleneck": { - "version": "2.19.5", - "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", - "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC" - }, - "node_modules/browserslist": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", - "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "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", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "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-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/builtins": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.1.0.tgz", - "integrity": "sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.0.0" - } - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/c8": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.3.tgz", - "integrity": "sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@bcoe/v8-coverage": "^1.0.1", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^3.1.1", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.1.6", - "test-exclude": "^7.0.1", - "v8-to-istanbul": "^9.0.0", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "monocart-coverage-reports": "^2" - }, - "peerDependenciesMeta": { - "monocart-coverage-reports": { - "optional": true - } - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001707", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001707.tgz", - "integrity": "sha512-3qtRjw/HQSMlDWf+X79N206fepf4SOOU6SQLMaq/0KkZLmSjPxAkBOQQ+FxbHKfHmYLZFfdWsO3KA90ceHPSnw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chai-as-promised": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", - "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", - "dev": true, - "license": "WTFPL", - "dependencies": { - "check-error": "^1.0.2" - }, - "peerDependencies": { - "chai": ">= 2.1.2 < 6" - } - }, - "node_modules/chai-bites": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/chai-bites/-/chai-bites-0.1.2.tgz", - "integrity": "sha512-eZVKGTywFkRuMle/UkiT9OXU4y4WeNy0yKe2t5iclIW3Yn9X3l7iWZoSeTjTpeQ1SIMn3In0rctjVCaRuKCmng==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "chai": ">=2 <5" - } - }, - "node_modules/chai-parentheses": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/chai-parentheses/-/chai-parentheses-0.0.2.tgz", - "integrity": "sha512-pdBOsH31vzWKYHr8JYTlsP+TFx7RTTm/2hQYbpxFd1WQ/X58ryrLBINRL2C1OWje8bi42NQqNZl2RooFPrsBqA==", - "dev": true, - "license": "MIT" - }, - "node_modules/chai-string": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/chai-string/-/chai-string-1.6.0.tgz", - "integrity": "sha512-sXV7whDmpax+8H++YaZelgin7aur1LGf9ZhjZa3ojETFJ0uPVuS4XEXuIagpZ/c8uVOtsSh4MwOjy5CBLjJSXA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "chai": "^4.1.2" - } - }, - "node_modules/chai-subset": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/chai-subset/-/chai-subset-1.6.0.tgz", - "integrity": "sha512-K3d+KmqdS5XKW5DWPd5sgNffL3uxdDe+6GdnJh3AYPhwnBGRY5urfvfcbRtWIvvpz+KxkL9FeBB6MZewLUNwug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk-template": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.0.tgz", - "integrity": "sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/clear-module": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", - "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^2.0.0", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-highlight": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", - "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", - "dev": true, - "license": "ISC", - "dependencies": { - "chalk": "^4.0.0", - "highlight.js": "^10.7.1", - "mz": "^2.4.0", - "parse5": "^5.1.1", - "parse5-htmlparser2-tree-adapter": "^6.0.0", - "yargs": "^16.0.0" - }, - "bin": { - "highlight": "bin/highlight" - }, - "engines": { - "node": ">=8.0.0", - "npm": ">=5.0.0" - } - }, - "node_modules/cli-highlight/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cli-highlight/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cli-highlight/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-highlight/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/cli-highlight/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cli-highlight/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", - "integrity": "sha512-f4r4yJnbT++qUPI9NR4XLDLq41gQ+uqnPItWG0F5ZkehuNiTTa3EY0S4AqTSUOeJ7/zU41oWPQSNkW5BqPL9bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "0.0.4", - "string-width": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/comment-json": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", - "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-timsort": "^1.0.3", - "core-util-is": "^1.0.3", - "esprima": "^4.0.1", - "has-own-prop": "^2.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/comment-parser": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", - "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, - "license": "MIT" - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "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/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/config-chain/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" - }, - "node_modules/conventional-changelog-angular": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-8.0.0.tgz", - "integrity": "sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-8.0.0.tgz", - "integrity": "sha512-eOvlTO6OcySPyyyk8pKz2dP4jjElYunj9hn9/s0OB+gapTO8zwS9UQWrZ1pmF2hFs3vw1xhonOLGcGjy/zgsuA==", - "dev": true, - "license": "ISC", - "dependencies": { - "compare-func": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-changelog-writer": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-8.0.1.tgz", - "integrity": "sha512-hlqcy3xHred2gyYg/zXSMXraY2mjAYYo0msUCpK+BGyaVJMFCKWVXPIHiaacGO2GGp13kvHWXFhYmxT4QQqW3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "conventional-commits-filter": "^5.0.0", - "handlebars": "^4.7.7", - "meow": "^13.0.0", - "semver": "^7.5.2" - }, - "bin": { - "conventional-changelog-writer": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-commits-filter": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-5.0.0.tgz", - "integrity": "sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/conventional-commits-parser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-6.1.0.tgz", - "integrity": "sha512-5nxDo7TwKB5InYBl4ZC//1g9GRwB/F3TXOGR9hgUjMGfvSP4Vu5NkpNro2+1+TIEy1vwxApl5ircECr2ri5JIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "meow": "^13.0.0" - }, - "bin": { - "conventional-commits-parser": "dist/cli/index.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/convert-hrtime": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz", - "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/copy-file": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/copy-file/-/copy-file-11.0.0.tgz", - "integrity": "sha512-mFsNh/DIANLqFt5VHZoGirdg7bK5+oTWlhnGu6tgRhzBlnEKWaPX2xrFaLltii/6rmhqFMJqffUgknuRdpYlHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.11", - "p-event": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/core-js-compat": { - "version": "3.41.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", - "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.24.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cosmiconfig": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", - "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cosmiconfig/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/cpy": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/cpy/-/cpy-11.1.0.tgz", - "integrity": "sha512-QGHetPSSuprVs+lJmMDcivvrBwTKASzXQ5qxFvRC2RFESjjod71bDvFvhxTjDgkNjrrb72AI6JPjfYwxrIy33A==", - "dev": true, - "license": "MIT", - "dependencies": { - "copy-file": "^11.0.0", - "globby": "^14.0.2", - "junk": "^4.0.1", - "micromatch": "^4.0.7", - "p-filter": "^4.1.0", - "p-map": "^7.0.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cspell": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.17.5.tgz", - "integrity": "sha512-l3Cfp87d7Yrodem675irdxV6+7+OsdR+jNwYHe33Dgnd6ePEfooYrvmfGdXF9rlQrNLUQp/HqYgHJzSq19UEsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-json-reporter": "8.17.5", - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "@cspell/dynamic-import": "8.17.5", - "@cspell/url": "8.17.5", - "chalk": "^5.4.1", - "chalk-template": "^1.1.0", - "commander": "^13.1.0", - "cspell-dictionary": "8.17.5", - "cspell-gitignore": "8.17.5", - "cspell-glob": "8.17.5", - "cspell-io": "8.17.5", - "cspell-lib": "8.17.5", - "fast-json-stable-stringify": "^2.1.0", - "file-entry-cache": "^9.1.0", - "get-stdin": "^9.0.0", - "semver": "^7.7.1", - "tinyglobby": "^0.2.12" - }, - "bin": { - "cspell": "bin.mjs", - "cspell-esm": "bin.mjs" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" - } - }, - "node_modules/cspell-config-lib": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.17.5.tgz", - "integrity": "sha512-XDc+UJO5RZ9S9e2Ajz332XjT7dv6Og2UqCiSnAlvHt7t/MacLHSPARZFIivheObNkWZ7E1iWI681RxKoH4o40w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-types": "8.17.5", - "comment-json": "^4.2.5", - "yaml": "^2.7.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-dictionary": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.17.5.tgz", - "integrity": "sha512-O/Uuhv1RuDu+5WYQml0surudweaTvr+2YJSmPSdlihByUSiogCbpGqwrRow7wQv/C5p1W1FlFjotvUfoR0fxHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "cspell-trie-lib": "8.17.5", - "fast-equals": "^5.2.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-gitignore": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.17.5.tgz", - "integrity": "sha512-I27fgOUZzH14jeIYo65LooB60fZ42f6OJL1lOR9Mk6IrIlDyUtzherGR+xx5KshK2katYkX42Qu4zsVYM6VFPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/url": "8.17.5", - "cspell-glob": "8.17.5", - "cspell-io": "8.17.5", - "find-up-simple": "^1.0.0" - }, - "bin": { - "cspell-gitignore": "bin.mjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-glob": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.17.5.tgz", - "integrity": "sha512-OXquou7UykInlGV5et5lNKYYrW0dwa28aEF995x1ocANND7o0bbHmFlbgyci/Lp4uFQai8sifmfFJbuIg2IC/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/url": "8.17.5", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-grammar": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.17.5.tgz", - "integrity": "sha512-st2n+FVw25MvMbsGb3TeJNRr6Oih4g14rjOd/UJN0qn+ceH360SAShUFqSd4kHHu2ADazI/TESFU6FRtMTPNOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5" - }, - "bin": { - "cspell-grammar": "bin.mjs" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-io": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.17.5.tgz", - "integrity": "sha512-oevM/8l0s6nc1NCYPqNFumrW50QSHoa6wqUT8cWs09gtZdE2AWG0U6bIE8ZEVz6e6FxS+6IenGKTdUUwP0+3fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-service-bus": "8.17.5", - "@cspell/url": "8.17.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-lib": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.17.5.tgz", - "integrity": "sha512-S3KuOrcST1d2BYmTXA+hnbRdho5n3w5GUvEaCx3QZQBwAPfLpAwJbe2yig1TxBpyEJ5LqP02i/mDg1pUCOP0hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-bundled-dicts": "8.17.5", - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-resolver": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "@cspell/dynamic-import": "8.17.5", - "@cspell/filetypes": "8.17.5", - "@cspell/strong-weak-map": "8.17.5", - "@cspell/url": "8.17.5", - "clear-module": "^4.1.2", - "comment-json": "^4.2.5", - "cspell-config-lib": "8.17.5", - "cspell-dictionary": "8.17.5", - "cspell-glob": "8.17.5", - "cspell-grammar": "8.17.5", - "cspell-io": "8.17.5", - "cspell-trie-lib": "8.17.5", - "env-paths": "^3.0.0", - "fast-equals": "^5.2.2", - "gensequence": "^7.0.0", - "import-fresh": "^3.3.1", - "resolve-from": "^5.0.0", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-uri": "^3.1.0", - "xdg-basedir": "^5.1.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cspell-trie-lib": { - "version": "8.17.5", - "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.17.5.tgz", - "integrity": "sha512-9hjI3nRQxtGEua6CgnLbK3sGHLx9dXR/BHwI/csRL4dN5GGRkE5X3CCoy1RJVL7iGFLIzi43+L10xeFRmWniKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspell/cspell-pipe": "8.17.5", - "@cspell/cspell-types": "8.17.5", - "gensequence": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/datastore-core": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/datastore-core/-/datastore-core-10.0.2.tgz", - "integrity": "sha512-B3WXxI54VxJkpXxnYibiF17si3bLXE1XOjrJB7wM5co9fx2KOEkiePDGiCCEtnapFHTnmAnYCPdA7WZTIpdn/A==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@libp2p/logger": "^5.0.1", - "interface-datastore": "^8.0.0", - "interface-store": "^6.0.0", - "it-drain": "^3.0.7", - "it-filter": "^3.1.1", - "it-map": "^3.1.1", - "it-merge": "^3.0.5", - "it-pipe": "^3.0.1", - "it-pushable": "^3.2.3", - "it-sort": "^3.0.6", - "it-take": "^3.0.6" - } - }, - "node_modules/date-fns": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", - "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", - "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "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", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/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", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", - "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-require-extensions/node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/del": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", - "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", - "dev": true, - "license": "MIT", - "dependencies": { - "globby": "^11.0.1", - "graceful-fs": "^4.2.4", - "is-glob": "^4.0.1", - "is-path-cwd": "^2.2.0", - "is-path-inside": "^3.0.2", - "p-map": "^4.0.0", - "rimraf": "^3.0.2", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/del/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/del/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/del/node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/del/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/del/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/delay": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-6.0.0.tgz", - "integrity": "sha512-2NJozoOHQ4NuZuVIr5CWd0iiLVIRSDepakaovIN+9eIDHEhdCAEvSy2cuf1DCrPPQLvHmbqTHODlhHg8UCy4zw==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/depcheck": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/depcheck/-/depcheck-1.4.7.tgz", - "integrity": "sha512-1lklS/bV5chOxwNKA/2XUUk/hPORp8zihZsXflr8x0kLwmcZ9Y9BsS6Hs3ssvA+2wUVbG0U2Ciqvm1SokNjPkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.23.0", - "@babel/traverse": "^7.23.2", - "@vue/compiler-sfc": "^3.3.4", - "callsite": "^1.0.0", - "camelcase": "^6.3.0", - "cosmiconfig": "^7.1.0", - "debug": "^4.3.4", - "deps-regex": "^0.2.0", - "findup-sync": "^5.0.0", - "ignore": "^5.2.4", - "is-core-module": "^2.12.0", - "js-yaml": "^3.14.1", - "json5": "^2.2.3", - "lodash": "^4.17.21", - "minimatch": "^7.4.6", - "multimatch": "^5.0.0", - "please-upgrade-node": "^3.2.0", - "readdirp": "^3.6.0", - "require-package-name": "^2.0.1", - "resolve": "^1.22.3", - "resolve-from": "^5.0.0", - "semver": "^7.5.4", - "yargs": "^16.2.0" - }, - "bin": { - "depcheck": "bin/depcheck.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/depcheck/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/depcheck/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/depcheck/node_modules/minimatch": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz", - "integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/depcheck/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/depcheck/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/depcheck/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/depcheck/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/deps-regex": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/deps-regex/-/deps-regex-0.2.0.tgz", - "integrity": "sha512-PwuBojGMQAYbWkMXOY9Pd/NWCDNHVH12pnS7WHqZkTSeMESe4hwnKKRp0yR87g37113x4JPbo/oIvXY+s/f56Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dns-packet": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", - "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", - "license": "MIT", - "dependencies": { - "@leichtgewicht/ip-codec": "^2.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true, - "license": "MIT" - }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-mocha": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/electron-mocha/-/electron-mocha-13.1.0.tgz", - "integrity": "sha512-n/PxV2Jv3mGiqFwoYWvzsjBxNXzuLqkfgxeJtjrrLpuYN/9VaJP98FUsd4GRKFFerD3Q1KihqNCaLXXEER2j1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "electron-window": "^0.8.0", - "mocha": "^11.0.1", - "which": "^5.0.0", - "yargs": "^17.7.2" - }, - "bin": { - "electron-mocha": "bin/electron-mocha" - }, - "engines": { - "node": ">= 16.0.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.124", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.124.tgz", - "integrity": "sha512-riELkpDUqBi00gqreV3RIGoowxGrfueEKBd6zPdOk/I8lvuFpBGNkYoHof3zUHbiTBsIU8oxdIIL/WNrAG1/7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/electron-window": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/electron-window/-/electron-window-0.8.1.tgz", - "integrity": "sha512-W1i9LfnZJozk3MXE8VgsL2E5wOUHSgyCvcg1H2vQQjj+gqhO9lVudgY3z3SF7LJAmi+0vy3CJkbMqsynWB49EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-electron-renderer": "^2.0.0" - } - }, - "node_modules/elegant-spinner": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/elegant-spinner/-/elegant-spinner-1.0.1.tgz", - "integrity": "sha512-B+ZM+RXvRqQaAmkMlO/oSe5nMUOaUnyfGYCEHoR8wrXsZR2mA0XVibsxV1bvTwxdRWah1PkQqso2EzhILGHtEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/email-addresses": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", - "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/emojilib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", - "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "license": "MIT", - "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/env-ci": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.0.tgz", - "integrity": "sha512-Z8dnwSDbV1XYM9SBF2J0GcNVvmfmfh3a49qddGIROhBoVro6MZVTji15z/sJbQ2ko2ei8n988EU1wzoLU/tF+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^8.0.0", - "java-properties": "^1.0.2" - }, - "engines": { - "node": "^18.17 || >=20.6.1" - } - }, - "node_modules/env-paths": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", - "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.23.9", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", - "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.0", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.0", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.18" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "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/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", - "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.1", - "@esbuild/android-arm": "0.25.1", - "@esbuild/android-arm64": "0.25.1", - "@esbuild/android-x64": "0.25.1", - "@esbuild/darwin-arm64": "0.25.1", - "@esbuild/darwin-x64": "0.25.1", - "@esbuild/freebsd-arm64": "0.25.1", - "@esbuild/freebsd-x64": "0.25.1", - "@esbuild/linux-arm": "0.25.1", - "@esbuild/linux-arm64": "0.25.1", - "@esbuild/linux-ia32": "0.25.1", - "@esbuild/linux-loong64": "0.25.1", - "@esbuild/linux-mips64el": "0.25.1", - "@esbuild/linux-ppc64": "0.25.1", - "@esbuild/linux-riscv64": "0.25.1", - "@esbuild/linux-s390x": "0.25.1", - "@esbuild/linux-x64": "0.25.1", - "@esbuild/netbsd-arm64": "0.25.1", - "@esbuild/netbsd-x64": "0.25.1", - "@esbuild/openbsd-arm64": "0.25.1", - "@esbuild/openbsd-x64": "0.25.1", - "@esbuild/sunos-x64": "0.25.1", - "@esbuild/win32-arm64": "0.25.1", - "@esbuild/win32-ia32": "0.25.1", - "@esbuild/win32-x64": "0.25.1" - } - }, - "node_modules/esbuild-plugin-wasm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esbuild-plugin-wasm/-/esbuild-plugin-wasm-1.1.0.tgz", - "integrity": "sha512-0bQ6+1tUbySSnxzn5jnXHMDvYnT0cN/Wd4Syk8g/sqAIJUg7buTIi22svS3Qz6ssx895NT+TgLPb33xi1OkZig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "type": "individual", - "url": "https://ko-fi.com/tschrock" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-compat-utils": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", - "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "eslint": ">=6.0.0" - } - }, - "node_modules/eslint-config-ipfs": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/eslint-config-ipfs/-/eslint-config-ipfs-7.0.6.tgz", - "integrity": "sha512-iID549DDGU+loFaTF9Oo6oxFyPstFvzRG9jjNP15+qpPeKxPXT8MCh6KL6b4TUaXlBD3znw32uag2zRVG+O/rQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "^7.5.0", - "@typescript-eslint/parser": "^7.5.0", - "eslint-config-love": "^47.0.0", - "eslint-config-standard": "^17.1.0", - "eslint-plugin-etc": "^2.0.3", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jsdoc": "^48.9.1", - "eslint-plugin-no-only-tests": "^3.1.0", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^6.1.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/eslint-config-love": { - "version": "47.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-love/-/eslint-config-love-47.0.0.tgz", - "integrity": "sha512-wIeJhb4/NF7nE5Ltppg1e9dp1Auxx0+ZPRysrXQ3uBKlW4Nj/UiTZu4r3sKWCxo6HGcRcI4MC1Q5421y3fny2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/parser": "^7.0.1" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^7.0.1", - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0", - "typescript": "*" - } - }, - "node_modules/eslint-config-standard": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-17.1.0.tgz", - "integrity": "sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==", - "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", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.1", - "eslint-plugin-import": "^2.25.2", - "eslint-plugin-n": "^15.0.0 || ^16.0.0 ", - "eslint-plugin-promise": "^6.0.0" - } - }, - "node_modules/eslint-etc": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-etc/-/eslint-etc-5.2.1.tgz", - "integrity": "sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/experimental-utils": "^5.0.0", - "tsutils": "^3.17.1", - "tsutils-etc": "^1.4.1" - }, - "peerDependencies": { - "eslint": "^8.0.0", - "typescript": ">=4.0.0" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-es-x": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", - "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/ota-meshi", - "https://opencollective.com/eslint" - ], - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.1.2", - "@eslint-community/regexpp": "^4.11.0", - "eslint-compat-utils": "^0.5.1" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": ">=8" - } - }, - "node_modules/eslint-plugin-etc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-etc/-/eslint-plugin-etc-2.0.3.tgz", - "integrity": "sha512-o5RS/0YwtjlGKWjhKojgmm82gV1b4NQUuwk9zqjy9/EjxNFKKYCaF+0M7DkYBn44mJ6JYFZw3Ft249dkKuR1ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "@phenomnomnominal/tsquery": "^5.0.0", - "@typescript-eslint/experimental-utils": "^5.0.0", - "eslint-etc": "^5.1.0", - "requireindex": "~1.2.0", - "tslib": "^2.0.0", - "tsutils": "^3.0.0" - }, - "peerDependencies": { - "eslint": "^8.0.0", - "typescript": ">=4.0.0" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" - } - }, - "node_modules/eslint-plugin-import/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-jsdoc": { - "version": "48.11.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.11.0.tgz", - "integrity": "sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@es-joy/jsdoccomment": "~0.46.0", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.1", - "debug": "^4.3.5", - "escape-string-regexp": "^4.0.0", - "espree": "^10.1.0", - "esquery": "^1.6.0", - "parse-imports": "^2.1.1", - "semver": "^7.6.3", - "spdx-expression-parse": "^4.0.0", - "synckit": "^0.9.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-jsdoc/node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-n": { - "version": "16.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-16.6.2.tgz", - "integrity": "sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "builtins": "^5.0.1", - "eslint-plugin-es-x": "^7.5.0", - "get-tsconfig": "^4.7.0", - "globals": "^13.24.0", - "ignore": "^5.2.4", - "is-builtin-module": "^3.2.1", - "is-core-module": "^2.12.1", - "minimatch": "^3.1.2", - "resolve": "^1.22.2", - "semver": "^7.5.3" - }, - "engines": { - "node": ">=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-n/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-n/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-n/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-n/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint-plugin-no-only-tests": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-no-only-tests/-/eslint-plugin-no-only-tests-3.3.0.tgz", - "integrity": "sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=5.0.0" - } - }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint-plugin-node/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-promise": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", - "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/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/eslint/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/eslint/node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/eslint/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eslint/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/exit-hook": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-4.0.0.tgz", - "integrity": "sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", - "dev": true, - "engines": { - "node": "> 0.1.90" - } - }, - "node_modules/fast-content-type-parse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz", - "integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-equals": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", - "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "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/figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha512-UxKlfCRuCBxSXU4C6t9scbDyWZ4VlaFFdojKtzJuSkuOBQ5CNFum+zZXFwHjo+CxBC1t6zlYPgHIgFjL8ggoEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/figures/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/file-entry-cache": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", - "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/file-url": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", - "integrity": "sha512-g872QGsHexznxkIAdK8UiZRe7SkE6kvylShU4Nsj8NvfvZag7S0QuQ4IgvPDkk75HxgjIVDwycFTDAgIiO4nDA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-up-simple": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", - "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-versions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-6.0.0.tgz", - "integrity": "sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver-regex": "^4.0.5", - "super-regex": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "micromatch": "^4.0.2" - } - }, - "node_modules/findup-sync": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", - "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.3", - "micromatch": "^4.0.4", - "resolve-dir": "^1.0.1" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", - "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.3.1", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "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/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "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/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "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/function-timeout": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-1.0.2.tgz", - "integrity": "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensequence": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-7.0.0.tgz", - "integrity": "sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "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-iterator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/get-iterator/-/get-iterator-2.0.1.tgz", - "integrity": "sha512-7HuY/hebu4gryTDT7O/XY/fvY9wRByEGdK6QOa4of8npTcv0+NS6frFKABcf6S9EBAsveTuKTsZQQBFMMNILIg==", - "license": "MIT" - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "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/get-stdin": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", - "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-stream": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", - "integrity": "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/gh-pages": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz", - "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^3.2.4", - "commander": "^13.0.0", - "email-addresses": "^5.0.0", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^11.1.1", - "globby": "^11.1.0" - }, - "bin": { - "gh-pages": "bin/gh-pages.js", - "gh-pages-clean": "bin/gh-pages-clean.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gh-pages/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gh-pages/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/git-log-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.1.tgz", - "integrity": "sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "argv-formatter": "~1.0.0", - "spawn-error-forwarder": "~1.0.0", - "split2": "~1.0.0", - "stream-combiner2": "~1.1.1", - "through2": "~2.0.0", - "traverse": "0.6.8" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-directory": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", - "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "4.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/global-prefix/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" - }, - "node_modules/global-prefix/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", - "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby/node_modules/ignore": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.3.tgz", - "integrity": "sha512-bAH5jbK/F3T3Jls4I0SO1hmPR0dKU0a7+SY6n1yzRtG54FLO8d6w/nxLFX2Nb7dBu6cCWXPaAME6cYqFUMmuCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/globby/node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-own-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", - "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasha/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/hashlru": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/hashlru/-/hashlru-2.3.0.tgz", - "integrity": "sha512-0cMsjjIC8I+D3M44pOQdsy0OHXGLVz6Z0beRuufhKa0KfaD2wGwAev6jILzXsd3/vpnNQJmWyZtIILqM1N+n5A==", - "license": "MIT" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/highlight.js": { - "version": "10.7.3", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": "*" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hook-std": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", - "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-cookie-agent": { - "version": "6.0.8", - "resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-6.0.8.tgz", - "integrity": "sha512-qnYh3yLSr2jBsTYkw11elq+T361uKAJaZ2dR4cfYZChw1dt9uL5t3zSUwehoqqVb4oldk1BpkXKm2oat8zV+oA==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.3" - }, - "engines": { - "node": ">=18.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/3846masa" - }, - "peerDependencies": { - "tough-cookie": "^4.0.0 || ^5.0.0", - "undici": "^5.11.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "undici": { - "optional": true - } - } - }, - "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/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "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/human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=16.17.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==", - "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" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/import-from-esm": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-from-esm/-/import-from-esm-2.0.0.tgz", - "integrity": "sha512-YVt14UZCgsX1vZQ3gKjkWVdBdHQ6eu3MPU1TBgL1H5orXe2+jWD006WCPPtOuwlQm10NuzOW5WawiF1Q9veW8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "import-meta-resolve": "^4.0.0" - }, - "engines": { - "node": ">=18.20" - } - }, - "node_modules/import-meta-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", - "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/index-to-position": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-1.0.0.tgz", - "integrity": "sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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": "4.1.1", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", - "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/interface-datastore": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-8.3.1.tgz", - "integrity": "sha512-3r0ETmHIi6HmvM5sc09QQiCD3gUfwtEM/AAChOyAd/UAKT69uk8LXfTSUBufbUIO/dU65Vj8nb9O6QjwW8vDSQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "interface-store": "^6.0.0", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/interface-store": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/interface-store/-/interface-store-6.0.2.tgz", - "integrity": "sha512-KSFCXtBlNoG0hzwNa0RmhHtrdhzexp+S+UY2s0rWTBJyfdEIgn6i6Zl9otVqrcFYbYrneBT7hbmHQ8gE0C3umA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/into-stream": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-7.0.0.tgz", - "integrity": "sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "from2": "^2.3.0", - "p-is-promise": "^3.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/irregular-plurals": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", - "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-arguments": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", - "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ci-info": "^2.0.0" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-electron": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", - "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-electron-renderer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-electron-renderer/-/is-electron-renderer-2.0.1.tgz", - "integrity": "sha512-pRlQnpaCFhDVPtkXkP+g9Ybv/CjbiQDjnKFQTEjpBfDKeV6dRDBczuFRDpM6DVfk2EjpMS8t5kwE5jPnqYl3zA==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", - "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-proto": "^1.0.0", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz", - "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-loopback-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-loopback-addr/-/is-loopback-addr-2.0.2.tgz", - "integrity": "sha512-26POf2KRCno/KTNL5Q0b/9TYnL00xEsSaLfiFRmjM7m7Lw7ZMmFybzzuX4CcsLAluZGd+niLUiMRxEooVE3aqg==", - "license": "MIT" - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-nan": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", - "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-network-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz", - "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-observable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-1.1.0.tgz", - "integrity": "sha512-NqCa4Sa2d+u7BWc6CukaObG3Fh+CU9bvixbpcXYhy2VvYS7vVGIdAgnIS5Ks3A/cqk4rebLJ9s8zBstT2aKnIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "symbol-observable": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-path-cwd": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", - "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-unicode-supported": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", - "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-uuid": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-uuid/-/is-uuid-1.0.2.tgz", - "integrity": "sha512-tCByphFcJgf2qmiMo5hMCgNAquNSagOetVetDvBXswGkNfoyEMvGH1yDlF8cbZbKnbVBr4Y5/rlpMz9umxyBkQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/isexe": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", - "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/issue-parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-7.0.1.tgz", - "integrity": "sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash.capitalize": "^4.2.1", - "lodash.escaperegexp": "^4.1.2", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.uniqby": "^4.7.0" - }, - "engines": { - "node": "^18.17 || >=20.6.1" - } - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "license": "ISC", - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/istanbul-lib-processinfo/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/it-all": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/it-all/-/it-all-3.0.7.tgz", - "integrity": "sha512-PkuYtu6XhJzuPTKXImd6y0qE6H91MUPV/b9xotXMAI6GjmD2v3NoHj2g5L0lS2qZ0EzyGWZU1kp0UxW8POvNBQ==", - "dev": true, - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-byte-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/it-byte-stream/-/it-byte-stream-1.1.1.tgz", - "integrity": "sha512-OIOb8PvK9ZV7MHvyxIDNyN3jmrxrJdx99G0RIYYb3Tzo1OWv+O1C6mfg7nnlDuuTQz2POYFXe87AShKAEl+POw==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-queueless-pushable": "^1.0.0", - "it-stream-types": "^2.0.2", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-drain": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/it-drain/-/it-drain-3.0.8.tgz", - "integrity": "sha512-eeOz+WwKc11ou1UuqZympcXPLCjpTn5ALcYFJiHeTEiYEZ2py/J1vq41XWYj88huCUiqp9iNHfObOKrbIk5Izw==", - "dev": true, - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-filter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/it-filter/-/it-filter-3.1.2.tgz", - "integrity": "sha512-2AozaGjIvBBiB7t7MpVNug9kwofqmKSpvgW7zhuyvCs6xxDd6FrfvqyfYtlQTKLNP+Io1WeXko1UQhdlK4M0gg==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-peekable": "^3.0.0" - } - }, - "node_modules/it-foreach": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/it-foreach/-/it-foreach-2.1.2.tgz", - "integrity": "sha512-PvXs3v1FaeWDhWzRxnwB4vSKJngxdLgi0PddkfurCvIFBmKTBfWONLeyDk5dxrvtCzdE4y96KzEQynk4/bbI5A==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-peekable": "^3.0.0" - } - }, - "node_modules/it-length-prefixed": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/it-length-prefixed/-/it-length-prefixed-10.0.1.tgz", - "integrity": "sha512-BhyluvGps26u9a7eQIpOI1YN7mFgi8lFwmiPi07whewbBARKAG9LE09Odc8s1Wtbt2MB6rNUrl7j9vvfXTJwdQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-reader": "^6.0.1", - "it-stream-types": "^2.0.1", - "uint8-varint": "^2.0.1", - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-length-prefixed-stream": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/it-length-prefixed-stream/-/it-length-prefixed-stream-1.2.1.tgz", - "integrity": "sha512-FYqlxc2toUoK+aPO5r3KDBIUG1mOvk2DzmjQcsfLUTHRWMJP4Va9855tVzg/22Bj+VUUaT7gxBg7HmbiCxTK4w==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-byte-stream": "^1.0.0", - "it-stream-types": "^2.0.2", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-map": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/it-map/-/it-map-3.1.2.tgz", - "integrity": "sha512-G3dzFUjTYHKumJJ8wa9dSDS3yKm8L7qDUnAgzemOD0UMztwm54Qc2v97SuUCiAgbOz/aibkSLImfoFK09RlSFQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-peekable": "^3.0.0" - } - }, - "node_modules/it-merge": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/it-merge/-/it-merge-3.0.9.tgz", - "integrity": "sha512-TjY4WTiwe4ONmaKScNvHDAJj6Tw0UeQFp4JrtC/3Mq7DTyhytes7mnv5OpZV4gItpZcs0AgRntpT2vAy2cnXUw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-queueless-pushable": "^2.0.0" - } - }, - "node_modules/it-merge/node_modules/it-queueless-pushable": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/it-queueless-pushable/-/it-queueless-pushable-2.0.0.tgz", - "integrity": "sha512-MlNnefWT/ntv5fesrHpxwVIu6ZdtlkN0A4aaJiE5wnmPMBv9ttiwX3UEMf78dFwIj5ZNaU9usYXg4swMEpUNJQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "abort-error": "^1.0.1", - "p-defer": "^4.0.1", - "race-signal": "^1.1.3" - } - }, - "node_modules/it-ndjson": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/it-ndjson/-/it-ndjson-1.1.2.tgz", - "integrity": "sha512-TPKpdYSNKjDdroCPnLamM5Up6XnPQ7F1KgNP3Ib5y5O4ayOVP+DHac/pzjUigcg9Kf9gkGVXDz8+FFKpWwoB3w==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-pair": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/it-pair/-/it-pair-2.0.6.tgz", - "integrity": "sha512-5M0t5RAcYEQYNG5BV7d7cqbdwbCAp5yLdzvkxsZmkuZsLbTdZzah6MQySYfaAQjNDCq6PUnDt0hqBZ4NwMfW6g==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-stream-types": "^2.0.1", - "p-defer": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-parallel": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/it-parallel/-/it-parallel-3.0.9.tgz", - "integrity": "sha512-FSg8T+pr7Z1VUuBxEzAAp/K1j8r1e9mOcyzpWMxN3mt33WFhroFjWXV1oYSSjNqcdYwxD/XgydMVMktJvKiDog==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "p-defer": "^4.0.1" - } - }, - "node_modules/it-peekable": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/it-peekable/-/it-peekable-3.0.6.tgz", - "integrity": "sha512-odk9wn8AwFQipy8+tFaZNRCM62riraKZJRysfbmOett9wgJumCwgZFzWUBUwMoiQapEcEVGwjDpMChZIi+zLuQ==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-pipe": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/it-pipe/-/it-pipe-3.0.1.tgz", - "integrity": "sha512-sIoNrQl1qSRg2seYSBH/3QxWhJFn9PKYvOf/bHdtCBF0bnghey44VyASsWzn5dAx0DCDDABq1hZIuzKmtBZmKA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-merge": "^3.0.0", - "it-pushable": "^3.1.2", - "it-stream-types": "^2.0.1" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-protobuf-stream": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/it-protobuf-stream/-/it-protobuf-stream-1.1.6.tgz", - "integrity": "sha512-TxqgDHXTBt1XkYhrGKP8ubNsYD4zuTClSg6S1M0xTPsskGKA4nPFOGM60zrkh4NMB1Wt3EnsqM5U7kXkx60EXQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-length-prefixed-stream": "^1.0.0", - "it-stream-types": "^2.0.2", - "uint8arraylist": "^2.4.8" - } - }, - "node_modules/it-pushable": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/it-pushable/-/it-pushable-3.2.3.tgz", - "integrity": "sha512-gzYnXYK8Y5t5b/BnJUr7glfQLO4U5vyb05gPx/TyTw+4Bv1zM9gFk4YsOrnulWefMewlphCjKkakFvj1y99Tcg==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "p-defer": "^4.0.0" - } - }, - "node_modules/it-queueless-pushable": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/it-queueless-pushable/-/it-queueless-pushable-1.0.2.tgz", - "integrity": "sha512-BFIm48C4O8+i+oVEPQpZ70+CaAsVUircvZtZCrpG2Q64933aLp+tDmas1mTBwqVBfIUUlg09d+e6SWW1CBuykQ==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "p-defer": "^4.0.1", - "race-signal": "^1.1.3" - } - }, - "node_modules/it-reader": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/it-reader/-/it-reader-6.0.4.tgz", - "integrity": "sha512-XCWifEcNFFjjBHtor4Sfaj8rcpt+FkY0L6WdhD578SCDhV4VUm7fCkF3dv5a+fTcfQqvN9BsxBTvWbYO6iCjTg==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-stream-types": "^2.0.1", - "uint8arraylist": "^2.0.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/it-sort": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/it-sort/-/it-sort-3.0.7.tgz", - "integrity": "sha512-PsaKSd2Z0uhq8Mq5htdfsE/UagmdLCLWdBXPwi3FZGR4BTG180pFamhK+O+luFtBCNGRoqKAdtbZGTyGwA9uzw==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "it-all": "^3.0.0" - } - }, - "node_modules/it-stream-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/it-stream-types/-/it-stream-types-2.0.2.tgz", - "integrity": "sha512-Rz/DEZ6Byn/r9+/SBCuJhpPATDF9D+dz5pbgSUyBsCDtza6wtNATrz/jz1gDyNanC3XdLboriHnOC925bZRBww==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-take": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/it-take/-/it-take-3.0.7.tgz", - "integrity": "sha512-0+EbsTvH1XCpwhhFkjWdqJTjzS5XP3KL69woBqwANNhMLKn0j39jk/WHIlvbg9XW2vEm7cZz4p8w5DkBZR8LoA==", - "dev": true, - "license": "Apache-2.0 OR MIT" - }, - "node_modules/it-to-buffer": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/it-to-buffer/-/it-to-buffer-4.0.8.tgz", - "integrity": "sha512-niZbR/+GbyQ2F2Nj79EJprT0gji5Si4nM1eJpgtlvfbvhsi5ZgA/y+mzSrOoNajiTC3svqvoNy8HGlTW2Faz/A==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arrays": "^5.1.0" - } - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/java-properties": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", - "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC", - "optional": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "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/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/junk": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", - "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true, - "license": "MIT" - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ky": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/ky/-/ky-1.7.5.tgz", - "integrity": "sha512-HzhziW6sc5m0pwi5M196+7cEBtbt0lCYi67wNsiwMUmz833wloE0gbzJPWKs1gliFKQb34huItDQX97LyOdPdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, - "node_modules/latest-version": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz", - "integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==", - "dev": true, - "license": "MIT", - "dependencies": { - "package-json": "^10.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/libp2p": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/libp2p/-/libp2p-2.8.2.tgz", - "integrity": "sha512-LYZUWXcL5kQ+5VIiWhUWURLR7tgNBfwqGTLtZukMqjb33U/YAdd9lqW2MXjvaJLXPuGgRAatisDTOEP/ckfhWA==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "@chainsafe/is-ip": "^2.0.2", - "@chainsafe/netmask": "^2.0.0", - "@libp2p/crypto": "^5.0.15", - "@libp2p/interface": "^2.7.0", - "@libp2p/interface-internal": "^2.3.9", - "@libp2p/logger": "^5.1.13", - "@libp2p/multistream-select": "^6.0.20", - "@libp2p/peer-collections": "^6.0.25", - "@libp2p/peer-id": "^5.1.0", - "@libp2p/peer-store": "^11.1.2", - "@libp2p/utils": "^6.6.0", - "@multiformats/dns": "^1.0.6", - "@multiformats/multiaddr": "^12.3.5", - "@multiformats/multiaddr-matcher": "^1.6.0", - "any-signal": "^4.1.1", - "datastore-core": "^10.0.2", - "interface-datastore": "^8.3.1", - "it-byte-stream": "^1.1.0", - "it-merge": "^3.0.5", - "it-parallel": "^3.0.8", - "merge-options": "^3.0.4", - "multiformats": "^13.3.1", - "p-defer": "^4.0.1", - "p-retry": "^6.2.1", - "progress-events": "^1.0.1", - "race-event": "^1.3.0", - "race-signal": "^1.1.2", - "uint8arrays": "^5.1.0" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/listr": { - "version": "0.14.3", - "resolved": "https://registry.npmjs.org/listr/-/listr-0.14.3.tgz", - "integrity": "sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@samverschueren/stream-to-observable": "^0.3.0", - "is-observable": "^1.1.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.5.0", - "listr-verbose-renderer": "^0.5.0", - "p-map": "^2.0.0", - "rxjs": "^6.3.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/listr-silent-renderer": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz", - "integrity": "sha512-L26cIFm7/oZeSNVhWB6faeorXhMg4HNlb/dS/7jHhr708jxlXrtrBWo4YUxZQkc6dGoxEAe6J/D3juTRBUzjtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz", - "integrity": "sha512-tKRsZpKz8GSGqoI/+caPmfrypiaq+OQCbd+CovEC24uk1h952lVj5sC7SqyFUm+OaJ5HN/a1YLt5cit2FMNsFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^2.3.0", - "strip-ansi": "^3.0.1" - }, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "listr": "^0.14.2" - } - }, - "node_modules/listr-update-renderer/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/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/listr-update-renderer/node_modules/indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-update-renderer/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr-update-renderer/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/listr-verbose-renderer": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz", - "integrity": "sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^2.4.1", - "cli-cursor": "^2.1.0", - "date-fns": "^1.27.2", - "figures": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-verbose-renderer/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/listr-verbose-renderer/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/listr-verbose-renderer/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/listr-verbose-renderer/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/listr-verbose-renderer/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/listr-verbose-renderer/node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/listr-verbose-renderer/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/listr-verbose-renderer/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/listr/node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/listr/node_modules/p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.capitalize": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", - "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "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.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.uniqby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", - "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", - "integrity": "sha512-mmPrW0Fh2fxOzdBbFv4g1m6pR72haFLPJ2G5SJEELf1y+iaQrDG6cWCPjy54RHYbZAt7X+ls690Kw62AdWXBzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/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/log-symbols/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/log-update": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz", - "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^3.0.0", - "cli-cursor": "^2.0.0", - "wrap-ansi": "^3.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-func-name": "^2.0.1" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "license": "ISC" - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/marked": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", - "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/marked-terminal": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", - "integrity": "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^7.0.0", - "ansi-regex": "^6.1.0", - "chalk": "^5.4.1", - "cli-highlight": "^2.1.11", - "cli-table3": "^0.6.5", - "node-emoji": "^2.2.0", - "supports-hyperlinks": "^3.1.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "marked": ">=1 <16" - } - }, - "node_modules/marked-terminal/node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "environment": "^1.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/matchit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/matchit/-/matchit-1.1.0.tgz", - "integrity": "sha512-+nGYoOlfHmxe5BW5tE0EMJppXEwdSf8uBA1GTZC7Q77kbT35+VKLYJMzVNWCHSsga1ps1tPYFtFyvxvKzWVmMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@arr/every": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "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/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/meow": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-13.2.0.tgz", - "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-options": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", - "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge-options/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/metro-react-native-babel-preset": { - "version": "0.64.0", - "resolved": "https://registry.npmjs.org/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.64.0.tgz", - "integrity": "sha512-HcZ0RWQRuJfpPiaHyFQJzcym+/dDIVUPwUAXWoub/C4GkGu+mPjp8vqK6g0FxokCnnI2TK0gZTza2IDfiNNscQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.0.0", - "@babel/plugin-proposal-class-properties": "^7.0.0", - "@babel/plugin-proposal-export-default-from": "^7.0.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", - "@babel/plugin-proposal-optional-chaining": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-export-default-from": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", - "@babel/plugin-syntax-optional-chaining": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.0.0", - "@babel/plugin-transform-flow-strip-types": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-commonjs": "^7.0.0", - "@babel/plugin-transform-object-assign": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-runtime": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.5.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/template": "^7.0.0", - "react-refresh": "^0.4.0" - }, - "peerDependencies": { - "@babel/core": "*" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.6.tgz", - "integrity": "sha512-4rGt7rvQHBbaSOF9POGkk1ocRP16Md1x36Xma8sz8h8/vfCUI2OtEIeCqe4Ofes853x4xDoPiFLIT47J5fI/7A==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa" - ], - "license": "MIT", - "bin": { - "mime": "bin/cli.js" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "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", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minimist-options/node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/minimist-options/node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", - "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/mocha/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/mocha/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mortice": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/mortice/-/mortice-3.0.6.tgz", - "integrity": "sha512-xUjsTQreX8rO3pHuGYDZ3PY/sEiONIzqzjLeog5akdY4bz9TlDDuvYlU8fm+6qnm4rnpa6AFxLhsfSBThLijdA==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "observable-webworkers": "^2.0.1", - "p-queue": "^8.0.1", - "p-timeout": "^6.0.0" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "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/multiformats": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/multiformats/-/multiformats-13.3.2.tgz", - "integrity": "sha512-qbB0CQDt3QKfiAzZ5ZYjLFOs+zW43vA4uyM8g27PeEuXZybUOFyjrVdP93HPBHMoglibwfkdVwbzfUq8qGcH6g==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/multimatch": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", - "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimatch": "^3.0.3", - "array-differ": "^3.0.0", - "array-union": "^2.1.0", - "arrify": "^2.0.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/multimatch/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/multimatch/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "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/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz", - "integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nerf-dart": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", - "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", - "dev": true, - "license": "MIT" - }, - "node_modules/netmask": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", - "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", - "license": "MIT", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/nise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", - "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.1", - "@sinonjs/text-encoding": "^0.7.3", - "just-extend": "^6.2.0", - "path-to-regexp": "^8.1.0" - } - }, - "node_modules/node-emoji": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", - "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.6.0", - "char-regex": "^1.0.2", - "emojilib": "^2.4.0", - "skin-tone": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-package-data": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-6.0.2.tgz", - "integrity": "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^7.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", - "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.9.2.tgz", - "integrity": "sha512-iriPEPIkoMYUy3F6f3wwSZAU93E0Eg6cHwIR6jzzOXWSy+SD/rOODEs74cVONHKSx2obXtuUoyidVEhISrisgQ==", - "bundleDependencies": [ - "@isaacs/string-locale-compare", - "@npmcli/arborist", - "@npmcli/config", - "@npmcli/fs", - "@npmcli/map-workspaces", - "@npmcli/package-json", - "@npmcli/promise-spawn", - "@npmcli/redact", - "@npmcli/run-script", - "@sigstore/tuf", - "abbrev", - "archy", - "cacache", - "chalk", - "ci-info", - "cli-columns", - "fastest-levenshtein", - "fs-minipass", - "glob", - "graceful-fs", - "hosted-git-info", - "ini", - "init-package-json", - "is-cidr", - "json-parse-even-better-errors", - "libnpmaccess", - "libnpmdiff", - "libnpmexec", - "libnpmfund", - "libnpmhook", - "libnpmorg", - "libnpmpack", - "libnpmpublish", - "libnpmsearch", - "libnpmteam", - "libnpmversion", - "make-fetch-happen", - "minimatch", - "minipass", - "minipass-pipeline", - "ms", - "node-gyp", - "nopt", - "normalize-package-data", - "npm-audit-report", - "npm-install-checks", - "npm-package-arg", - "npm-pick-manifest", - "npm-profile", - "npm-registry-fetch", - "npm-user-validate", - "p-map", - "pacote", - "parse-conflict-json", - "proc-log", - "qrcode-terminal", - "read", - "semver", - "spdx-expression-parse", - "ssri", - "supports-color", - "tar", - "text-table", - "tiny-relative-date", - "treeverse", - "validate-npm-package-name", - "which", - "write-file-atomic" - ], - "dev": true, - "license": "Artistic-2.0", - "workspaces": [ - "docs", - "smoke-tests", - "mock-globals", - "mock-registry", - "workspaces/*" - ], - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/arborist": "^8.0.0", - "@npmcli/config": "^9.0.0", - "@npmcli/fs": "^4.0.0", - "@npmcli/map-workspaces": "^4.0.2", - "@npmcli/package-json": "^6.1.0", - "@npmcli/promise-spawn": "^8.0.2", - "@npmcli/redact": "^3.0.0", - "@npmcli/run-script": "^9.0.1", - "@sigstore/tuf": "^3.0.0", - "abbrev": "^3.0.0", - "archy": "~1.0.0", - "cacache": "^19.0.1", - "chalk": "^5.3.0", - "ci-info": "^4.1.0", - "cli-columns": "^4.0.0", - "fastest-levenshtein": "^1.0.16", - "fs-minipass": "^3.0.3", - "glob": "^10.4.5", - "graceful-fs": "^4.2.11", - "hosted-git-info": "^8.0.2", - "ini": "^5.0.0", - "init-package-json": "^7.0.2", - "is-cidr": "^5.1.0", - "json-parse-even-better-errors": "^4.0.0", - "libnpmaccess": "^9.0.0", - "libnpmdiff": "^7.0.0", - "libnpmexec": "^9.0.0", - "libnpmfund": "^6.0.0", - "libnpmhook": "^11.0.0", - "libnpmorg": "^7.0.0", - "libnpmpack": "^8.0.0", - "libnpmpublish": "^10.0.1", - "libnpmsearch": "^8.0.0", - "libnpmteam": "^7.0.0", - "libnpmversion": "^7.0.0", - "make-fetch-happen": "^14.0.3", - "minimatch": "^9.0.5", - "minipass": "^7.1.1", - "minipass-pipeline": "^1.2.4", - "ms": "^2.1.2", - "node-gyp": "^11.0.0", - "nopt": "^8.0.0", - "normalize-package-data": "^7.0.0", - "npm-audit-report": "^6.0.0", - "npm-install-checks": "^7.1.1", - "npm-package-arg": "^12.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-profile": "^11.0.1", - "npm-registry-fetch": "^18.0.2", - "npm-user-validate": "^3.0.0", - "p-map": "^4.0.0", - "pacote": "^19.0.1", - "parse-conflict-json": "^4.0.0", - "proc-log": "^5.0.0", - "qrcode-terminal": "^0.12.0", - "read": "^4.0.0", - "semver": "^7.6.3", - "spdx-expression-parse": "^4.0.0", - "ssri": "^12.0.0", - "supports-color": "^9.4.0", - "tar": "^6.2.1", - "text-table": "~0.2.0", - "tiny-relative-date": "^1.3.0", - "treeverse": "^3.0.0", - "validate-npm-package-name": "^6.0.0", - "which": "^5.0.0", - "write-file-atomic": "^6.0.0" - }, - "bin": { - "npm": "bin/npm-cli.js", - "npx": "bin/npx-cli.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm-package-json-lint": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/npm-package-json-lint/-/npm-package-json-lint-8.0.0.tgz", - "integrity": "sha512-44xqAKoV0nXnBYYLGUhMItGZb5tW3cLoW3UZxcsaCOX/YAkECrzOQA5F48oAA51vVE5CqAnsJB2CFvtolzMA3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.6", - "ajv-errors": "^1.0.1", - "chalk": "^4.1.2", - "cosmiconfig": "^8.3.6", - "debug": "^4.3.4", - "globby": "^11.1.0", - "ignore": "^5.3.1", - "is-plain-obj": "^3.0.0", - "jsonc-parser": "^3.2.1", - "log-symbols": "^4.1.0", - "meow": "^9.0.0", - "plur": "^4.0.0", - "semver": "^7.6.2", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1", - "type-fest": "^4.20.0", - "validate-npm-package-name": "^5.0.1" - }, - "bin": { - "npmPkgJsonLint": "dist/cli.js" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=9.0.0" - } - }, - "node_modules/npm-package-json-lint/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/npm-package-json-lint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm-package-json-lint/node_modules/cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/npm-package-json-lint/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/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/npm-package-json-lint/node_modules/is-plain-obj": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", - "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/npm-package-json-lint/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/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/npm-package-json-lint/node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-package-json-lint/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/npm-package-json-lint/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/npm-package-json-lint/node_modules/read-pkg/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/npm-package-json-lint/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-package-json-lint/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-package-json-lint/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/npm-package-json-lint/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui": { - "version": "8.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/npm/node_modules/@isaacs/string-locale-compare": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/@npmcli/agent": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "agent-base": "^7.1.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "lru-cache": "^10.0.1", - "socks-proxy-agent": "^8.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/arborist": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/string-locale-compare": "^1.1.0", - "@npmcli/fs": "^4.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/metavuln-calculator": "^8.0.0", - "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.1", - "@npmcli/query": "^4.0.0", - "@npmcli/redact": "^3.0.0", - "@npmcli/run-script": "^9.0.1", - "bin-links": "^5.0.0", - "cacache": "^19.0.1", - "common-ancestor-path": "^1.0.1", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "json-stringify-nice": "^1.1.4", - "lru-cache": "^10.2.2", - "minimatch": "^9.0.4", - "nopt": "^8.0.0", - "npm-install-checks": "^7.1.0", - "npm-package-arg": "^12.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.1", - "pacote": "^19.0.0", - "parse-conflict-json": "^4.0.0", - "proc-log": "^5.0.0", - "proggy": "^3.0.0", - "promise-all-reject-late": "^1.0.0", - "promise-call-limit": "^3.0.1", - "read-package-json-fast": "^4.0.0", - "semver": "^7.3.7", - "ssri": "^12.0.0", - "treeverse": "^3.0.0", - "walk-up-path": "^3.0.1" - }, - "bin": { - "arborist": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/config": { - "version": "9.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/map-workspaces": "^4.0.1", - "@npmcli/package-json": "^6.0.1", - "ci-info": "^4.0.0", - "ini": "^5.0.0", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/fs": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/git": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^8.0.0", - "ini": "^5.0.0", - "lru-cache": "^10.0.1", - "npm-pick-manifest": "^10.0.0", - "proc-log": "^5.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/installed-package-contents": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/map-workspaces": { - "version": "4.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/name-from-folder": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "glob": "^10.2.2", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { - "version": "8.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cacache": "^19.0.0", - "json-parse-even-better-errors": "^4.0.0", - "pacote": "^20.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/metavuln-calculator/node_modules/pacote": { - "version": "20.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", - "ssri": "^12.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/name-from-folder": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/node-gyp": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/package-json": { - "version": "6.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "glob": "^10.2.2", - "hosted-git-info": "^8.0.0", - "json-parse-even-better-errors": "^4.0.0", - "normalize-package-data": "^7.0.0", - "proc-log": "^5.0.0", - "semver": "^7.5.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/promise-spawn": { - "version": "8.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/query": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "postcss-selector-parser": "^6.1.2" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/redact": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@npmcli/run-script": { - "version": "9.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^4.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "node-gyp": "^11.0.0", - "proc-log": "^5.0.0", - "which": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/@sigstore/protobuf-specs": { - "version": "0.3.2", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/@sigstore/tuf": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2", - "tuf-js": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/@tufjs/canonical-json": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^16.14.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/abbrev": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/agent-base": { - "version": "7.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/aggregate-error": { - "version": "3.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-regex": { - "version": "5.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ansi-styles": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/aproba": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/archy": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/balanced-match": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/bin-links": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cmd-shim": "^7.0.0", - "npm-normalize-package-bin": "^4.0.0", - "proc-log": "^5.0.0", - "read-cmd-shim": "^5.0.0", - "write-file-atomic": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/binary-extensions": { - "version": "2.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/npm/node_modules/cacache": { - "version": "19.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^4.0.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^10.0.1", - "minipass": "^7.0.3", - "minipass-collect": "^2.0.1", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^7.0.2", - "ssri": "^12.0.0", - "tar": "^7.4.3", - "unique-filename": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/chownr": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/minizlib": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/mkdirp": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/p-map": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/tar": { - "version": "7.4.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/cacache/node_modules/yallist": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/chalk": { - "version": "5.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/npm/node_modules/chownr": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ci-info": { - "version": "4.1.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/cidr-regex": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "ip-regex": "^5.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/cli-columns": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/npm/node_modules/cmd-shim": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/npm/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/common-ancestor-path": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/cross-spawn": { - "version": "7.0.6", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/cssesc": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/debug": { - "version": "4.3.7", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/npm/node_modules/diff": { - "version": "5.2.0", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/npm/node_modules/eastasianwidth": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/emoji-regex": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/encoding": { - "version": "0.1.13", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/npm/node_modules/env-paths": { - "version": "2.2.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/npm/node_modules/err-code": { - "version": "2.0.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/exponential-backoff": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "Apache-2.0" - }, - "node_modules/npm/node_modules/fastest-levenshtein": { - "version": "1.0.16", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/npm/node_modules/foreground-child": { - "version": "3.3.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/fs-minipass": { - "version": "3.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/glob": { - "version": "10.4.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/graceful-fs": { - "version": "4.2.11", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/hosted-git-info": { - "version": "8.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/http-cache-semantics": { - "version": "4.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause" - }, - "node_modules/npm/node_modules/http-proxy-agent": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/https-proxy-agent": { - "version": "7.0.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/iconv-lite": { - "version": "0.6.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npm/node_modules/ignore-walk": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/imurmurhash": { - "version": "0.1.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/npm/node_modules/indent-string": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/ini": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/init-package-json": { - "version": "7.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/package-json": "^6.0.0", - "npm-package-arg": "^12.0.0", - "promzard": "^2.0.0", - "read": "^4.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4", - "validate-npm-package-name": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/ip-address": { - "version": "9.0.5", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/npm/node_modules/ip-regex": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/is-cidr": { - "version": "5.1.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "cidr-regex": "^4.1.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/npm/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/isexe": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.3", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/npm/node_modules/jsbn": { - "version": "1.1.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/json-parse-even-better-errors": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/json-stringify-nice": { - "version": "1.1.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff": { - "version": "6.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/just-diff-apply": { - "version": "5.5.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/libnpmaccess": { - "version": "9.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmdiff": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "binary-extensions": "^2.3.0", - "diff": "^5.1.0", - "minimatch": "^9.0.4", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "tar": "^6.2.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmexec": { - "version": "9.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0", - "@npmcli/run-script": "^9.0.1", - "ci-info": "^4.0.0", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0", - "proc-log": "^5.0.0", - "read": "^4.0.0", - "read-package-json-fast": "^4.0.0", - "semver": "^7.3.7", - "walk-up-path": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmfund": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmhook": { - "version": "11.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmorg": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmpack": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/arborist": "^8.0.0", - "@npmcli/run-script": "^9.0.1", - "npm-package-arg": "^12.0.0", - "pacote": "^19.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmpublish": { - "version": "10.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ci-info": "^4.0.0", - "normalize-package-data": "^7.0.0", - "npm-package-arg": "^12.0.0", - "npm-registry-fetch": "^18.0.1", - "proc-log": "^5.0.0", - "semver": "^7.3.7", - "sigstore": "^3.0.0", - "ssri": "^12.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmsearch": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmteam": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "aproba": "^2.0.0", - "npm-registry-fetch": "^18.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/libnpmversion": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.1", - "@npmcli/run-script": "^9.0.1", - "json-parse-even-better-errors": "^4.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.7" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/lru-cache": { - "version": "10.4.3", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/make-fetch-happen": { - "version": "14.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/agent": "^3.0.0", - "cacache": "^19.0.1", - "http-cache-semantics": "^4.1.1", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^1.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "ssri": "^12.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/make-fetch-happen/node_modules/negotiator": { - "version": "1.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/npm/node_modules/minimatch": { - "version": "9.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/minipass": { - "version": "7.1.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-collect": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npm/node_modules/minipass-fetch": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^3.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm/node_modules/minipass-fetch/node_modules/minizlib": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/minipass-flush": { - "version": "1.0.5", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline": { - "version": "1.2.4", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized": { - "version": "1.0.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/minizlib": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/mkdirp": { - "version": "1.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/ms": { - "version": "2.1.3", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/mute-stream": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/node-gyp": { - "version": "11.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^14.0.3", - "nopt": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "tar": "^7.4.3", - "which": "^5.0.0" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/chownr": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/minizlib": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/mkdirp": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/tar": { - "version": "7.4.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/node-gyp/node_modules/yallist": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/npm/node_modules/nopt": { - "version": "8.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "abbrev": "^2.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/nopt/node_modules/abbrev": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/normalize-package-data": { - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^8.0.0", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-audit-report": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-bundled": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-install-checks": { - "version": "7.1.1", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-normalize-package-bin": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-package-arg": { - "version": "12.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^8.0.0", - "proc-log": "^5.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^6.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-packlist": { - "version": "9.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^7.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-pick-manifest": { - "version": "10.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^7.1.0", - "npm-normalize-package-bin": "^4.0.0", - "npm-package-arg": "^12.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-profile": { - "version": "11.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch": { - "version": "18.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/redact": "^3.0.0", - "jsonparse": "^1.3.1", - "make-fetch-happen": "^14.0.0", - "minipass": "^7.0.2", - "minipass-fetch": "^4.0.0", - "minizlib": "^3.0.1", - "npm-package-arg": "^12.0.0", - "proc-log": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/npm-registry-fetch/node_modules/minizlib": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/npm/node_modules/npm-user-validate": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "BSD-2-Clause", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/p-map": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/package-json-from-dist": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/npm/node_modules/pacote": { - "version": "19.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^6.0.0", - "@npmcli/installed-package-contents": "^3.0.0", - "@npmcli/package-json": "^6.0.0", - "@npmcli/promise-spawn": "^8.0.0", - "@npmcli/run-script": "^9.0.0", - "cacache": "^19.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^7.0.2", - "npm-package-arg": "^12.0.0", - "npm-packlist": "^9.0.0", - "npm-pick-manifest": "^10.0.0", - "npm-registry-fetch": "^18.0.0", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1", - "sigstore": "^3.0.0", - "ssri": "^12.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "bin/index.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/parse-conflict-json": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "just-diff": "^6.0.0", - "just-diff-apply": "^5.2.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/path-key": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/path-scurry": { - "version": "1.11.1", - "dev": true, - "inBundle": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm/node_modules/proc-log": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/proggy": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/promise-all-reject-late": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-call-limit": { - "version": "3.0.2", - "dev": true, - "inBundle": true, - "license": "ISC", - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/promise-inflight": { - "version": "1.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/promise-retry": { - "version": "2.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/promzard": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "read": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/qrcode-terminal": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "bin": { - "qrcode-terminal": "bin/qrcode-terminal.js" - } - }, - "node_modules/npm/node_modules/read": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "mute-stream": "^2.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/read-cmd-shim": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/read-package-json-fast": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^4.0.0", - "npm-normalize-package-bin": "^4.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/retry": { - "version": "0.12.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/npm/node_modules/rimraf": { - "version": "5.0.10", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/safer-buffer": { - "version": "2.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "optional": true - }, - "node_modules/npm/node_modules/semver": { - "version": "7.6.3", - "dev": true, - "inBundle": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/shebang-command": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/shebang-regex": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/signal-exit": { - "version": "4.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/npm/node_modules/sigstore": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.0.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "@sigstore/sign": "^3.0.0", - "@sigstore/tuf": "^3.0.0", - "@sigstore/verify": "^2.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/bundle": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/core": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/sign": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.0.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2", - "make-fetch-happen": "^14.0.1", - "proc-log": "^5.0.0", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/sigstore/node_modules/@sigstore/verify": { - "version": "2.0.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^3.0.0", - "@sigstore/core": "^2.0.0", - "@sigstore/protobuf-specs": "^0.3.2" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/smart-buffer": { - "version": "4.2.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks": { - "version": "2.8.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ip-address": "^9.0.5", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/npm/node_modules/socks-proxy-agent": { - "version": "8.0.4", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.1", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/npm/node_modules/spdx-correct": { - "version": "3.2.0", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-exceptions": { - "version": "2.5.0", - "dev": true, - "inBundle": true, - "license": "CC-BY-3.0" - }, - "node_modules/npm/node_modules/spdx-expression-parse": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/spdx-license-ids": { - "version": "3.0.20", - "dev": true, - "inBundle": true, - "license": "CC0-1.0" - }, - "node_modules/npm/node_modules/sprintf-js": { - "version": "1.1.3", - "dev": true, - "inBundle": true, - "license": "BSD-3-Clause" - }, - "node_modules/npm/node_modules/ssri": { - "version": "12.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/string-width": { - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi": { - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/supports-color": { - "version": "9.4.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/npm/node_modules/tar": { - "version": "6.2.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/npm/node_modules/text-table": { - "version": "0.2.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/tiny-relative-date": { - "version": "1.3.0", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/treeverse": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm/node_modules/tuf-js": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "3.0.1", - "debug": "^4.3.6", - "make-fetch-happen": "^14.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/tuf-js/node_modules/@tufjs/models": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "2.0.0", - "minimatch": "^9.0.5" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/unique-filename": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^5.0.0" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/unique-slug": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/util-deprecate": { - "version": "1.0.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/validate-npm-package-license": { - "version": "3.0.4", - "dev": true, - "inBundle": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/npm/node_modules/validate-npm-package-name": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/walk-up-path": { - "version": "3.0.1", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/npm/node_modules/which": { - "version": "5.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/which/node_modules/isexe": { - "version": "3.1.1", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": ">=16" - } - }, - "node_modules/npm/node_modules/wrap-ansi": { - "version": "8.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "6.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "9.2.2", - "dev": true, - "inBundle": true, - "license": "MIT" - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { - "version": "5.1.2", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "7.1.0", - "dev": true, - "inBundle": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/npm/node_modules/write-file-atomic": { - "version": "6.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/npm/node_modules/yallist": { - "version": "4.0.0", - "dev": true, - "inBundle": true, - "license": "ISC" - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", - "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^3.3.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^6.0.2", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/nyc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/nyc/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/nyc/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nyc/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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/object-is": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", - "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/observable-webworkers": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/observable-webworkers/-/observable-webworkers-2.0.1.tgz", - "integrity": "sha512-JI1vB0u3pZjoQKOK1ROWzp0ygxSi7Yb0iR+7UNsw4/Zn4cQ0P3R7XL38zac/Dy2tEA7Lg88/wIJTjF8vYXZ0uw==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "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/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.2.0.tgz", - "integrity": "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "cli-cursor": "^5.0.0", - "cli-spinners": "^2.9.2", - "is-interactive": "^2.0.0", - "is-unicode-supported": "^2.0.0", - "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.2", - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true, - "license": "MIT" - }, - "node_modules/ora/node_modules/log-symbols": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-6.0.0.tgz", - "integrity": "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.3.0", - "is-unicode-supported": "^1.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/log-symbols/node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-defer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-4.0.1.tgz", - "integrity": "sha512-Mr5KC5efvAK5VUptYEIopP1bakB85k2IWXaRC0rsh1uwn1L6M0LVml8OIQ4Gudg4oyZakf7FmeRLkMMtZW1i5A==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-each-series": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", - "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-event": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-6.0.1.tgz", - "integrity": "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-filter": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-4.1.0.tgz", - "integrity": "sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-map": "^7.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-is-promise": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", - "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", - "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.3.tgz", - "integrity": "sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz", - "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-reduce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", - "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-retry": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", - "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.2", - "is-network-error": "^1.0.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=16.17" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-tap": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-tap/-/p-tap-3.1.0.tgz", - "integrity": "sha512-xJSaeByOOQu5GnHEcnrxMkNi8O3Ez5X1wz8RT6wiL3mJFd4oXcSOvcKq+1CFUtuVYTSTWL/8rlkaCJRoR+L+NA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-timeout": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", - "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-wait-for": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/p-wait-for/-/p-wait-for-5.0.2.tgz", - "integrity": "sha512-lwx6u1CotQYPVju77R+D0vFomni/AqRfqLmqQ8hekklqZ6gAY9rONh7lBQ0uxWMkC2AuX9b2DVAl8To0NyP1JA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-timeout": "^6.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/package-json": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz", - "integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ky": "^1.2.0", - "registry-auth-token": "^5.0.2", - "registry-url": "^6.0.1", - "semver": "^7.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/parent-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", - "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/parse-imports": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", - "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", - "dev": true, - "license": "Apache-2.0 AND MIT", - "dependencies": { - "es-module-lexer": "^1.5.3", - "slashes": "^3.0.12" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true, - "license": "MIT" - }, - "node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse5": "^6.0.1" - } - }, - "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/pascalcase": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-2.0.0.tgz", - "integrity": "sha512-DHpENy5Qm/FaX+x3iBLoMLG/XHNCTgL+yErm1TwuVaj6u4fiOSkYkf60vGtITk7hrKHOO4uCl9vRrD4hqjNKjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.2.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/patch-package": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-6.5.1.tgz", - "integrity": "sha512-I/4Zsalfhc6bphmJTlrLoOcAF87jcxko4q0qsv4bGcurbr8IskEOtdnt9iCmsQVGL1B+iUhSQqweyTLJfCF9rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^4.1.2", - "cross-spawn": "^6.0.5", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^9.0.0", - "is-ci": "^2.0.0", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.6", - "open": "^7.4.2", - "rimraf": "^2.6.3", - "semver": "^5.6.0", - "slash": "^2.0.0", - "tmp": "^0.0.33", - "yaml": "^1.10.2" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "node": ">=10", - "npm": ">5" - } - }, - "node_modules/patch-package/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/patch-package/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/patch-package/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/patch-package/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/patch-package/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/patch-package/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/patch-package/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/patch-package/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/patch-package/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/patch-package/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/patch-package/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/patch-package/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/patch-package/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/patch-package/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "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/pico-signals": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pico-signals/-/pico-signals-1.0.0.tgz", - "integrity": "sha512-Av5eg3cMtXbQVxVoIpP+dzHMBisRZuZy3htFWyaGGScT94AdfeT0On/QVhFNQhIMiY7aLi21W4pD+5KdWbEBUw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", - "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "load-json-file": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-conf/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", - "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-up/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-up/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/playwright-core": { - "version": "1.50.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.50.1.tgz", - "integrity": "sha512-ra9fsNWayuYumt+NiM069M6OkcRb1FZSK8bgi66AtpFoWkg2+y0bJSNmkFrWhMbEBbVKC/EruAHH3g0zmtwGmQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test": { - "version": "14.1.9", - "resolved": "https://registry.npmjs.org/playwright-test/-/playwright-test-14.1.9.tgz", - "integrity": "sha512-L6HkKrcaW+qhaIPPOsoR1HDDR3bQdKeQCcpLkCbebZDG1ikSzMwmF3HAcEtAUXbmRwZcvB1dPoxQi6jlCF/f+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "acorn-loose": "^8.3.0", - "assert": "^2.1.0", - "buffer": "^6.0.3", - "c8": "^10.1.3", - "camelcase": "^8.0.0", - "chokidar": "^3.6.0", - "cpy": "^11.0.0", - "esbuild": "0.23.0", - "esbuild-plugin-wasm": "^1.1.0", - "events": "^3.3.0", - "execa": "^9.3.0", - "exit-hook": "^4.0.0", - "globby": "^14.0.2", - "kleur": "^4.1.5", - "lilconfig": "^3.1.3", - "lodash": "^4.17.21", - "merge-options": "^3.0.4", - "nanoid": "^5.0.9", - "ora": "^8.0.1", - "p-timeout": "^6.1.4", - "path-browserify": "^1.0.1", - "playwright-core": "1.50.1", - "polka": "^0.5.2", - "premove": "^4.0.0", - "process": "^0.11.10", - "sade": "^1.8.1", - "sirv": "^3.0.0", - "source-map": "0.6.1", - "source-map-support": "^0.5.21", - "stream-browserify": "^3.0.0", - "tempy": "^3.1.0", - "test-exclude": "^7.0.1", - "util": "^0.12.5", - "v8-to-istanbul": "^9.3.0" - }, - "bin": { - "playwright-test": "cli.js", - "pw-test": "cli.js" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/aix-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", - "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/android-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", - "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/android-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", - "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/android-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", - "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/darwin-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", - "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/darwin-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", - "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/freebsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", - "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/freebsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", - "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-arm": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", - "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", - "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", - "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-loong64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", - "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-mips64el": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", - "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-ppc64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", - "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-riscv64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", - "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-s390x": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", - "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/linux-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", - "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/netbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", - "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/openbsd-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", - "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/openbsd-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", - "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/sunos-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", - "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/win32-arm64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", - "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/win32-ia32": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", - "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@esbuild/win32-x64": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", - "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/playwright-test/node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/esbuild": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", - "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.23.0", - "@esbuild/android-arm": "0.23.0", - "@esbuild/android-arm64": "0.23.0", - "@esbuild/android-x64": "0.23.0", - "@esbuild/darwin-arm64": "0.23.0", - "@esbuild/darwin-x64": "0.23.0", - "@esbuild/freebsd-arm64": "0.23.0", - "@esbuild/freebsd-x64": "0.23.0", - "@esbuild/linux-arm": "0.23.0", - "@esbuild/linux-arm64": "0.23.0", - "@esbuild/linux-ia32": "0.23.0", - "@esbuild/linux-loong64": "0.23.0", - "@esbuild/linux-mips64el": "0.23.0", - "@esbuild/linux-ppc64": "0.23.0", - "@esbuild/linux-riscv64": "0.23.0", - "@esbuild/linux-s390x": "0.23.0", - "@esbuild/linux-x64": "0.23.0", - "@esbuild/netbsd-x64": "0.23.0", - "@esbuild/openbsd-arm64": "0.23.0", - "@esbuild/openbsd-x64": "0.23.0", - "@esbuild/sunos-x64": "0.23.0", - "@esbuild/win32-arm64": "0.23.0", - "@esbuild/win32-ia32": "0.23.0", - "@esbuild/win32-x64": "0.23.0" - } - }, - "node_modules/playwright-test/node_modules/execa": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.3", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.0", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/playwright-test/node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/human-signals": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", - "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/playwright-test/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/playwright-test/node_modules/util": { - "version": "0.12.5", - "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", - "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "which-typed-array": "^1.1.2" - } - }, - "node_modules/please-upgrade-node": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", - "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver-compare": "^1.0.0" - } - }, - "node_modules/plur": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", - "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "irregular-plurals": "^3.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/polka": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/polka/-/polka-0.5.2.tgz", - "integrity": "sha512-FVg3vDmCqP80tOrs+OeNlgXYmFppTXdjD5E7I4ET1NjvtNmQrb1/mJibybKkb/d4NA7YWAr1ojxuhpL3FHqdlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@polka/url": "^0.5.0", - "trouter": "^2.0.1" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/premove": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/premove/-/premove-4.0.0.tgz", - "integrity": "sha512-zim/Hr4+FVdCIM7zL9b9Z0Wfd5Ya3mnKtiuDv7L5lzYzanSq6cOcVJ7EFcgK4I0pt28l8H0jX/x3nyog380XgQ==", - "dev": true, - "license": "MIT", - "bin": { - "premove": "bin.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/pretty-ms": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz", - "integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "license": "MIT" - }, - "node_modules/process-on-spawn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz", - "integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/progress-events": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/progress-events/-/progress-events-1.0.1.tgz", - "integrity": "sha512-MOzLIwhpt64KIVN64h1MwdKWiyKFNc/S6BoYKPIVUHFg0/eIEyBulhWCgn678v/4c0ri3FdGuzXymNCv02MUIw==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/prompt": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", - "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@colors/colors": "1.5.0", - "async": "3.2.3", - "read": "1.0.x", - "revalidator": "0.1.x", - "winston": "2.x" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/prompt/node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", - "dev": true, - "license": "MIT" - }, - "node_modules/proper-lockfile": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", - "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "retry": "^0.12.0", - "signal-exit": "^3.0.2" - } - }, - "node_modules/proper-lockfile/node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/proper-lockfile/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true, - "license": "ISC" - }, - "node_modules/protons-runtime": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/protons-runtime/-/protons-runtime-5.5.0.tgz", - "integrity": "sha512-EsALjF9QsrEk6gbCx3lmfHxVN0ah7nG3cY7GySD4xf4g8cr7g543zB88Foh897Sr1RQJ9yDCUsoT1i1H/cVUFA==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8-varint": "^2.0.2", - "uint8arraylist": "^2.4.3", - "uint8arrays": "^5.0.1" - } - }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "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/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/race-event": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/race-event/-/race-event-1.3.0.tgz", - "integrity": "sha512-kaLm7axfOnahIqD3jQ4l1e471FIFcEGebXEnhxyLscuUzV8C94xVHtWEqDDXxll7+yu/6lW0w1Ff4HbtvHvOHg==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/race-signal": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/race-signal/-/race-signal-1.1.3.tgz", - "integrity": "sha512-Mt2NznMgepLfORijhQMncE26IhkmjEphig+/1fKC0OtaKwys/gpvpmswSjoN01SS+VO951mj0L4VIDXdXsjnfA==", - "license": "Apache-2.0 OR MIT" - }, - "node_modules/ramda": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", - "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==", - "dev": true, - "license": "MIT" - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "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)", - "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/rc/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" - }, - "node_modules/rc/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", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-native-test-runner": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/react-native-test-runner/-/react-native-test-runner-5.0.0.tgz", - "integrity": "sha512-/ztZUqRqV98/lLbGN781egGXjkR8i7MhfAm7nGtKe1DoDuITkvQk/4fF/nXfDyZEtaae9NYuv2MocUR/qcN1bQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-proposal-async-generator-functions": "^7.12.12", - "babel-plugin-transform-inline-environment-variables": "^0.4.3", - "chai": "^4.2.0", - "execa": "^4.1.0", - "find-up": "^5.0.0", - "fs-extra": "^9.0.1", - "globby": "^11.0.1", - "is-ci": "^2.0.0", - "is-uuid": "^1.0.2", - "lilconfig": "^2.0.2", - "meow": "^8.0.0", - "merge-options": "^3.0.4", - "metro-react-native-babel-preset": "^0.64.0", - "ora": "^5.1.0", - "p-retry": "^4.2.0", - "p-tap": "^3.1.0", - "patch-package": "^6.2.2", - "pico-signals": "^1.0.0", - "read-pkg": "^5.2.0", - "semver": "^7.3.4", - "tempy": "^1.0.0", - "yn": "^4.0.0" - }, - "bin": { - "rn-test": "cli/index.js" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/react-native-test-runner/node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/react-native-test-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/react-native-test-runner/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/react-native-test-runner/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-test-runner/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/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/react-native-test-runner/node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/react-native-test-runner/node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-test-runner/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/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/react-native-test-runner/node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/react-native-test-runner/node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/react-native-test-runner/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/react-native-test-runner/node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/react-native-test-runner/node_modules/read-pkg/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/react-native-test-runner/node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/react-native-test-runner/node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/react-native-test-runner/node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/node_modules/tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/react-native-test-runner/node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/react-native-test-runner/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/react-native-test-runner/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/react-refresh": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.4.3.tgz", - "integrity": "sha512-Hwln1VNuGl/6bVwnd0Xdn1e84gT/8T9aYNL+HAKDArLCS7LWjwr7StE30IEYbIkx0Vi3vs+coQxe+SQDbGbbpA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "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/read-package-up": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/read-package-up/-/read-package-up-11.0.0.tgz", - "integrity": "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0", - "read-pkg": "^9.0.0", - "type-fest": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-9.0.1.tgz", - "integrity": "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.3", - "normalize-package-data": "^6.0.0", - "parse-json": "^8.0.0", - "type-fest": "^4.6.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-11.0.0.tgz", - "integrity": "sha512-LOVbvF1Q0SZdjClSefZ0Nz5z8u+tIE7mV5NibzmE9VYmDe9CaBbAVtz1veOSZbofrdsilxuDAYnFenukZVp8/Q==", - "deprecated": "Renamed to read-package-up", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up-simple": "^1.0.0", - "read-pkg": "^9.0.0", - "type-fest": "^4.6.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/parse-json": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.2.0.tgz", - "integrity": "sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.26.2", - "index-to-position": "^1.0.0", - "type-fest": "^4.37.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg/node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true, - "license": "MIT" - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", - "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/registry-auth-token": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", - "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pnpm/npm-conf": "^2.1.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "rc": "1.2.8" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "jsesc": "~3.0.2" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "license": "ISC", - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true, - "license": "ISC" - }, - "node_modules/require-package-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/require-package-name/-/require-package-name-2.0.1.tgz", - "integrity": "sha512-uuoJ1hU/k6M0779t3VMVIYpb2VMJk05cehCaABFhXaibcbvfgR8wKiozLjVFSzJPmQMRqIcO0HMyTFqfV09V6Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/requireindex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", - "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.5" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor/node_modules/mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/revalidator": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", - "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", - "dev": true, - "license": "Apache 2.0", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/rimraf": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", - "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^11.0.0", - "package-json-from-dist": "^1.0.0" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz", - "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/jackspeak": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", - "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", - "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/roarr/node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "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", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/rxjs": { - "version": "6.6.7", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", - "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^1.9.0" - }, - "engines": { - "npm": ">=2.0.0" - } - }, - "node_modules/rxjs/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/sade": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", - "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/semantic-release": { - "version": "24.2.3", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.3.tgz", - "integrity": "sha512-KRhQG9cUazPavJiJEFIJ3XAMjgfd0fcK3B+T26qOl8L0UG5aZUjeRfREO0KM5InGtYwxqiiytkJrbcYoLDEv0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@semantic-release/commit-analyzer": "^13.0.0-beta.1", - "@semantic-release/error": "^4.0.0", - "@semantic-release/github": "^11.0.0", - "@semantic-release/npm": "^12.0.0", - "@semantic-release/release-notes-generator": "^14.0.0-beta.1", - "aggregate-error": "^5.0.0", - "cosmiconfig": "^9.0.0", - "debug": "^4.0.0", - "env-ci": "^11.0.0", - "execa": "^9.0.0", - "figures": "^6.0.0", - "find-versions": "^6.0.0", - "get-stream": "^6.0.0", - "git-log-parser": "^1.2.0", - "hook-std": "^3.0.0", - "hosted-git-info": "^8.0.0", - "import-from-esm": "^2.0.0", - "lodash-es": "^4.17.21", - "marked": "^12.0.0", - "marked-terminal": "^7.0.0", - "micromatch": "^4.0.2", - "p-each-series": "^3.0.0", - "p-reduce": "^3.0.0", - "read-package-up": "^11.0.0", - "resolve-from": "^5.0.0", - "semver": "^7.3.2", - "semver-diff": "^4.0.0", - "signale": "^1.2.1", - "yargs": "^17.5.1" - }, - "bin": { - "semantic-release": "bin/semantic-release.js" - }, - "engines": { - "node": ">=20.8.1" - } - }, - "node_modules/semantic-release-monorepo": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/semantic-release-monorepo/-/semantic-release-monorepo-8.0.2.tgz", - "integrity": "sha512-TQC6KKIA0ATjii1OT0ZmQqcVzBJoaetJaJBC8FmKkg1IbDR4wBsuX6gl6UHDdijRDl8YyXqahj2hkJNyV6m9Jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "execa": "^5.1.1", - "file-url": "^3.0.0", - "fs-extra": "^10.0.1", - "get-stream": "^6.0.1", - "git-log-parser": "^1.2.0", - "p-each-series": "^2.1.0", - "p-limit": "^3.1.0", - "pkg-up": "^3.1.0", - "ramda": "^0.27.2", - "read-pkg": "^5.2.0", - "semantic-release-plugin-decorators": "^4.0.0", - "tempy": "1.0.1" - }, - "peerDependencies": { - "semantic-release": ">=22.0.7" - } - }, - "node_modules/semantic-release-monorepo/node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release-monorepo/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/semantic-release-monorepo/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/semantic-release-monorepo/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/semantic-release-monorepo/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/semantic-release-monorepo/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/semantic-release-monorepo/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/semantic-release-monorepo/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release-monorepo/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release-monorepo/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/semantic-release-monorepo/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/semantic-release-monorepo/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/semantic-release-monorepo/node_modules/temp-dir": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", - "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release-monorepo/node_modules/tempy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-1.0.1.tgz", - "integrity": "sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "del": "^6.0.0", - "is-stream": "^2.0.0", - "temp-dir": "^2.0.0", - "type-fest": "^0.16.0", - "unique-string": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/tempy/node_modules/type-fest": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", - "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-monorepo/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release-monorepo/node_modules/unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "dev": true, - "license": "MIT", - "dependencies": { - "crypto-random-string": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/semantic-release-monorepo/node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release-plugin-decorators": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/semantic-release-plugin-decorators/-/semantic-release-plugin-decorators-4.0.0.tgz", - "integrity": "sha512-5eqaITbgGJu7AWCqY/ZwDh3TCS84Q9i470AImwP9vw3YcFRyR8sEb499Zbnqa076bv02yFUn88GtloQMXQsBrg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "semantic-release": ">20" - } - }, - "node_modules/semantic-release/node_modules/@semantic-release/error": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", - "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/semantic-release/node_modules/@sindresorhus/merge-streams": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", - "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/aggregate-error": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-5.0.0.tgz", - "integrity": "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^5.2.0", - "indent-string": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/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/semantic-release/node_modules/clean-stack": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-5.2.0.tgz", - "integrity": "sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/cosmiconfig": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", - "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.1", - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - }, - "peerDependencies": { - "typescript": ">=4.9.5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/semantic-release/node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/semantic-release/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/execa": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", - "integrity": "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/merge-streams": "^4.0.0", - "cross-spawn": "^7.0.3", - "figures": "^6.1.0", - "get-stream": "^9.0.0", - "human-signals": "^8.0.0", - "is-plain-obj": "^4.1.0", - "is-stream": "^4.0.1", - "npm-run-path": "^6.0.0", - "pretty-ms": "^9.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^4.0.0", - "yoctocolors": "^2.0.0" - }, - "engines": { - "node": "^18.19.0 || >=20.5.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/semantic-release/node_modules/execa/node_modules/get-stream": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", - "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sec-ant/readable-stream": "^0.4.1", - "is-stream": "^4.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/figures": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", - "integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/hosted-git-info": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.2.tgz", - "integrity": "sha512-sYKnA7eGln5ov8T8gnYlkSOxFJvywzEx9BueN6xo/GKO8PGiI6uK6xx+DIGe45T3bdVjLAQDQW1aicT8z8JwQg==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^10.0.1" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/semantic-release/node_modules/human-signals": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", - "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/semantic-release/node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/is-stream": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", - "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/semantic-release/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/semantic-release/node_modules/npm-run-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", - "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^4.0.0", - "unicorn-magic": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/p-reduce": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", - "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semantic-release/node_modules/strip-final-newline": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", - "integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "license": "MIT" - }, - "node_modules/semver-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", - "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/semver-regex": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", - "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/shiki": { - "version": "0.14.7", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", - "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-sequence-parser": "^1.1.0", - "jsonc-parser": "^3.2.0", - "vscode-oniguruma": "^1.7.0", - "vscode-textmate": "^8.0.0" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "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.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "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/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/signale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", - "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^2.3.2", - "figures": "^2.0.0", - "pkg-conf": "^2.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/signale/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/signale/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/signale/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/signale/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/signale/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/signale/node_modules/figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/signale/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/signale/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/sinon": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-20.0.0.tgz", - "integrity": "sha512-+FXOAbdnj94AQIxH0w1v8gzNxkawVvNqE3jUzRLptR71Oykeu2RrQXXl/VQjKay+Qnh73fDt/oDfMo6xMeDQbQ==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon-ts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sinon-ts/-/sinon-ts-2.0.0.tgz", - "integrity": "sha512-fhwqbvf8Vc2vPr0TWUHbdKI/Y/q0nNSN6MLMCYYELFsQ2Y3M7qekn8CXxjC1URcjFk+H9c63lif7hKFBRSpWOg==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "peerDependencies": { - "sinon": "*" - } - }, - "node_modules/sirv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.1.tgz", - "integrity": "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/sirv/node_modules/@polka/url": { - "version": "1.0.0-next.28", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", - "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", - "dev": true, - "license": "MIT" - }, - "node_modules/skin-tone": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", - "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "unicode-emoji-modifier-base": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slashes": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", - "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", - "dev": true, - "license": "ISC" - }, - "node_modules/slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha512-up04hB2hR92PgjpyU3y/eg91yIBILyjVY26NvvciY3EVVPjybkMszMpXQ9QAkcS3I5rtJBDLoTxxg+qvW8c7rw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spawn-error-forwarder": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", - "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", - "dev": true, - "license": "MIT" - }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spawn-wrap/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/spawn-wrap/node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/spawn-wrap/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "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/spawn-wrap/node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/spawn-wrap/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/spawn-wrap/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/spawn-wrap/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/spawn-wrap/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-correct/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", - "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.21", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz", - "integrity": "sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/split2": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", - "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", - "dev": true, - "license": "ISC", - "dependencies": { - "through2": "~2.0.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/stdin-discarder": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.2.2.tgz", - "integrity": "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stream-browserify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", - "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "~2.0.4", - "readable-stream": "^3.5.0" - } - }, - "node_modules/stream-browserify/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", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/stream-combiner2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", - "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-5.0.0.tgz", - "integrity": "sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.1.tgz", - "integrity": "sha512-0fk9zBqO67Nq5M/m45qHCJxylV/DhBlIOVExqgOMiCCrzrhU6tCibRXNqE3jwJLftzE9SNuZtYbpzcO+i9FiKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-outer/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/strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - }, - "bin": { - "sl-log-transformer": "bin/sl-log-transformer.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/super-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-1.0.0.tgz", - "integrity": "sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-timeout": "^1.0.1", - "time-span": "^5.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", - "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=14.18" - }, - "funding": { - "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/symbol-observable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", - "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/unts" - } - }, - "node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.16" - } - }, - "node_modules/tempy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", - "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-stream": "^3.0.0", - "temp-dir": "^3.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/test-exclude": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", - "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^10.4.1", - "minimatch": "^9.0.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/time-span": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz", - "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "convert-hrtime": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", - "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.3", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.3", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", - "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tldts": { - "version": "6.1.85", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.85.tgz", - "integrity": "sha512-gBdZ1RjCSevRPFix/hpaUWeak2/RNUZB4/8frF1r5uYMHjFptkiT0JXIebWvgI/0ZHXvxaUDDJshiA0j6GdL3w==", - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.85" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.85", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.85.tgz", - "integrity": "sha512-DTjUVvxckL1fIoPSb3KE7ISNtkWSawZdpfxGxwiIrZoO6EbHVDXXUIlIuWympPaeS+BLGyggozX/HTMsRAdsoA==", - "license": "MIT" - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", - "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/traverse": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz", - "integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/trim-repeated/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/trouter": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/trouter/-/trouter-2.0.1.tgz", - "integrity": "sha512-kr8SKKw94OI+xTGOkfsvwZQ8mWoikZDd2n8XZHjJVZUARZT+4/VV6cacRS6CLsH9bNm+HFIPU1Zx4CnNnb4qlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "matchit": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/ts-node/node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/tsconfig": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-7.0.0.tgz", - "integrity": "sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/strip-bom": "^3.0.0", - "@types/strip-json-comments": "0.0.30", - "strip-bom": "^3.0.0", - "strip-json-comments": "^2.0.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/tsconfig/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", - "engines": { - "node": ">=0.10.0" - } - }, - "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/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils-etc": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/tsutils-etc/-/tsutils-etc-1.4.2.tgz", - "integrity": "sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs": "^17.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "ts-flags": "bin/ts-flags", - "ts-kind": "bin/ts-kind" - }, - "peerDependencies": { - "tsutils": "^3.0.0", - "typescript": ">=4.0.0" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "4.38.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.38.0.tgz", - "integrity": "sha512-2dBz5D5ycHIoliLYLi0Q2V7KRaDlH0uWIvmk7TYlAg5slqwiPv1ezJdZm1QEM0xgk29oYWMCbIG7E6gHpvChlg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typedoc": { - "version": "0.25.13", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", - "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.3.0", - "minimatch": "^9.0.3", - "shiki": "^0.14.7" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 16" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x" - } - }, - "node_modules/typedoc-plugin-mdn-links": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-3.3.8.tgz", - "integrity": "sha512-Aewg+SW7hBdffRpT6WnpRwWthoaF9irlzXDKRyvcDVekPZSFujOlh690SV6eCgqrtP7GBJmN0TVeJUq6+6rb1w==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typedoc": ">= 0.23.14 || 0.24.x || 0.25.x || 0.26.x" - } - }, - "node_modules/typedoc-plugin-missing-exports": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-2.3.0.tgz", - "integrity": "sha512-iI9ITNNLlbsLCBBeYDyu0Qqp3GN/9AGyWNKg8bctRXuZEPT7G1L+0+MNWG9MsHcf/BFmNbXL0nQ8mC/tXRicog==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typedoc": "0.24.x || 0.25.x" - } - }, - "node_modules/typedoc/node_modules/marked": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", - "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", - "dev": true, - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-docs-verifier": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/typescript-docs-verifier/-/typescript-docs-verifier-2.5.3.tgz", - "integrity": "sha512-fATV69QQZzIQWDGfUzo2USUcUTK0hPqTm7XZuyHf4QOkZUshnkwDk8TEk2IxaIlHxKjbM+5RtyDgxCtKYycjXA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "chalk": "^4.1.2", - "fs-extra": "^10.0.0", - "ora": "^5.4.1", - "strip-ansi": "^7.0.1", - "ts-node": "^10.8.1", - "tsconfig": "^7.0.0", - "yargs": "^17.5.1" - }, - "bin": { - "typescript-docs-verifier": "dist/bin/compile-typescript-docs.js" - }, - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "typescript": ">3.8.3" - } - }, - "node_modules/typescript-docs-verifier/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/typescript-docs-verifier/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript-docs-verifier/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/typescript-docs-verifier/node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript-docs-verifier/node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript-docs-verifier/node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript-docs-verifier/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/typescript-docs-verifier/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript-docs-verifier/node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript-docs-verifier/node_modules/ora/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript-docs-verifier/node_modules/ora/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript-docs-verifier/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/typescript-docs-verifier/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/typescript-docs-verifier/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/uint8-varint": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/uint8-varint/-/uint8-varint-2.0.4.tgz", - "integrity": "sha512-FwpTa7ZGA/f/EssWAb5/YV6pHgVF1fViKdW8cWaEarjB8t7NyofSWBdOTyFPaGuUG4gx3v1O3PQ8etsiOs3lcw==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arraylist": "^2.0.0", - "uint8arrays": "^5.0.0" - } - }, - "node_modules/uint8arraylist": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/uint8arraylist/-/uint8arraylist-2.4.8.tgz", - "integrity": "sha512-vc1PlGOzglLF0eae1M8mLRTBivsvrGsdmJ5RbK3e+QRvRLOZfZhQROTwH/OfyF3+ZVUg9/8hE8bmKP2CvP9quQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "uint8arrays": "^5.0.1" - } - }, - "node_modules/uint8arrays": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/uint8arrays/-/uint8arrays-5.1.0.tgz", - "integrity": "sha512-vA6nFepEmlSKkMBnLBaUMVvAC4G3CTmO58C12y4sq6WPDOR7mOFYOi7GlrQ4djeSbP6JG9Pv9tJDM97PedRSww==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "multiformats": "^13.0.0" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici": { - "version": "6.21.2", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.2.tgz", - "integrity": "sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==", - "license": "MIT", - "engines": { - "node": ">=18.17" - } - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-emoji-modifier-base": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", - "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/universal-user-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", - "integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-join": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", - "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "2.0.3" - } - }, - "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" - }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", - "dev": true, - "license": "ISC" - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "license": "MIT" - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/vscode-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/weald": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/weald/-/weald-1.0.4.tgz", - "integrity": "sha512-+kYTuHonJBwmFhP1Z4YQK/dGi3jAnJGCYhyODFpHK73rbxnp9lnZQj7a2m+WVgn8fXr5bJaxUpF6l8qZpPeNWQ==", - "license": "Apache-2.0 OR MIT", - "dependencies": { - "ms": "^3.0.0-canary.1", - "supports-color": "^9.4.0" - } - }, - "node_modules/weald/node_modules/ms": { - "version": "3.0.0-canary.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-3.0.0-canary.1.tgz", - "integrity": "sha512-kh8ARjh8rMN7Du2igDRO9QJnqCb2xYTJxyQYK7vJJS4TvLLmsbyhiKpSW+t+y26gyOyMd0riphX0GeWKU3ky5g==", - "license": "MIT", - "engines": { - "node": ">=12.13" - } - }, - "node_modules/weald/node_modules/supports-color": { - "version": "9.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz", - "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/wherearewe": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wherearewe/-/wherearewe-2.0.1.tgz", - "integrity": "sha512-XUguZbDxCA2wBn2LoFtcEhXL6AXo+hVjGonwhSTTTU9SzbWG8Xu3onNIpzf9j/mYUcJQ0f+m37SzG77G851uFw==", - "dev": true, - "license": "Apache-2.0 OR MIT", - "dependencies": { - "is-electron": "^2.2.0" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/which": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", - "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/which-typed-array": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", - "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/winston": { - "version": "2.4.7", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", - "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^2.6.4", - "colors": "1.0.x", - "cycle": "1.0.x", - "eyes": "0.1.x", - "isstream": "0.1.x", - "stack-trace": "0.0.x" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/winston/node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/wrap-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", - "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "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/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/xdg-basedir": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", - "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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/yn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-4.0.0.tgz", - "integrity": "sha512-huWiiCS4TxKc4SfgmTwW1K7JmXPPAmuXWYy4j9qjQo4+27Kni8mGhAAi1cloRWmBe2EqcLgt3IGqQoRL/MtPgg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", - "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/package.json b/package.json index 8d75055..4b69c55 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { - "name": "@libp2p/http-fetch", - "version": "2.2.2", - "description": "Implementation of the WHATWG Fetch API on libp2p streams", - "author": "@marcopolo", + "name": "@libp2p/http", + "version": "0.0.0", + "description": "Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP", "license": "Apache-2.0 OR MIT", "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", "repository": { @@ -53,9 +52,9 @@ "types": "./dist/src/ping.d.ts", "import": "./dist/src/ping.js" }, - "./well-known-handler": { - "types": "./dist/src/well-known-handler.d.ts", - "import": "./dist/src/well-known-handler.js" + "./servers/node": { + "types": "./dist/src/servers/node.d.ts", + "import": "./dist/src/servers/node.js" } }, "eslintConfig": { @@ -152,15 +151,16 @@ }, "scripts": { "build": "aegir build", - "test": "aegir test", "clean": "aegir clean", "lint": "aegir lint", + "test": "aegir test", "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", + "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", "test:webkit": "aegir test -t browser -- --browser webkit", "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", "dep-check": "aegir dep-check", "doc-check": "aegir doc-check", "docs": "aegir docs", @@ -172,26 +172,50 @@ "@libp2p/interface": "^2.2.0", "@libp2p/interface-internal": "^2.0.10", "@libp2p/peer-id": "^5.0.7", + "@libp2p/utils": "^6.6.0", "@multiformats/multiaddr": "^12.3.0", "@multiformats/multiaddr-to-uri": "^11.0.0", + "@multiformats/uri-to-multiaddr": "^9.0.1", "http-cookie-agent": "^6.0.7", + "it-byte-stream": "^2.0.1", + "it-queueless-pushable": "^2.0.0", + "it-to-browser-readablestream": "^2.0.10", + "multiformats": "^13.3.2", "p-defer": "^4.0.1", + "race-event": "^1.3.0", + "race-signal": "^1.1.3", "tough-cookie": "^5.0.0", "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8", "uint8arrays": "^5.1.0", - "undici": "^6.21.0" + "undici": "^6.21.2" }, "devDependencies": { - "@libp2p/interface-compliance-tests": "^6.1.8", - "@libp2p/logger": "^5.1.3", + "@chainsafe/libp2p-noise": "^16.1.0", + "@chainsafe/libp2p-yamux": "^7.0.1", + "@fastify/websocket": "^11.0.2", + "@libp2p/memory": "^1.1.4", + "@libp2p/ping": "^2.0.27", + "@libp2p/websockets": "^9.2.8", + "@types/express": "^5.0.1", + "@types/ws": "^8.18.0", "aegir": "^45.0.0", + "express": "^4.21.2", + "fastify": "^5.2.2", "it-pair": "^2.0.6", "libp2p": "^2.2.1", - "sinon-ts": "^2.0.0" + "wherearewe": "^2.0.1", + "ws": "^8.18.1" }, "browser": { - "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js" + "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js", + "./dist/src/http.js": "./dist/src/http.browser.js", + "./dist/src/http/index.js": "./dist/src/http/index.browser.js", + "./dist/test/index.spec.js": "./dist/test/index.browser.spec.js", + "node:events": "events", + "node:stream": "readable-stream", + "node:http": false, + "undici": false }, "sideEffects": false } diff --git a/src/auth/client.ts b/src/auth/client.ts index df69c1e..cf51567 100644 --- a/src/auth/client.ts +++ b/src/auth/client.ts @@ -54,7 +54,7 @@ export interface AuthenticateServerOptions extends AbortOptions { hostname?: AuthenticatedFetchOptions['hostname'] } -interface DoAuthenticatedFetchOptions { +export interface DoAuthenticatedFetchOptions { fetch?: AuthenticatedFetchOptions['fetch'] hostname?: AuthenticatedFetchOptions['hostname'] } diff --git a/src/constants.ts b/src/constants.ts index 696da07..f3949f7 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,2 +1,2 @@ -export const PROTOCOL_NAME = '/http/1.1' +export const PROTOCOL = '/http/1.1' export const WELL_KNOWN_PROTOCOLS = '/.well-known/libp2p/protocols' diff --git a/src/fetch.ts b/src/fetch.ts new file mode 100644 index 0000000..040b6a0 --- /dev/null +++ b/src/fetch.ts @@ -0,0 +1,373 @@ +/* eslint-disable max-depth */ +/* eslint-disable complexity */ + +import { HTTPParser } from '@achingbrain/http-parser-js' +import { multiaddr, protocols } from '@multiformats/multiaddr' +import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' +import defer from 'p-defer' +import { type Uint8ArrayList } from 'uint8arraylist' + +interface Fetch { (req: Request): Promise } + +function getStringMethod (method: number): string { + return HTTPParser.methods[method] ?? 'UNKNOWN' +} + +interface Duplex> { + source: AsyncIterable | Iterable + sink(source: AsyncIterable | Iterable): RSink +} + +let ranDetectionForBrokenReqBody = false +let brokenRequestBody = false + +/** + * Detects if the request body can not be a ReadableStream and should be read in + * full before returning the request This is only an issue in the current version of Firefox. + * + * @returns true if the request body can not be a ReadableStream and should be read in full before returning the request + */ +async function detectBrokenRequestBody (): Promise { + if (ranDetectionForBrokenReqBody) { + return brokenRequestBody + } + ranDetectionForBrokenReqBody = true + const rs = new ReadableStream({ + start (controller) { + controller.enqueue(new Uint8Array([0])) + controller.close() + } + }) + + const req = new Request('https://example.com', { + method: 'POST', + body: rs, + // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit + duplex: 'half' + }) + + const ab = await req.arrayBuffer() + brokenRequestBody = ab.byteLength !== 1 + return brokenRequestBody +} + +/** + * Create a fetch function that can be used to fetch requests via a duplex stream + * + * @returns a function that can be used to fetch requests via a duplex stream + */ +export function fetchViaDuplex (s: Duplex): Fetch { + return async (req) => { + await writeRequestToDuplex(s, req) + const [respP] = readHTTPMsg(false, s) + const resp = await respP + if (!(resp instanceof Response)) { + throw new Error('Expected a response') + } + return resp + } +} + +/** + * A function that can be used to handle HTTP requests + */ +export interface HTTPHandler { (req: Request): Promise } + +/** + * + * @param s - Duplex where the request will be read from and the response will be written to + * @param h - HTTP handler that will be called with the request + */ +export async function handleRequestViaDuplex (s: Duplex, h: HTTPHandler): Promise { + const [reqP] = readHTTPMsg(true, s) + const req = await reqP + if (!(req instanceof Request)) { + throw new Error('Expected a request') + } + + const resp = await h(req) + await writeResponseToDuplex(s, resp) +} + +/** + * Exported for testing. + * + * @param expectRequest - is this a Request or a Response + * @param r - where to read from + * @returns two promises. The first is the parsed Request or Response. The second is a promise that resolves when the parsing is done. + */ +export function readHTTPMsg (expectRequest: boolean, r: Duplex): [Promise, Promise] { + const msgPromise = defer() + + return [ + msgPromise.promise, + (async () => { + const body = new TransformStream() + const writer = body.writable.getWriter() + let messageComplete = false + let fulfilledMsgPromise = false + + const parser = new HTTPParser(expectRequest ? 'REQUEST' : 'RESPONSE') + parser[HTTPParser.kOnHeadersComplete] = (info) => { + fulfilledMsgPromise = true + + // Handle the headers + const headers = new Headers() + + for (let i = 0; i < info.headers.length; i += 2) { + headers.set(info.headers[i], info.headers[i + 1]) + } + + let reqBody: ReadableStream | null = body.readable + + // Headers are parsed. We can return the response + try { + if (expectRequest) { + if (getStringMethod(info.method) === 'GET') { + reqBody = null + } + + const urlWithHost = `https://${headers.get('Host') ?? 'unknown_host._libp2p'}${info.url}` + detectBrokenRequestBody().then(async (broken) => { + let req: Request + if (!broken) { + req = new Request(urlWithHost, { + method: getStringMethod(info.method), + body: reqBody, + headers, + // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit + duplex: 'half' + }) + } else { + if (reqBody === null) { + req = new Request(urlWithHost, { + method: getStringMethod(info.method), + headers + }) + } else { + // Unfortunate workaround for a bug in Firefox's Request implementation. + // They don't support ReadableStream bodies, so we need to read the whole body. + const rdr = reqBody.getReader() + const parts = [] + while (true) { + const { done, value } = await rdr.read() + if (done) { + break + } + if (value !== undefined) { + parts.push(value) + } + } + const totalSize = parts.reduce((acc, part) => acc + part.byteLength, 0) + const body = new Uint8Array(totalSize) + for (let i = 0, offset = 0; i < parts.length; i++) { + body.set(parts[i], offset) + offset += parts[i].byteLength + } + req = new Request(urlWithHost, { + method: getStringMethod(info.method), + body, + headers + }) + } + } + msgPromise.resolve(req) + fulfilledMsgPromise = true + }).catch(err => { + msgPromise.reject(err) + }) + } else { + let respBody: ReadableStream | null = body.readable + if (info.statusCode === 204) { + respBody = null + } + const resp = new Response(respBody, { + headers, + status: info.statusCode, + statusText: info.statusMessage + }) + msgPromise.resolve(resp) + fulfilledMsgPromise = true + } + } catch (error) { + msgPromise.reject(error) + } + } + parser[HTTPParser.kOnBody] = (buf) => { + writer.write(buf) + .catch((err: Error) => { + msgPromise.reject(err) + }) + } + parser[HTTPParser.kOnMessageComplete] = () => { + messageComplete = true + writer.close() + .catch((err: Error) => { + msgPromise.reject(err) + }) + } + + // Consume data + for await (const chunks of r.source) { + const chunk = chunks.subarray() + parser.execute(chunk) + } + + parser.finish() + + if (!messageComplete) { + await writer.abort(new Error('Incomplete HTTP message')) + + if (!fulfilledMsgPromise) { + msgPromise.reject(new Error('Incomplete HTTP message')) + } + } + })() + ] +} + +const multiaddrURIPrefix = 'multiaddr:' +const CRLF = '\r\n' +const encodedCRLF = new TextEncoder().encode(CRLF) +const encodedFinalChunk = new TextEncoder().encode(`0${CRLF}${CRLF}`) +async function writeRequestToDuplex (s: Duplex, request: Request): Promise { + const method = request.method + + let reqUrl = request.url + let path = '' + let urlHost = '' + if (reqUrl.startsWith(multiaddrURIPrefix)) { + reqUrl = reqUrl.substring(multiaddrURIPrefix.length) + const ma = multiaddr(reqUrl) + // Find the http-path component + const [, httpPathVal] = ma.stringTuples().find(([code, value]) => + code === protocols('http-path').code + + ) ?? ['', ''] + path = decodeURIComponent(httpPathVal ?? '') + + try { + const maWithoutPath = ma.decapsulateCode(protocols('http-path').code) + const url = new URL(multiaddrToUri(maWithoutPath)) + urlHost = url.host + } catch {} + } else { + const url = new URL(reqUrl) + urlHost = url.host + path = (url.pathname ?? '') + (url.search ?? '') + } + const headers = request.headers + + if (!path.startsWith('/')) { + path = `/${path}` + } + let httpRequest = `${method} ${path} HTTP/1.1${CRLF}` + + // Add Host header if not present + if (!headers.has('Host') && urlHost !== '') { + httpRequest += `Host: ${urlHost}${CRLF}` + } + // Add connection close + if (!headers.has('Connection')) { + httpRequest += `Connection: close${CRLF}` + } + + headers.forEach((value, name) => { + httpRequest += `${name}: ${value}${CRLF}` + }) + + let reqBody = request.body + if (request.body === undefined && typeof request.arrayBuffer === 'function') { + const body = await request.arrayBuffer() + if (body.byteLength > 0) { + reqBody = new ReadableStream({ + start (controller) { + controller.enqueue(new Uint8Array(body)) + controller.close() + } + }) + } else { + reqBody = null + } + } + + const requestIncludesContentAndNeedsContentLength = reqBody !== null && !headers.has('Content-Length') && (method === 'POST' || method === 'PUT' || method === 'PATCH') + + if (requestIncludesContentAndNeedsContentLength) { + // If we don't have the content length, we need to use chunked encoding + httpRequest += `Transfer-Encoding: chunked${CRLF}` + } + httpRequest += CRLF + + void s.sink((async function * () { + const httpRequestBuffer = new TextEncoder().encode(httpRequest) + yield httpRequestBuffer + + if (reqBody === null || reqBody === undefined) { + return + } + + const reader = reqBody.getReader() + try { + while (true) { + const { done, value } = await reader.read() + // If the stream is done, break the loop + if (done) { + if (requestIncludesContentAndNeedsContentLength) { + yield encodedFinalChunk + } + break + } + + // add the chunk length + if (requestIncludesContentAndNeedsContentLength) { + const chunkLength = value.byteLength.toString(16) + const chunkLengthBuffer = new TextEncoder().encode(`${chunkLength}${CRLF}`) + yield chunkLengthBuffer + } + + yield value + + if (requestIncludesContentAndNeedsContentLength) { + yield encodedCRLF + } + } + } finally { + reader.releaseLock() + } + })()) +} + +async function writeResponseToDuplex (s: Duplex, resp: Response): Promise { + await s.sink((async function * () { + const textEncoder = new TextEncoder() + const status = resp.status + const reason = resp.statusText + const headers = resp.headers + + let httpRequest = `HTTP/1.1 ${status} ${reason}${CRLF}` + + // Add connection close + if (!headers.has('Connection')) { + httpRequest += `Connection: close${CRLF}` + } + + headers.forEach((value, name) => { + httpRequest += `${name}: ${value}${CRLF}` + }) + httpRequest += CRLF + + yield textEncoder.encode(httpRequest) + + if (resp.body !== null && resp.body !== undefined) { + const reader = resp.body.getReader() + while (true) { + const { done, value } = await reader.read() + if (done) { + break + } + yield value + } + } + })()) +} diff --git a/src/fetch/body/blob.ts b/src/fetch/body/blob.ts new file mode 100644 index 0000000..0f45844 --- /dev/null +++ b/src/fetch/body/blob.ts @@ -0,0 +1,6 @@ +export function blobBody (blob: Blob, headers: Headers): ReadableStream { + headers.set('Content-Length', `${blob.size}`) + headers.set('Content-Type', (blob.type != null && blob.type !== '') ? blob.type : 'application/octet-stream') + + return blob.stream() +} diff --git a/src/fetch/body/bytes.ts b/src/fetch/body/bytes.ts new file mode 100644 index 0000000..b17959a --- /dev/null +++ b/src/fetch/body/bytes.ts @@ -0,0 +1,13 @@ +import { toUint8Array } from '../../utils.js' + +export function bytesBody (bytes: Uint8Array, headers: Headers): ReadableStream { + headers.set('Content-Length', `${bytes.byteLength}`) + headers.set('Content-Type', 'application/octet-stream') + + return new ReadableStream({ + start (controller) { + controller.enqueue(toUint8Array(bytes)) + controller.close() + } + }) +} diff --git a/src/fetch/body/form-data.ts b/src/fetch/body/form-data.ts new file mode 100644 index 0000000..2ba32fe --- /dev/null +++ b/src/fetch/body/form-data.ts @@ -0,0 +1,116 @@ +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' + +function calculateSize (name: string, entry: FormDataEntryValue, boundary: string): number { + const header = [ + `--${boundary}` + ] + + let contentLength = 0 + const trailingLinebreak = '\r\n'.length + + if (typeof entry === 'string') { + header.push( + `Content-Disposition: form-data; name="${name}"`, + 'Content-Type: text/plain; charset="UTF-8"', + `Content-Length: ${entry.length}`, + '' + ) + + contentLength = entry.length + trailingLinebreak + } else { + header.push( + `Content-Disposition: form-data; name="${name}"; filename="${encodeURIComponent(entry.name)}"`, + 'Content-Type: application/octet-stream', + `Content-Length: ${entry.size}`, + '' + ) + + contentLength = entry.size + trailingLinebreak + } + + const buf = uint8arrayFromString(header.join('\r\n')) + + return buf.byteLength + contentLength +} + +export function formDataBody (formData: FormData, headers: Headers): ReadableStream { + const boundary = `-----------------------------${crypto.randomUUID()}` + headers.set('Content-Type', `multipart/form-data; boundary=${boundary}`) + + // calculate length + let length = 0 + for (const [name, value] of formData.entries()) { + length += calculateSize(name, value, boundary) + } + + headers.set('Content-Length', `${length}`) + + const formDataIterator = formData.entries() + let fileDataReader: ReadableStreamDefaultReader | undefined + + function queuePart (controller: ReadableStreamDefaultController, name: string, entry: FormDataEntryValue, boundary: string): void { + const header = [ + `--${boundary}` + ] + + if (typeof entry === 'string') { + header.push( + `Content-Disposition: form-data; name="${name}"`, + 'Content-Type: text/plain; charset="UTF-8"', + `Content-Length: ${entry.length}`, + '', + entry, + '' + ) + } else { + header.push( + `Content-Disposition: form-data; name="${name}"; filename="${encodeURIComponent(entry.name)}"`, + 'Content-Type: application/octet-stream', + `Content-Length: ${entry.size}`, + '' + ) + + // write header this time, next time read file data + fileDataReader = entry.stream().getReader() + } + + controller.enqueue(uint8arrayFromString(header.join('\r\n'))) + } + + async function getNext (controller: ReadableStreamDefaultController, boundary: string): Promise { + // check if we are part way through reading a File entry + if (fileDataReader != null) { + const result = await fileDataReader.read() + + if (result.value != null) { + controller.enqueue(result.value) + } + + if (result.done) { + controller.enqueue(uint8arrayFromString('\r\n')) + fileDataReader = undefined + } + + return + } + + // read next FormData field + const { done, value } = formDataIterator.next() + + if (value != null) { + const [name, entry] = value + + queuePart(controller, name, entry, boundary) + } + + if (done === true) { + controller.close() + } + } + + return new ReadableStream({ + async pull (controller): Promise { + await getNext(controller, boundary) + } + }) +} diff --git a/src/fetch/body/readable-stream.ts b/src/fetch/body/readable-stream.ts new file mode 100644 index 0000000..7c73db4 --- /dev/null +++ b/src/fetch/body/readable-stream.ts @@ -0,0 +1,26 @@ +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' + +export function readableStreamBody (stream: ReadableStream, headers: Headers): ReadableStream { + headers.set('Content-Type', 'application/octet-stream') + headers.set('Transfer-Encoding', 'chunked') + + const reader = stream.getReader() + + return new ReadableStream({ + async pull (controller) { + const { done, value } = await reader.read() + + if (value != null) { + controller.enqueue(uint8arrayFromString(`${value.byteLength}\r\n`)) + controller.enqueue(value) + controller.enqueue(uint8arrayFromString('\r\n')) + } + + if (done) { + // write the final chunk + controller.enqueue(uint8arrayFromString('0\r\n\r\n')) + controller.close() + } + } + }) +} diff --git a/src/fetch/body/string.ts b/src/fetch/body/string.ts new file mode 100644 index 0000000..748d758 --- /dev/null +++ b/src/fetch/body/string.ts @@ -0,0 +1,13 @@ +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' + +export function stringBody (str: string, headers: Headers): ReadableStream { + headers.set('Content-Length', `${str.length}`) + headers.set('Content-Type', 'text/plain; charset="UTF-8"') + + return new ReadableStream({ + start (controller) { + controller.enqueue(uint8ArrayFromString(str)) + controller.close() + } + }) +} diff --git a/src/fetch/index.ts b/src/fetch/index.ts index 168d963..7113a8f 100644 --- a/src/fetch/index.ts +++ b/src/fetch/index.ts @@ -1,409 +1,28 @@ -/* eslint-disable max-depth */ -/* eslint-disable complexity */ +import { byteStream } from 'it-byte-stream' +import { readResponse } from './read-response.js' +import { sendRequest } from './send-request.js' +import type { ComponentLogger, Logger, Stream } from '@libp2p/interface' -import { HTTPParser } from '@achingbrain/http-parser-js' -import { multiaddr, protocols } from '@multiformats/multiaddr' -import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' -import defer from 'p-defer' -import { type Uint8ArrayList } from 'uint8arraylist' - -interface Fetch { (req: Request): Promise } - -const METHODS = [ - 'DELETE', - 'GET', - 'HEAD', - 'POST', - 'PUT', - 'CONNECT', - 'OPTIONS', - 'TRACE', - 'COPY', - 'LOCK', - 'MKCOL', - 'MOVE', - 'PROPFIND', - 'PROPPATCH', - 'SEARCH', - 'UNLOCK', - 'BIND', - 'REBIND', - 'UNBIND', - 'ACL', - 'REPORT', - 'MKACTIVITY', - 'CHECKOUT', - 'MERGE', - 'M-SEARCH', - 'NOTIFY', - 'SUBSCRIBE', - 'UNSUBSCRIBE', - 'PATCH', - 'PURGE', - 'MKCALENDAR', - 'LINK', - 'UNLINK' -] - -function getStringMethod (method: number): string { - return METHODS[method] ?? 'UNKNOWN' +export interface FetchInit extends RequestInit { + logger: ComponentLogger } -interface Duplex> { - source: AsyncIterable | Iterable - sink(source: AsyncIterable | Iterable): RSink +export interface SendRequestInit extends RequestInit { + log: Logger } -let ranDetectionForBrokenReqBody = false -let brokenRequestBody = false +export async function fetch (stream: Stream, resource: string | URL, init: FetchInit): Promise { + const log = init.logger.forComponent('libp2p:http:fetch') + resource = typeof resource === 'string' ? new URL(resource) : resource + const bytes = byteStream(stream) -/** - * Detects if the request body can not be a ReadableStream and should be read in - * full before returning the request This is only an issue in the current version of Firefox. - * - * @returns true if the request body can not be a ReadableStream and should be read in full before returning the request - */ -async function detectBrokenRequestBody (): Promise { - if (ranDetectionForBrokenReqBody) { - return brokenRequestBody - } - ranDetectionForBrokenReqBody = true - const rs = new ReadableStream({ - start (controller) { - controller.enqueue(new Uint8Array([0])) - controller.close() - } + await sendRequest(bytes, resource, { + ...init, + log }) - const req = new Request('https://example.com', { - method: 'POST', - body: rs, - // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit - duplex: 'half' - }) - - const ab = await req.arrayBuffer() - brokenRequestBody = ab.byteLength !== 1 - return brokenRequestBody -} - -/** - * Create a fetch function that can be used to fetch requests via a duplex stream - * - * @returns a function that can be used to fetch requests via a duplex stream - */ -export function fetchViaDuplex (s: Duplex): Fetch { - return async (req) => { - await writeRequestToDuplex(s, req) - const [respP] = readHTTPMsg(false, s) - const resp = await respP - if (!(resp instanceof Response)) { - throw new Error('Expected a response') - } - return resp - } -} - -/** - * A function that can be used to handle HTTP requests - */ -export interface HTTPHandler { (req: Request): Promise } - -/** - * - * @param s - Duplex where the request will be read from and the response will be written to - * @param h - HTTP handler that will be called with the request - */ -export async function handleRequestViaDuplex (s: Duplex, h: HTTPHandler): Promise { - const [reqP] = readHTTPMsg(true, s) - const req = await reqP - if (!(req instanceof Request)) { - throw new Error('Expected a request') - } - - const resp = await h(req) - await writeResponseToDuplex(s, resp) -} - -/** - * Exported for testing. - * - * @param expectRequest - is this a Request or a Response - * @param r - where to read from - * @returns two promises. The first is the parsed Request or Response. The second is a promise that resolves when the parsing is done. - */ -export function readHTTPMsg (expectRequest: boolean, r: Duplex): [Promise, Promise] { - const msgPromise = defer() - - return [ - msgPromise.promise, - (async () => { - const body = new TransformStream() - const writer = body.writable.getWriter() - let messageComplete = false - let fulfilledMsgPromise = false - - const parser = new HTTPParser(expectRequest ? 'REQUEST' : 'RESPONSE') - parser[HTTPParser.kOnHeadersComplete] = (info) => { - fulfilledMsgPromise = true - - // Handle the headers - const headers = new Headers() - - for (let i = 0; i < info.headers.length; i += 2) { - headers.set(info.headers[i], info.headers[i + 1]) - } - - let reqBody: ReadableStream | null = body.readable - - // Headers are parsed. We can return the response - try { - if (expectRequest) { - if (getStringMethod(info.method) === 'GET') { - reqBody = null - } - - const urlWithHost = `https://${headers.get('Host') ?? 'unknown_host._libp2p'}${info.url}` - detectBrokenRequestBody().then(async (broken) => { - let req: Request - if (!broken) { - req = new Request(urlWithHost, { - method: getStringMethod(info.method), - body: reqBody, - headers, - // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit - duplex: 'half' - }) - } else { - if (reqBody === null) { - req = new Request(urlWithHost, { - method: getStringMethod(info.method), - headers - }) - } else { - // Unfortunate workaround for a bug in Firefox's Request implementation. - // They don't support ReadableStream bodies, so we need to read the whole body. - const rdr = reqBody.getReader() - const parts = [] - while (true) { - const { done, value } = await rdr.read() - if (done) { - break - } - if (value !== undefined) { - parts.push(value) - } - } - const totalSize = parts.reduce((acc, part) => acc + part.byteLength, 0) - const body = new Uint8Array(totalSize) - for (let i = 0, offset = 0; i < parts.length; i++) { - body.set(parts[i], offset) - offset += parts[i].byteLength - } - req = new Request(urlWithHost, { - method: getStringMethod(info.method), - body, - headers - }) - } - } - msgPromise.resolve(req) - fulfilledMsgPromise = true - }).catch(err => { - msgPromise.reject(err) - }) - } else { - let respBody: ReadableStream | null = body.readable - if (info.statusCode === 204) { - respBody = null - } - const resp = new Response(respBody, { - headers, - status: info.statusCode, - statusText: info.statusMessage - }) - msgPromise.resolve(resp) - fulfilledMsgPromise = true - } - } catch (error) { - msgPromise.reject(error) - } - } - parser[HTTPParser.kOnBody] = (buf) => { - writer.write(buf) - .catch((err: Error) => { - msgPromise.reject(err) - }) - } - parser[HTTPParser.kOnMessageComplete] = () => { - messageComplete = true - writer.close() - .catch((err: Error) => { - msgPromise.reject(err) - }) - } - - // Consume data - for await (const chunks of r.source) { - const chunk = chunks.subarray() - parser.execute(chunk) - } - - parser.finish() - - if (!messageComplete) { - await writer.abort(new Error('Incomplete HTTP message')) - - if (!fulfilledMsgPromise) { - msgPromise.reject(new Error('Incomplete HTTP message')) - } - } - })() - ] -} - -const multiaddrURIPrefix = 'multiaddr:' -const CRLF = '\r\n' -const encodedCRLF = new TextEncoder().encode(CRLF) -const encodedFinalChunk = new TextEncoder().encode(`0${CRLF}${CRLF}`) -async function writeRequestToDuplex (s: Duplex, request: Request): Promise { - const method = request.method - - let reqUrl = request.url - let path = '' - let urlHost = '' - if (reqUrl.startsWith(multiaddrURIPrefix)) { - reqUrl = reqUrl.substring(multiaddrURIPrefix.length) - const ma = multiaddr(reqUrl) - // Find the http-path component - const [, httpPathVal] = ma.stringTuples().find(([code, value]) => - code === protocols('http-path').code - - ) ?? ['', ''] - path = decodeURIComponent(httpPathVal ?? '') - - try { - const maWithoutPath = ma.decapsulateCode(protocols('http-path').code) - const url = new URL(multiaddrToUri(maWithoutPath)) - urlHost = url.host - } catch {} - } else { - const url = new URL(reqUrl) - urlHost = url.host - path = (url.pathname ?? '') + (url.search ?? '') - } - const headers = request.headers - - if (!path.startsWith('/')) { - path = `/${path}` - } - let httpRequest = `${method} ${path} HTTP/1.1${CRLF}` - - // Add Host header if not present - if (!headers.has('Host') && urlHost !== '') { - httpRequest += `Host: ${urlHost}${CRLF}` - } - // Add connection close - if (!headers.has('Connection')) { - httpRequest += `Connection: close${CRLF}` - } - - headers.forEach((value, name) => { - httpRequest += `${name}: ${value}${CRLF}` + return readResponse(bytes, resource, { + ...init, + log }) - - let reqBody = request.body - if (request.body === undefined && typeof request.arrayBuffer === 'function') { - const body = await request.arrayBuffer() - if (body.byteLength > 0) { - reqBody = new ReadableStream({ - start (controller) { - controller.enqueue(new Uint8Array(body)) - controller.close() - } - }) - } else { - reqBody = null - } - } - - const requestIncludesContentAndNeedsContentLength = reqBody !== null && !headers.has('Content-Length') && (method === 'POST' || method === 'PUT' || method === 'PATCH') - - if (requestIncludesContentAndNeedsContentLength) { - // If we don't have the content length, we need to use chunked encoding - httpRequest += `Transfer-Encoding: chunked${CRLF}` - } - httpRequest += CRLF - - void s.sink((async function * () { - const httpRequestBuffer = new TextEncoder().encode(httpRequest) - yield httpRequestBuffer - - if (reqBody === null || reqBody === undefined) { - return - } - - const reader = reqBody.getReader() - try { - while (true) { - const { done, value } = await reader.read() - // If the stream is done, break the loop - if (done) { - if (requestIncludesContentAndNeedsContentLength) { - yield encodedFinalChunk - } - break - } - - // add the chunk length - if (requestIncludesContentAndNeedsContentLength) { - const chunkLength = value.byteLength.toString(16) - const chunkLengthBuffer = new TextEncoder().encode(`${chunkLength}${CRLF}`) - yield chunkLengthBuffer - } - - yield value - - if (requestIncludesContentAndNeedsContentLength) { - yield encodedCRLF - } - } - } finally { - reader.releaseLock() - } - })()) -} - -async function writeResponseToDuplex (s: Duplex, resp: Response): Promise { - await s.sink((async function * () { - const textEncoder = new TextEncoder() - const status = resp.status - const reason = resp.statusText - const headers = resp.headers - - let httpRequest = `HTTP/1.1 ${status} ${reason}${CRLF}` - - // Add connection close - if (!headers.has('Connection')) { - httpRequest += `Connection: close${CRLF}` - } - - headers.forEach((value, name) => { - httpRequest += `${name}: ${value}${CRLF}` - }) - httpRequest += CRLF - - yield textEncoder.encode(httpRequest) - - if (resp.body !== null && resp.body !== undefined) { - const reader = resp.body.getReader() - while (true) { - const { done, value } = await reader.read() - if (done) { - break - } - yield value - } - } - })()) } diff --git a/src/fetch/read-response.ts b/src/fetch/read-response.ts new file mode 100644 index 0000000..173d9fe --- /dev/null +++ b/src/fetch/read-response.ts @@ -0,0 +1,85 @@ +import { HTTPParser } from '@achingbrain/http-parser-js' +import type { SendRequestInit } from './index.js' +import type { Stream } from '@libp2p/interface' +import type { ByteStream } from 'it-byte-stream' + +export async function readResponse (bytes: ByteStream, resource: URL, init: SendRequestInit): Promise { + return new Promise((resolve, reject) => { + const body = new TransformStream() + const writer = body.writable.getWriter() + let headersComplete = false + + const parser = new HTTPParser('RESPONSE') + parser[HTTPParser.kOnHeadersComplete] = (info) => { + init.log('response headers complete') + headersComplete = true + const headers: Array<[string, string]> = [] + + for (let i = 0; i < info.headers.length; i += 2) { + headers.push([info.headers[i], info.headers[i + 1]]) + } + + const response = new Response(body.readable, { + status: info.statusCode, + statusText: info.statusMessage, + headers + }) + + resolve(response) + } + parser[HTTPParser.kOnBody] = (buf) => { + init.log('response read body %d bytes', buf.byteLength) + writer.write(buf) + .catch((err: Error) => { + reject(err) + }) + } + parser[HTTPParser.kOnMessageComplete] = () => { + init.log('response message complete') + writer.close() + .catch((err: Error) => { + reject(err) + }) + + const stream = bytes.unwrap() + stream.close() + .catch(err => { + stream.abort(err) + }) + } + + Promise.resolve() + .then(async () => { + let read = 0 + while (true) { + const chunk = await bytes.read({ + signal: init.signal ?? undefined + }) + + if (chunk == null) { + const err = parser.finish() + + if (err != null) { + init.log('response stream ended with error - %e', err) + } else { + init.log('response stream ended') + } + + if (!headersComplete) { + reject(new Error(`Response ended before headers were received, read ${read} bytes`)) + } + + break + } + + read += chunk.byteLength + + init.log('response stream read %d bytes', chunk.byteLength) + parser.execute(chunk.subarray(), 0, chunk.byteLength) + } + }) + .catch((err: Error) => { + reject(err) + }) + }) +} diff --git a/src/fetch/send-request.ts b/src/fetch/send-request.ts new file mode 100644 index 0000000..ce101da --- /dev/null +++ b/src/fetch/send-request.ts @@ -0,0 +1,102 @@ +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { blobBody } from './body/blob.js' +import { bytesBody } from './body/bytes.js' +import { formDataBody } from './body/form-data.js' +import { readableStreamBody } from './body/readable-stream.js' +import { stringBody } from './body/string.js' +import type { SendRequestInit } from './index.js' +import type { Stream } from '@libp2p/interface' +import type { ByteStream } from 'it-byte-stream' + +export async function sendRequest (bytes: ByteStream, url: URL, init: SendRequestInit): Promise { + const headers = new Headers(init.headers) + + const host = headers.get('host') ?? url.hostname + headers.set('host', host) + + if (headers.get('user-agent') == null) { + headers.set('user-agent', 'libp2p/fetch') + } + + let content: ReadableStream | undefined + + if (init.body != null) { + content = normalizeContent(init.body, headers) + } + + const req = [ + `${init?.method?.toUpperCase() ?? 'GET'} ${url.pathname ?? '/'} HTTP/1.1`, + ...writeHeaders(headers), + '', + '' + ] + + await bytes.write(uint8arrayFromString(req.join('\r\n')), { + signal: init.signal ?? undefined + }) + + if (content != null) { + init.log('request sending body') + await sendBody(bytes, content, init) + } +} + +async function sendBody (bytes: ByteStream, stream: ReadableStream, init: SendRequestInit): Promise { + const reader = stream.getReader() + + while (true) { + const { done, value } = await reader.read() + + if (value != null) { + init.log('request send %d bytes', value.byteLength) + await bytes.write(value, { + signal: init.signal ?? undefined + }) + } + + if (done) { + init.log('request finished sending body') + break + } + } +} + +function normalizeContent (body: BodyInit, headers: Headers): ReadableStream { + if (typeof body === 'string') { + return stringBody(body, headers) + } else if (body instanceof Blob) { + return blobBody(body, headers) + } else if (isBytes(body)) { + return bytesBody(body, headers) + } else if (body instanceof URLSearchParams) { + return stringBody(body.toString(), headers) + } else if (body instanceof ReadableStream) { + return readableStreamBody(body, headers) + } else if (body instanceof FormData) { + return formDataBody(body, headers) + } + + throw new Error('Unsupported body type') +} + +function writeHeaders (headers: Headers): string[] { + const output = [] + + if (headers.get('Connection') == null) { + headers.set('Connection', 'close') + } + + for (const [key, value] of headers.entries()) { + output.push(`${key}: ${value}`) + } + + return output +} + +function isBytes (obj?: any): obj is Uint8Array { + if (obj == null) { + return false + } + + return obj.byteLength != null +} diff --git a/src/http.browser.ts b/src/http.browser.ts new file mode 100644 index 0000000..e217e41 --- /dev/null +++ b/src/http.browser.ts @@ -0,0 +1,332 @@ +import { HTTPParser } from '@achingbrain/http-parser-js' +import { UnsupportedOperationError, serviceCapabilities } from '@libp2p/interface' +import { fromStringTuples } from '@multiformats/multiaddr' +import { queuelessPushable } from 'it-queueless-pushable' +import { Uint8ArrayList } from 'uint8arraylist' +import { PROTOCOL, WELL_KNOWN_PROTOCOLS } from './constants.js' +import { fetch } from './fetch/index.js' +import { HTTPRegistrar } from './registrar.js' +import { NOT_FOUND_RESPONSE, responseToStream, streamToRequest, toMultiaddrs, toResource } from './utils.js' +import { streamToWebSocket } from './websocket/utils.js' +import { WebSocket as WebSocketClass } from './websocket/websocket.js' +import type { Endpoint, HTTPInit, HTTP as HTTPInterface, WebSocketInit, HeaderInfo, HTTPRequestHandler, WebSocketHandler } from './index.js' +import type { ProtocolMap } from './well-known-handler.js' +import type { ComponentLogger, IncomingStreamData, Logger, PeerId, Startable, Stream } from '@libp2p/interface' +import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' +import type { Multiaddr } from '@multiformats/multiaddr' + +const HTTP_PATH_CODEC = 0x01e1 + +export interface HTTPComponents { + registrar: Registrar + connectionManager: ConnectionManager + logger: ComponentLogger +} + +export class HTTP implements HTTPInterface, Startable { + private readonly log: Logger + protected readonly components: HTTPComponents + private readonly endpoint?: Endpoint + private readonly httpRegistrar: HTTPRegistrar + + constructor (components: HTTPComponents, init: HTTPInit = {}) { + this.components = components + this.log = components.logger.forComponent('libp2p:http') + this.httpRegistrar = new HTTPRegistrar(components) + this.endpoint = init.server + this.onStream = this.onStream.bind(this) + } + + readonly [Symbol.toStringTag] = '@libp2p/http' + + readonly [serviceCapabilities]: string[] = [ + '@libp2p/http' + ] + + async start (): Promise { + await this.components.registrar.handle(PROTOCOL, (data) => { + this.onStream(data) + .catch(err => { + this.log.error('could not handle incoming stream - %e', err) + }) + }) + } + + async stop (): Promise { + await this.components.registrar.unhandle(PROTOCOL) + } + + private async onStream ({ stream, connection }: IncomingStreamData): Promise { + const info = await readHeaders(stream) + const isWebSocketRequest = info.headers.get('upgrade') === 'websocket' + + if (isWebSocketRequest && this.canHandleWebSocket(info)) { + this.log('handling incoming request %s %s', info.method, info.url) + this.handleWebSocket(streamToWebSocket(info, stream)) + return + } + + if (!isWebSocketRequest && this.canHandleHTTP(info)) { + this.log('handling incoming request %s %s', info.method, info.url) + const res = await this.handleHTTP(streamToRequest(info, stream)) + await responseToStream(res, stream) + await stream.close() + return + } + + // pass request to endpoint if available + if (this.endpoint == null) { + this.log('cannot handle incoming request %s %s and no endpoint configured', info.method, info.url) + await stream.sink([NOT_FOUND_RESPONSE]) + return + } + + this.log('passing incoming request %s %s to endpoint', info.method, info.url) + this.endpoint.inject(info, stream, connection) + .catch(err => { + this.log.error('error injecting request to endpoint - %e', err) + stream.abort(err) + }) + } + + canHandleHTTP (req: { url?: string }): boolean { + if (req.url == null) { + return false + } + + if (req.url === WELL_KNOWN_PROTOCOLS) { + return true + } + + // try handler registered with registrar + if (this.httpRegistrar.canHandleHTTP(req)) { + return true + } + + return false + } + + canHandleWebSocket (req: { url?: string }): boolean { + if (req.url == null) { + return false + } + + if (req.url === WELL_KNOWN_PROTOCOLS) { + return true + } + + // try handler registered with registrar + if (this.httpRegistrar.canHandleWebSocket(req)) { + return true + } + + return false + } + + /** + * Handle an incoming HTTP request + */ + async handleHTTP (req: Request): Promise { + const url = new URL(req.url) + + // serve protocol map + if (url.pathname === WELL_KNOWN_PROTOCOLS) { + const map = JSON.stringify(this.getProtocolMap()) + return new Response(map, { + headers: { + 'Content-Type': 'application/json', + 'Content-Length': `${map.length}` + } + }) + } + + // pass request to handler + return this.httpRegistrar.handleHTTP(req) + } + + handleWebSocket (ws: WebSocket): void { + // serve protocol map + if (ws.url === WELL_KNOWN_PROTOCOLS) { + const map = JSON.stringify(this.getProtocolMap()) + ws.send(map) + ws.close() + return + } + + // pass request to handler + this.httpRegistrar.handleWebSocket(ws) + } + + agent (...args: any[]): any { + throw new UnsupportedOperationError('This method is not supported in browsers') + } + + dispatcher (...args: any[]): any { + throw new UnsupportedOperationError('This method is not supported in browsers') + } + + connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init?: WebSocketInit): globalThis.WebSocket { + let url = toResource(resource) + + if (url instanceof URL) { + const socket = new globalThis.WebSocket(url, protocols) + socket.binaryType = 'arraybuffer' + + return socket + } + + // strip http-path tuple but record the value if set + let httpPath = '/' + url = url.map(ma => { + return fromStringTuples( + ma.stringTuples().filter(t => { + if (t[0] === HTTP_PATH_CODEC && t[1] != null) { + httpPath = `/${t[1]}` + } + + return t[0] !== HTTP_PATH_CODEC + }) + ) + }) + + return new WebSocketClass(url, new URL(`http://example.com${decodeURIComponent(httpPath)}`), this.components.connectionManager, { + ...init, + protocols, + isClient: true + }) + } + + async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: RequestInit = {}): Promise { + let url = toResource(resource) + + if (url instanceof URL) { + return globalThis.fetch(url, init) + } + + // strip http-path tuple but record the value if set + let httpPath = '/' + url = url.map(ma => { + return fromStringTuples( + ma.stringTuples().filter(t => { + if (t[0] === HTTP_PATH_CODEC && t[1] != null) { + httpPath = `/${t[1]}` + } + + return t[0] !== HTTP_PATH_CODEC + }) + ) + }) + + const connection = await this.components.connectionManager.openConnection(url, { + signal: init.signal ?? undefined + }) + const stream = await connection.newStream(PROTOCOL, { + signal: init.signal ?? undefined + }) + + return fetch(stream, new URL(`http://example.com${decodeURIComponent(httpPath)}`), { + ...init, + logger: this.components.logger + }) + } + + async getSupportedProtocols (peer: PeerId | Multiaddr | Multiaddr[]): Promise { + const addresses = toMultiaddrs(peer, `/http-path/${encodeURIComponent(WELL_KNOWN_PROTOCOLS.substring(1))}`) + const resp = await this.fetch(addresses, { + method: 'GET', + headers: { + Accept: 'application/json' + } + }) + + if (resp.status !== 200) { + throw new Error(`Unexpected status code: ${resp.status}`) + } + + return resp.json() + } + + async getProtocolPath (peer: PeerId | Multiaddr, protocol: string): Promise { + const peerMeta = await this.getSupportedProtocols(peer) + + if (peerMeta[protocol] == null) { + throw new Error(`Peer does not serve protocol: ${protocol}`) + } + + return peerMeta[protocol].path + } + + handleHTTPProtocol (protocol: string, handler: HTTPRequestHandler, path?: string): void { + this.httpRegistrar.handleHTTPProtocol(protocol, handler, path) + } + + handleWebSocketProtocol (protocol: string, handler: WebSocketHandler, path?: string): void { + this.httpRegistrar.handleWebSocketProtocol(protocol, handler, path) + } + + unhandleHTTPProtocol (protocol: string): void { + this.httpRegistrar.unhandleHTTPProtocol(protocol) + } + + unhandleWebSocketProtocol (protocol: string): void { + this.httpRegistrar.unhandleWebSocketProtocol(protocol) + } + + getProtocolMap (): ProtocolMap { + return this.httpRegistrar.getProtocolMap() + } +} + +/** + * Reads HTTP headers from an incoming stream + */ +async function readHeaders (stream: Stream): Promise { + return new Promise((resolve, reject) => { + const parser = new HTTPParser('REQUEST') + const source = queuelessPushable() + const earlyData = new Uint8ArrayList() + let headersComplete = false + + parser[HTTPParser.kOnHeadersComplete] = (info) => { + headersComplete = true + const headers = new Headers() + + // set incoming headers + for (let i = 0; i < info.headers.length; i += 2) { + headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) + } + + resolve({ + ...info, + headers, + raw: earlyData, + method: HTTPParser.methods[info.method] + }) + } + + // replace source with request body + const streamSource = stream.source + stream.source = source + + Promise.resolve().then(async () => { + for await (const chunk of streamSource) { + // only use the message parser until the headers have been read + if (!headersComplete) { + earlyData.append(chunk) + parser.execute(chunk.subarray()) + } else { + await source.push(new Uint8ArrayList(chunk)) + } + } + + await source.end() + }) + .catch((err: Error) => { + stream.abort(err) + reject(err) + }) + .finally(() => { + parser.finish() + }) + }) +} diff --git a/src/http.ts b/src/http.ts new file mode 100644 index 0000000..07cd175 --- /dev/null +++ b/src/http.ts @@ -0,0 +1,108 @@ +import { Agent as NodeAgent } from 'node:http' +import { isPeerId } from '@libp2p/interface' +import { Agent as UnidiciAgent } from 'undici' +import { PROTOCOL } from './constants.js' +import { HTTP as HTTPBrowser } from './http.browser.js' +import { streamToSocket } from './stream-to-socket.js' +import { toResource } from './utils.js' +import type { HTTP as HTTPInterface } from './index.js' +import type { AbortOptions, PeerId } from '@libp2p/interface' +import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' +import type { Multiaddr } from '@multiformats/multiaddr' +import type { Agent, AgentOptions } from 'node:http' +import type { Socket, TcpNetConnectOpts } from 'node:net' +import type { Dispatcher } from 'undici' + +export type { HTTPComponents } from './http.browser.js' + +async function createConnection (connectionManager: ConnectionManager, peer: PeerId | Multiaddr | Multiaddr[], options?: AbortOptions): Promise { + const connection = await connectionManager.openConnection(peer, options) + const stream = await connection.newStream(PROTOCOL, options) + + return streamToSocket(stream, connection) +} + +interface HTTPDispatcherComponents { + connectionManager: ConnectionManager +} + +interface HTTPDispatcherInit extends UnidiciAgent.Options { + peer: PeerId | Multiaddr | Multiaddr[] +} + +export class HTTPDispatcher extends UnidiciAgent { + constructor (components: HTTPDispatcherComponents, init: HTTPDispatcherInit) { + super({ + ...init, + connect: (options, cb) => { + createConnection(components.connectionManager, init.peer, { + // @ts-expect-error types are wonky + signal: options.timeout != null ? AbortSignal.timeout(options.timeout) : undefined + }) + .then(socket => { + cb(null, socket) + }, err => { + cb(err, null) + }) + } + }) + } +} + +interface HTTPAgentComponents { + connectionManager: ConnectionManager +} + +interface HTTPAgentInit extends AgentOptions { + peer: PeerId | Multiaddr | Multiaddr[] +} + +class HTTPAgent extends NodeAgent { + public readonly keepAliveMsecs: number = 100 + private readonly components: HTTPAgentComponents + private readonly peer: PeerId | Multiaddr | Multiaddr[] + + constructor (components: HTTPAgentComponents, init: HTTPAgentInit) { + super(init) + this.components = components + this.peer = init.peer + } + + createConnection (options: TcpNetConnectOpts, cb: (err?: Error, socket?: Socket) => void): void { + createConnection(this.components.connectionManager, this.peer, options) + .then(socket => { + cb(undefined, socket) + }, err => { + cb(err) + }) + } +} + +export interface HTTPClientComponents { + registrar: Registrar + connectionManager: ConnectionManager +} + +export class HTTP extends HTTPBrowser implements HTTPInterface { + agent (peer: PeerId | Multiaddr | Multiaddr[], options?: AgentOptions): Agent { + if (!isPeerId(peer) && toResource(peer) instanceof URL) { + return new NodeAgent(options) + } + + return new HTTPAgent(this.components, { + ...options, + peer + }) + } + + dispatcher (peer: PeerId | Multiaddr | Multiaddr[], options?: UnidiciAgent.Options): Dispatcher { + if (!isPeerId(peer) && toResource(peer) instanceof URL) { + return new UnidiciAgent(options) + } + + return new HTTPDispatcher(this.components, { + ...options, + peer + }) + } +} diff --git a/src/http/incoming-message.ts b/src/http/incoming-message.ts new file mode 100644 index 0000000..c7e52e3 --- /dev/null +++ b/src/http/incoming-message.ts @@ -0,0 +1,71 @@ +import { Readable } from 'node:stream' +import { HTTPParser } from '@achingbrain/http-parser-js' +import type { HeaderInfo } from '@achingbrain/http-parser-js' +import type { IncomingHttpHeaders } from 'node:http' +import type { Socket } from 'node:net' + +export class IncomingMessage extends Readable { + public aborted: boolean + public httpVersion: string + public httpVersionMajor: number + public httpVersionMinor: number + public complete: boolean + public connection: Socket + public socket: Socket + public headers: IncomingHttpHeaders + public headersDistinct: NodeJS.Dict + public rawHeaders: string[] + public trailers: NodeJS.Dict + public trailersDistinct: NodeJS.Dict + public rawTrailers: string[] + public method?: string | undefined + public url?: string | undefined + public statusCode?: number | undefined + public statusMessage?: string | undefined + + constructor (socket: Socket, info: HeaderInfo) { + super({ + read () { + if (socket.isPaused()) { + socket.resume() + } + } + }) + this.aborted = false + this.socket = socket + this.httpVersion = `${info.versionMajor}.${info.versionMinor}` + this.httpVersionMajor = info.versionMajor + this.httpVersionMinor = info.versionMinor + this.method = HTTPParser.methods[info.method] + this.statusCode = info.statusCode + this.statusMessage = info.statusMessage + this.url = info.url + this.complete = false + this.connection = socket + this.headers = {} + this.headersDistinct = {} + this.rawHeaders = [] + this.trailers = {} + this.trailersDistinct = {} + this.rawTrailers = [] + + // set incoming headers + for (const [key, value] of info.headers.entries()) { + this.headers[key] = value + this.rawHeaders.push(key, value) + } + } + + setTimeout (msecs: number, callback?: () => void): this { + this.socket.setTimeout(msecs, callback) + return this + } + + destroy (error?: Error): this { + if (error != null) { + this.socket.destroy(error) + } + + return this + } +} diff --git a/src/http/index.browser.ts b/src/http/index.browser.ts new file mode 100644 index 0000000..fbe13a2 --- /dev/null +++ b/src/http/index.browser.ts @@ -0,0 +1,38 @@ +import { HTTPServer } from './server.js' +import type { ServerOptions, RequestListener, IncomingMessage, ServerResponse, Server } from 'node:http' + +/** + * Implements the same interface as `createServer` from `node:http` just without + * any node internals. + * + * If running in a browser, instances of `http.Server` returned by this function + * could be passed to a web framework such as `express` or `fastify`, assuming + * they are runnable in browsers. + */ +export function createServer< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse> = typeof ServerResponse + > (requestListener?: RequestListener): Server +export function createServer< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse> = typeof ServerResponse + > (options: ServerOptions, + requestListener?: RequestListener): Server +export function createServer< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse> = typeof ServerResponse +> (options: any, + requestListener?: any): Server { + if (typeof options === 'function') { + requestListener = options + options = {} + } + + const server: Server = new HTTPServer(options) + + if (requestListener != null) { + server.on('request', requestListener) + } + + return server +} diff --git a/src/http/index.ts b/src/http/index.ts new file mode 100644 index 0000000..f5701de --- /dev/null +++ b/src/http/index.ts @@ -0,0 +1 @@ +export { createServer } from 'node:http' diff --git a/src/http/server-response.ts b/src/http/server-response.ts new file mode 100644 index 0000000..3d76977 --- /dev/null +++ b/src/http/server-response.ts @@ -0,0 +1,310 @@ +import { Writable } from 'node:stream' +import { InvalidParametersError } from '@libp2p/interface' +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import type { IncomingMessage } from './incoming-message.js' +import type { OutgoingHttpHeader, OutgoingHttpHeaders } from 'node:http' +import type { Socket } from 'node:net' + +const STATUS_CODES: Record = { + 100: 'Continue', // RFC 7231 6.2.1 + 101: 'Switching Protocols', // RFC 7231 6.2.2 + 102: 'Processing', // RFC 2518 10.1 (obsoleted by RFC 4918) + 103: 'Early Hints', // RFC 8297 2 + 200: 'OK', // RFC 7231 6.3.1 + 201: 'Created', // RFC 7231 6.3.2 + 202: 'Accepted', // RFC 7231 6.3.3 + 203: 'Non-Authoritative Information', // RFC 7231 6.3.4 + 204: 'No Content', // RFC 7231 6.3.5 + 205: 'Reset Content', // RFC 7231 6.3.6 + 206: 'Partial Content', // RFC 7233 4.1 + 207: 'Multi-Status', // RFC 4918 11.1 + 208: 'Already Reported', // RFC 5842 7.1 + 226: 'IM Used', // RFC 3229 10.4.1 + 300: 'Multiple Choices', // RFC 7231 6.4.1 + 301: 'Moved Permanently', // RFC 7231 6.4.2 + 302: 'Found', // RFC 7231 6.4.3 + 303: 'See Other', // RFC 7231 6.4.4 + 304: 'Not Modified', // RFC 7232 4.1 + 305: 'Use Proxy', // RFC 7231 6.4.5 + 307: 'Temporary Redirect', // RFC 7231 6.4.7 + 308: 'Permanent Redirect', // RFC 7238 3 + 400: 'Bad Request', // RFC 7231 6.5.1 + 401: 'Unauthorized', // RFC 7235 3.1 + 402: 'Payment Required', // RFC 7231 6.5.2 + 403: 'Forbidden', // RFC 7231 6.5.3 + 404: 'Not Found', // RFC 7231 6.5.4 + 405: 'Method Not Allowed', // RFC 7231 6.5.5 + 406: 'Not Acceptable', // RFC 7231 6.5.6 + 407: 'Proxy Authentication Required', // RFC 7235 3.2 + 408: 'Request Timeout', // RFC 7231 6.5.7 + 409: 'Conflict', // RFC 7231 6.5.8 + 410: 'Gone', // RFC 7231 6.5.9 + 411: 'Length Required', // RFC 7231 6.5.10 + 412: 'Precondition Failed', // RFC 7232 4.2 + 413: 'Payload Too Large', // RFC 7231 6.5.11 + 414: 'URI Too Long', // RFC 7231 6.5.12 + 415: 'Unsupported Media Type', // RFC 7231 6.5.13 + 416: 'Range Not Satisfiable', // RFC 7233 4.4 + 417: 'Expectation Failed', // RFC 7231 6.5.14 + 418: 'I\'m a Teapot', // RFC 7168 2.3.3 + 421: 'Misdirected Request', // RFC 7540 9.1.2 + 422: 'Unprocessable Entity', // RFC 4918 11.2 + 423: 'Locked', // RFC 4918 11.3 + 424: 'Failed Dependency', // RFC 4918 11.4 + 425: 'Too Early', // RFC 8470 5.2 + 426: 'Upgrade Required', // RFC 2817 and RFC 7231 6.5.15 + 428: 'Precondition Required', // RFC 6585 3 + 429: 'Too Many Requests', // RFC 6585 4 + 431: 'Request Header Fields Too Large', // RFC 6585 5 + 451: 'Unavailable For Legal Reasons', // RFC 7725 3 + 500: 'Internal Server Error', // RFC 7231 6.6.1 + 501: 'Not Implemented', // RFC 7231 6.6.2 + 502: 'Bad Gateway', // RFC 7231 6.6.3 + 503: 'Service Unavailable', // RFC 7231 6.6.4 + 504: 'Gateway Timeout', // RFC 7231 6.6.5 + 505: 'HTTP Version Not Supported', // RFC 7231 6.6.6 + 506: 'Variant Also Negotiates', // RFC 2295 8.1 + 507: 'Insufficient Storage', // RFC 4918 11.5 + 508: 'Loop Detected', // RFC 5842 7.2 + 509: 'Bandwidth Limit Exceeded', + 510: 'Not Extended', // RFC 2774 7 + 511: 'Network Authentication Required' // RFC 6585 6 +} + +export class ServerResponse extends Writable { + public req: Request + public chunkedEncoding: boolean + public shouldKeepAlive: boolean + public useChunkedEncodingByDefault: boolean + public sendDate: boolean + public finished: boolean + public headersSent: boolean + public connection: Socket | null + public socket: Socket | null + public statusCode: number + public statusMessage: string + public strictContentLength: boolean + + private readonly headers: Record> + private sentHeaders: boolean + + constructor (req: Request, socket: Socket) { + super() + + this.req = req + this.headers = {} + this.socket = socket + this.connection = socket + this.chunkedEncoding = false + this.shouldKeepAlive = false + this.useChunkedEncodingByDefault = false + this.sendDate = false + this.finished = false + this.headersSent = false + this.strictContentLength = false + this.sentHeaders = false + this.statusCode = 200 + this.statusMessage = STATUS_CODES[this.statusCode] + } + + _write (chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void { + this.flushHeaders() + this.socket?.write(chunk, encoding, callback) + } + + _final (callback: (error?: Error | null) => void): void { + this.socket?.end(callback) + } + + _destroy (error: Error | null, callback: (error?: Error | null) => void): void { + this.socket?.destroy(error ?? undefined) + callback() + } + + setTimeout (msecs: number, callback?: () => void): this { + this.socket?.setTimeout(msecs, callback) + return this + } + + setHeader (name: string, value: number | string | string[]): this { + this.headers[name] = value + return this + } + + setHeaders (headers: Headers | Map): this { + for (const [key, value] of headers.entries()) { + this.setHeader(key, value) + } + + return this + } + + appendHeader (name: string, value: string | string[]): this { + if (this.headers[name] == null) { + this.headers[name] = value + } else { + let existingValue = this.headers[name] + + if (!Array.isArray(existingValue)) { + existingValue = [existingValue] + this.headers[name] = existingValue + } + + if (Array.isArray(value)) { + existingValue.push(...value) + } else { + existingValue.push(value) + } + } + + return this + } + + getHeader (name: string): number | string | string[] | undefined { + const existingValue = this.headers[name] + + if (Array.isArray(existingValue)) { + return existingValue.map(v => v.toString()) + } + + return existingValue + } + + getHeaders (): OutgoingHttpHeaders { + const output: OutgoingHttpHeaders = {} + + for (const name of Object.keys(this.headers)) { + output[name] = this.getHeader(name) + } + + return output + } + + getHeaderNames (): string[] { + return [...Object.keys(this.headers)] + } + + hasHeader (name: string): boolean { + return this.headers[name] != null + } + + removeHeader (name: string): void { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete this.headers[name] + } + + addTrailers (headers: OutgoingHttpHeaders | ReadonlyArray<[string, string]>): void { + + } + + flushHeaders (): void { + if (this.sentHeaders) { + return + } + + this.sentHeaders = true + + const res = [ + `HTTP/1.1 ${this.statusCode} ${this.statusMessage}`, + ...writeHeaders(this.headers), + '', + '' + ] + + this.socket?.write(uint8arrayFromString(res.join('\r\n'))) + } + + writeContinue (callback?: () => void): void { + const res = [ + `HTTP/1.1 100 ${STATUS_CODES[100]}`, + '', + '' + ] + + this.socket?.write(uint8arrayFromString(res.join('\r\n')), callback) + } + + writeEarlyHints (hints: Record, callback?: () => void): void { + const res = [ + `HTTP/1.1 103 ${STATUS_CODES[103]}`, + ...writeHeaders(hintsToHeaders(hints)), + '', + '' + ] + + this.socket?.write(uint8arrayFromString(res.join('\r\n')), callback) + } + + writeHead (statusCode: number, statusMessage?: string, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this + writeHead (statusCode: number, headers?: OutgoingHttpHeaders | OutgoingHttpHeader[]): this + writeHead (...args: any[]): this { + const statusCode = parseInt(args[0] ?? this.statusCode, 10) + let headers: OutgoingHttpHeaders | OutgoingHttpHeader[] | undefined = args[1] + + if (args.length === 3) { + this.statusMessage = args[1] ?? this.statusMessage + headers = args[2] + } + + if (headers != null) { + for (const [key, value] of Object.keys(headers)) { + this.setHeader(key, value) + } + } + + if (STATUS_CODES[statusCode] == null) { + throw new InvalidParametersError(`Unknown status code ${statusCode}`) + } + + this.flushHeaders() + + return this + } + + writeProcessing (): void { + const res = [ + `HTTP/1.1 102 ${STATUS_CODES[102]}`, + '', + '' + ] + + this.socket?.write(uint8arrayFromString(res.join('\r\n'))) + } + + end (cb?: (() => void) | undefined): this + end (chunk: any, cb?: (() => void) | undefined): this + end (chunk: any, encoding: BufferEncoding, cb?: (() => void) | undefined): this + end (chunk?: any, encoding?: any, cb?: any): this { + super.end(chunk, encoding, cb) + + return this + } +} + +function hintsToHeaders (hints: Record): Record { + const output: Record = {} + + for (const [key, value] of Object.entries(hints)) { + output[key] = Array.isArray(value) ? value : [value] + } + + return output +} + +function writeHeaders (headers: Record>): string[] { + const output = [] + + for (const [key, value] of Object.entries(headers)) { + if (value == null) { + continue + } + + if (Array.isArray(value)) { + output.push(`${key}: ${value.join(', ')}`) + } else { + output.push(`${key}: ${value}`) + } + } + + return output +} diff --git a/src/http/server.ts b/src/http/server.ts new file mode 100644 index 0000000..d40fd3d --- /dev/null +++ b/src/http/server.ts @@ -0,0 +1,156 @@ +import { EventEmitter } from 'node:events' +import { HTTPParser } from '@achingbrain/http-parser-js' +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { IncomingMessage as IncomingMessageClass } from './incoming-message.js' +import { ServerResponse as ServerResponseClass } from './server-response.js' +import type { ServerOptions, ServerResponse, IncomingMessage } from 'node:http' +import type { AddressInfo, ListenOptions, Socket } from 'node:net' + +export interface HTTPServerEvents { + request: [Request, Response] +} + +export class HTTPServer < + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends typeof ServerResponse> = typeof ServerResponse +> extends EventEmitter { + public maxHeadersCount: number | null + public maxRequestsPerSocket: number | null + public timeout: number + public headersTimeout: number + public keepAliveTimeout: number + public requestTimeout: number + public maxConnections: number + public connections: number + private _listening: boolean + private readonly _options: ServerOptions + + constructor (options: ServerOptions = {}) { + super() + + this.maxHeadersCount = 0 + this.maxRequestsPerSocket = 0 + this.timeout = 0 + this.headersTimeout = 120_000 + this.keepAliveTimeout = options.keepAliveTimeout ?? 0 + this.requestTimeout = options.requestTimeout ?? 120_000 + this.maxConnections = 0 + this.connections = 0 + this._listening = false + this._options = options + + this.on('connection', this._handleConnection.bind(this)) + } + + private _handleConnection (socket: Socket): void { + const parser = new HTTPParser('REQUEST') + let req: IncomingMessage | undefined + + parser[HTTPParser.kOnHeadersComplete] = (info) => { + const headers = new Headers() + + // set incoming headers + for (let i = 0; i < info.headers.length; i += 2) { + headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) + } + + req = new IncomingMessageClass(socket, { + ...info, + headers + }) + const res = new ServerResponseClass(req, socket) + + if (info.upgrade) { + const listeners = this.listenerCount('upgrade') + + if (listeners === 0) { + socket.write(uint8arrayFromString('HTTP/1.1 501 Not Implemented\r\n\r\n')) + // socket.end() + return + } else { + this.emit('upgrade', req, socket, new Uint8Array(0)) + return + } + } + + this.emit('request', req, res) + } + parser[HTTPParser.kOnBody] = (buf) => { + req?.push(buf) + } + + parser[HTTPParser.kOnMessageComplete] = () => { + req?.push(null) + } + + socket.on('data', (chunk) => { + parser.execute(chunk, 0, chunk.byteLength) + }) + socket.on('end', () => { + parser.finish() + req?.push(null) + }) + } + + setTimeout (msecs?: number, callback?: (socket: Socket) => void): this + setTimeout (callback?: (socket: Socket) => void): this + setTimeout (msecs?: any, callback?: any): this { + return this + } + + closeAllConnections (): void { + + } + + closeIdleConnections (): void { + + } + + listen (port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): this + listen (port?: number, hostname?: string, listeningListener?: () => void): this + listen (port?: number, backlog?: number, listeningListener?: () => void): this + listen (port?: number, listeningListener?: () => void): this + listen (path: string, backlog?: number, listeningListener?: () => void): this + listen (path: string, listeningListener?: () => void): this + listen (options: ListenOptions, listeningListener?: () => void): this + listen (handle: any, backlog?: number, listeningListener?: () => void): this + listen (handle: any, listeningListener?: () => void): this + listen (...args: any[]): this { + this._listening = true + return this + } + + close (callback?: (err?: Error) => void): this { + this._listening = false + callback?.() + return this + } + + address (): AddressInfo | string | null { + return null + } + + getConnections (cb: (error: Error | null, count: number) => void): void { + cb(null, this.connections) + } + + ref (): this { + return this + } + + unref (): this { + return this + } + + get listening (): boolean { + return this._listening + } + + set listening (listening: boolean) { + + } + + async [Symbol.asyncDispose] (): Promise { + + } +} diff --git a/src/index.ts b/src/index.ts index a81e369..7e58160 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,57 +1,426 @@ /** * @packageDocumentation * - * {@link http} implements the WHATWG [Fetch - * api](https://fetch.spec.whatwg.org). It can be used as a drop in replacement - * for the browser's fetch function. It supports http, https, and multiaddr - * URIs. Use HTTP in p2p networks. + * This module allows you to use HTTP requests as a transport for libp2p + * protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP + * requests (HTTP over libp2p). * - * @example + * It integrates with existing Node.js friendly HTTP frameworks such as + * [express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well + * as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ + * [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based + * frameworks like [Hono](https://hono.dev/). * - * See the `examples/` for full examples of how to use the HTTP service. + * It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s + * and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s + * (based on the [ws](https://www.npmjs.com/package/ws) module API in the + * absence of a native Node.js API to emulate) in browsers to truly realize the + * power of the distributed web. * - * ```typescript + * Instead of the regular "host:port" addressing, it uses a libp2p PeerId and/or + * multiaddr(s) and lets libp2p take care of the routing, thus taking advantage + * of features like multi-routes, NAT transversal and stream multiplexing over a + * single connection. + * + * # Servers + * + * You can create HTTP and WebSocket servers using the framework of your choice, + * as long as it accepts a Node.js `http.Server` instance. + * + * @example Node HTTP server + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { http } from '@libp2p/http' + * import { nodeServer } from '@libp2p/http/servers/node' + * import { createServer } from 'node:http' + * + * const server = createServer((req, res) => { + * req.end('Hello world!') + * }) + * + * const listener = await createLibp2p({ + * // ...other options + * services: { + * http: http({ + * server: nodeServer(server) + * }) + * } + * }) + * ``` + * + * @example Express server + * + * ```ts + * import express from 'express' + * import { http } from '@libp2p/http' + * import { nodeServer } from '@libp2p/http/servers/node' + * import { createServer } from 'node:http' + * + * // create an express app + * const app = express() + * app.get('/', (req, res) => { + * res.send('Hello World!') + * }) + * + * const server = createServer(app) + * + * const listener = await createLibp2p({ + * // ...other options + * services: { + * http: http({ + * server: nodeServer(server) + * }) + * } + * }) + * ``` + * + * @example Fastify server + * + * ```ts + * import { fastify } from 'fastify' + * import { createLibp2p } from 'libp2p' + * import { http } from '@libp2p/http' + * import { nodeServer } from '@libp2p/http/servers/node' + * import { createServer } from 'node:http' + * + * let server + * + * // create a fastify app + * const app = fastify({ + * serverFactory: (handler, opts) => { + * server = createServer((req, res) => { + * handler(req, res) + * }) + * + * return server + * } + * }) + * app.get('/', async (req, res) => { + * await res.send('Hello World!') + * }) + * await app.ready() + * + * if (server == null) { + * throw new Error('Server not created') + * } + * + * const listener = await createLibp2p({ + * // ...other options + * services: { + * http: http({ + * server: nodeServer(server) + * }) + * } + * }) + * ``` + * + * @example ws WebSocket server + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { httpServer } from '@libp2p/http' + * import { createServer } from 'node:http' + * import { WebSocketServer } from 'ws' + * + * const wss = new WebSocketServer({ noServer: true }) + * wss.on('connection', (ws) => { + * ws.on('message', (data) => { + * ws.send(data) + * }) + * }) + * + * const server = createServer((req, res) => { + * req.end('Hello world!') + * }) + * + * server.on('upgrade', (request, socket, head) => { + * wss.handleUpgrade(request, socket, head, (ws) => { + * wss.emit('connection', ws, request) + * }) + * }) + * + * const listener = await createLibp2p({ + * // ...other options + * services: { + * httpServer: httpServer({ server }) + * } + * }) + * ``` + * + * # Clients + * + * You can use the built-in `.fetch` and `.connect` methods to make HTTP or + * WebSocket requests respectively, or you can create a Node.js `http.Agent` for + * use with the `node:http`, or a `Dispatcher` for use with `undici`. + * + * @example Using fetch to make a HTTP request + * + * This example works in all JavaScript environments, Node.js and browsers too! + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { http } from '@libp2p/http' + * import { peerIdFromString } from '@libp2p/peer-id' + * import { multiaddr } from '@multiformats/multiaddr' + * + * const client = await createLibp2p({ + * // ...other options + * services: { + * http: http() + * } + * }) + * + * const peerId = peerIdFromString('12DKoo') + * const ma = multiaddr(`/p2p/${peerId}/http`) + * const response = await client.services.httpClient.fetch(ma, { + * signal: AbortSignal.timeout(10_000) + * }) + * + * console.info('Response:', response.status) + * // Response: 200 + * + * console.info(await response.text()) + * // Hello world! + * ``` + * + * @example Using connect to create a WebSocket + * + * This example works in all JavaScript environments, Node.js and browsers too! + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { httpClient } from '@libp2p/http' + * import { peerIdFromString } from '@libp2p/peer-id' + * + * const client = await createLibp2p({ + * // ...other options + * services: { + * httpClient: httpClient() + * } + * }) + * + * const peerId = peerIdFromString('12DKoo') + * const url = new URL('http://example.com') + * const webSocket = await client.services.httpClient.connect(peerId, url, { + * signal: AbortSignal.timeout(10_000) + * }) + * + * webSocket.addEventListener('message', (evt) => { + * console.info(response.data) + * // + * }) + * ``` + * + * @example Using a http.Agent to make a request with node:http + * + * This example only works in Node.js-compatible environments. + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { httpClient } from '@libp2p/http' + * import { peerIdFromString } from '@libp2p/peer-id' + * import * as http from 'node:http' + * + * const client = await createLibp2p({ + * // ...other options + * services: { + * httpClient: httpClient() + * } + * }) + * + * const peerId = peerIdFromString('12DKoo') + * const agent = client.services.httpClient.agent(peerId) + * + * const req = http.request({ host: 'example.com', agent }, (res) => { + * let result = '' + * + * res.setEncoding('utf8') + * res.on('data', (chunk) => { + * result += chunk + * }) + * res.on('end', () => { + * console.info(result) + * // Hello world! + * }) + * }) + * + * req.end() + * ``` + * + * @example Using a Dispatcher to make a request with undici + * + * This example only works in Node.js-compatible environments. + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { httpClient } from '@libp2p/http' + * import { peerIdFromString } from '@libp2p/peer-id' + * import { fetch } from 'undici' + * + * const client = await createLibp2p({ + * // ...other options + * services: { + * httpClient: httpClient() + * } + * }) + * + * const peerId = peerIdFromString('12DKoo') + * const url = new URL('http://example.com') + * + * const dispatcher = client.services.httpClient.dispatcher(peerId) + * const response = await fetch(url, { + * dispatcher, + * signal: AbortSignal.timeout(10_000) + * }) + * + * console.info('Response:', response.status) + * // Response: 200 + * + * console.info(await response.text()) + * // Hello world! + * ``` + * + * # Browsers + * + * Making requests to servers is all good and well, but what if you could also + * run a web or WebSocket server in a browser? + * + * @example A HTTP server running in a browser + * + * Once configured you can make requests to this server in the same was as the + * fetch example near the top of this README. + * + * ```ts * import { createLibp2p } from 'libp2p' - * import { http } from '@libp2p/http-fetch' + * import { httpServer, createServer } from '@libp2p/http' * - * const node = await createLibp2p({ - * // other options ... - * services: { - * http: http() - * } + * const server = createServer((req, res) => { + * req.end('Hello world!') * }) * - * await node.start() + * const listener = await createLibp2p({ + * // ...other options + * services: { + * httpServer: httpServer({ server }) + * } + * }) + * ``` + * + * @example A WebSocket server running in a browser * - * // Make an http request to a libp2p peer - * let resp = await node.services.http.fetch('multiaddr:/dns4/localhost/tcp/1234') + * Once configured you can make requests to this server in the same was as the + * WebSocket example near the top of this README. * - * // Or a traditional HTTP request - * resp = await node.services.http.fetch('multiaddr:/dns4/example.com/tcp/443/tls/http') + * ```ts + * import { createLibp2p } from 'libp2p' + * import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' + * + * const wss = createWebSocketServer() + * wss.addEventListener('connection', (evt) => { + * const ws = evt.webSocket + * + * ws.on('message', (data) => { + * ws.send(data) + * }) + * }) * - * // And of course, you can use the fetch API as you normally would - * resp = await node.services.http.fetch('https://example.com') + * const server = createServer((req, res) => { + * req.end('Hello world!') + * }) * - * // This gives you the accessibility of the fetch API with the flexibility of - * // using a p2p network. + * server.addListener('upgrade', (request, socket, head) => { + * wss.handleUpgrade(request, socket, head, (ws) => { + * wss.emit('connection', ws, request) + * }) + * }) + * + * const listener = await createLibp2p({ + * // ...other options + * services: { + * httpServer: httpServer({ server }) + * } + * }) * ``` */ -import { WHATWGFetch, type ProtosMap } from './whatwg-fetch-service.js' -import type { ComponentLogger, PeerId } from '@libp2p/interface' -import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' +import { HTTP as HTTPClass } from './http.js' +import type { HTTPComponents } from './http.js' +import type { ProtocolMap } from './well-known-handler.js' +import type { AbortOptions, Connection, PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' +import type { Agent, AgentOptions } from 'node:http' +import type { Uint8ArrayList } from 'uint8arraylist' +import type { Dispatcher, Agent as UnidiciAgent } from 'undici' export { WELL_KNOWN_PROTOCOLS } from './constants.js' +export interface WebSocketInit extends AbortOptions { + /** + * The maximum message size to be sent or received over the socket in bytes + * + * @default 10_485_760 + */ + maxMessageSize?: number + + /** + * Headers to send with the initial upgrade request + */ + headers?: HeadersInit +} + +export interface HTTPRequestHandler { + (req: Request): Promise +} + +export interface WebSocketHandler { + (ws: WebSocket): void +} + /** * HTTP service interface */ export interface HTTP { /** - * Make a request in a similar way to globalThis.fetch + * Make a request in a similar way to globalThis.fetch. + * + * If the passed `resource` is a string, if it starts with a `/` character it + * will be interpreted as a Multiaddr, otherwise it will be interpreted as a + * URL. + * + * URLs can start with the `multiaddr:` scheme if the global URL class in the + * runtime environment supports it. + */ + fetch(resource: string | URL | Multiaddr | Multiaddr[], init?: RequestInit): Promise + + /** + * Open a WebSocket connection to an HTTP server over libp2p. + * + * If the passed `resource` starts with a `/` character, it will be + * interpreted as a Multiaddr, otherwise it will be interpreted as a URL. + * + * URLs can start with the `multiaddr:` scheme if the global URL class in the + * runtime environment supports it. + */ + connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init?: WebSocketInit): WebSocket + + /** + * Get a libp2p-enabled Agent for use with node's `http` module. This method + * will throw when not running under Node.js or Electron. + * + * All requests using this Agent will be sent to the peer reachable by the + * peer ID or multiaddr(s) passed as the first argument. + */ + agent (peer: PeerId | Multiaddr | Multiaddr[], options?: AgentOptions): Agent + + /** + * Get a libp2p-enabled Dispatcher for use with the `undici` module. This + * method will throw when not running under Node.js or Electron. + * + * All requests using this Agent will be sent to the peer reachable by the + * peer ID or multiaddr(s) passed as the first argument. */ - fetch(request: RequestInfo, requestInit?: RequestInit): Promise + dispatcher (peer: PeerId | Multiaddr | Multiaddr[], options?: UnidiciAgent.Options): Dispatcher /** * Uses the peer's .well-known endpoint to find where it hosts a given @@ -59,44 +428,84 @@ export interface HTTP { * * Throws an error if the peer does not serve the protocol. */ - prefixForProtocol (peer: PeerId | Multiaddr, protocol: string): Promise + getProtocolPath (peer: PeerId | Multiaddr | Multiaddr[], protocol: string, options?: AbortOptions): Promise /** - * Get the .well-known protocols for a peer. + * Get the .well-known protocols for a peer */ - getPeerMeta (peer: PeerId | Multiaddr): Promise + getSupportedProtocols (peer: PeerId | Multiaddr | Multiaddr[], options?: AbortOptions): Promise /** - * Registers a handler for the given protocol on the given path. - * - * This is incompatible with a customHTTPHandler. + * Register a listener for a HTTP protocol */ - handleHTTPProtocol (protocol: string, path: string, handler: (req: Request) => Promise): void -} + handleHTTPProtocol (protocol: string, handler: HTTPRequestHandler, path?: string): void -/** - * - */ -export interface HTTPWithCustomHandler { /** - * Will full a request to this peer's .well-known libp2p endpoint using - * information from the registerProtocol calls. + * Register a listener for a WebSocket protocol */ - serveWellKnownProtocols (req: Request): Promise + handleWebSocketProtocol (protocol: string, handler: WebSocketHandler, path?: string): void /** - * Inform this service of a protocol that you support and where it can be - * found. - * - * This metadata will be served at the .well-known endpoint. + * Remove a listener for a HTTP protocol + */ + unhandleHTTPProtocol (protocol: string): void + + /** + * Remove a listener for a WebSocket protocol + */ + unhandleWebSocketProtocol (protocol: string): void + + /** + * Return the protocol->path mappings supported by this server */ - registerProtocol(protocol: string, path: string): void + getProtocolMap (): ProtocolMap + + /** + * Returns true if there is a handler registered for the incoming Request or + * WebSocket + */ + canHandleHTTP (req: { url?: string }): boolean + + /** + * Returns true if there is a handler registered for the incoming Request or + * WebSocket + */ + canHandleWebSocket (req: { url?: string }): boolean + + /** + * Handle an incoming HTTP request + */ + handleHTTP: HTTPRequestHandler + + /** + * Handle an incoming WebSocket + */ + handleWebSocket: WebSocketHandler } -export interface FetchComponents { - registrar: Registrar - connectionManager: ConnectionManager - logger: ComponentLogger +/** + * Parsed from the incoming HTTP message + */ +export interface HeaderInfo { + versionMajor: number + versionMinor: number + headers: Headers + method: string + url: string + statusCode: number + statusMessage: string + upgrade: boolean + shouldKeepAlive: boolean + raw: Uint8ArrayList +} + +export interface Endpoint { + /** + * Accept an incoming request. The headers have already been parsed, the + * stream/connection should be transformed into whatever format the HTTP + * server requires + */ + inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise } /** @@ -107,39 +516,15 @@ export interface FetchComponents { */ export interface HTTPInit { /** - * Native Fetch implementation. Defaults to global fetch if available. If not - * available, it will throw an error. + * A server that will receive incoming requests */ - fetch?(request: Request): Promise -} - -export interface CustomHTTPHandlerInit { - /** - * Custom root HTTP handler for handling requests. If you set this you are in - * charge of fulfilling all HTTP requests including serving the libp2p - * well-known protocols (`.serverWellKnownProtocols` may be helpful). - * - * Most users should use the default handler. Which is used by calling - * `.handleHTTPProtocol`. - */ - customHTTPHandler(req: Request): Promise + server?: Endpoint } /** * Create an HTTP service that provides a `fetch` implementation and a way to * register custom HTTP handlers. */ -export function http (init: HTTPInit = {}): (components: FetchComponents) => HTTP { - return (components) => new WHATWGFetch(components, init) -} - -/** - * Start an HTTP service with a custom HTTP handler that is responsible for - * handling all HTTP requests and routing appropriately. - * - * Most users should use the `http` function and register their own protocols - * with `.handleHTTPProtocol`. - */ -export function httpCustomServer (init: HTTPInit & CustomHTTPHandlerInit): (components: FetchComponents) => HTTP & HTTPWithCustomHandler { - return (components) => new WHATWGFetch(components, init) +export function http (init: HTTPInit = {}): (components: HTTPComponents) => HTTP { + return (components) => new HTTPClass(components, init) } diff --git a/src/ping.ts b/src/ping.ts deleted file mode 100644 index 511872d..0000000 --- a/src/ping.ts +++ /dev/null @@ -1,64 +0,0 @@ -// http-ping implementation -import { isPeerId, type Libp2p, type PeerId } from '@libp2p/interface' -import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' -import type { HTTP } from './index.js' - -const PING_SIZE = 32 -export const PING_PROTOCOL_ID = '/http-ping/1' - -/** - * Serve a ping request - * - * @param req - An HTTP Request object - * @returns a Response object - */ -export async function servePing (req: Request): Promise { - const buf = new Uint8Array(await req.arrayBuffer()) - if (buf.length !== PING_SIZE) { - return new Response(null, { status: 400 }) - } - return new Response( - buf, - { - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Length': `${PING_SIZE}` - } - } - ) -} - -/** - * Send a ping request to a peer - * - * @param node - a libp2p node - * @param peerIdOrMultiaddr - Target peer - */ -export async function sendPing (node: Libp2p<{ http: HTTP }>, peerIdOrMultiaddr: PeerId | Multiaddr): Promise { - const peerAddr: Multiaddr = isPeerId(peerIdOrMultiaddr) ? multiaddr(`/p2p/${peerIdOrMultiaddr.toString()}`) : peerIdOrMultiaddr - const buf = new Uint8Array(PING_SIZE) - // Fill buffer with random data - crypto.getRandomValues(buf) - const pingEndpoint = await node.services.http.prefixForProtocol(peerAddr, PING_PROTOCOL_ID) - const requestURL = 'multiaddr:' + peerAddr.encapsulate(`/http-path/${encodeURIComponent(pingEndpoint)}`).toString() - - const resp = await node.services.http.fetch(new Request(requestURL, { - method: 'POST', - headers: { - 'Content-Type': 'application/octet-stream', - 'Content-Length': `${PING_SIZE}` - }, - body: buf - })) - if (resp.status !== 200) { - throw new Error(`Unexpected status code: ${resp.status}`) - } - - const respBuf = new Uint8Array(await resp.arrayBuffer()) - if (respBuf.length !== PING_SIZE) { - throw new Error(`Unexpected response size: ${respBuf.length}`) - } - if (!buf.every((v, i) => v === respBuf[i])) { - throw new Error('Ping body mismatch') - } -} diff --git a/src/ping/index.ts b/src/ping/index.ts new file mode 100644 index 0000000..6891c3a --- /dev/null +++ b/src/ping/index.ts @@ -0,0 +1,26 @@ +// http-ping implementation +import { PingHTTPService as PingHTTPServiceClass } from './ping.js' +import type { HTTP } from '../index.js' +import type { AbortOptions, PeerId } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' + +export const HTTP_PING_PROTOCOL = '/http-ping/1' + +export interface PingHTTPComponents { + http: HTTP +} + +export interface PingOptions extends AbortOptions { + /** + * If true, make a request over a WebSocket instead of HTTP + */ + webSocket?: true +} + +export interface PingHTTP { + ping (peer: PeerId | Multiaddr | Multiaddr[], options?: PingOptions): Promise +} + +export function pingHTTP (): (components: PingHTTPComponents) => PingHTTP { + return (components) => new PingHTTPServiceClass(components) +} diff --git a/src/ping/ping.ts b/src/ping/ping.ts new file mode 100644 index 0000000..811ba46 --- /dev/null +++ b/src/ping/ping.ts @@ -0,0 +1,132 @@ +// http-ping implementation +import { ProtocolError, serviceDependencies } from '@libp2p/interface' +import { raceEvent } from 'race-event' +import { raceSignal } from 'race-signal' +import { equals as uint8ArrayEquals } from 'uint8arrays/equals' +import { toMultiaddrs } from '../utils.js' +import { HTTP_PING_PROTOCOL } from './index.js' +import type { PingHTTPComponents, PingHTTP as PingHTTPInterface, PingOptions } from './index.js' +import type { PeerId, Startable } from '@libp2p/interface' +import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr' + +const PING_SIZE = 32 + +export class PingHTTPService implements PingHTTPInterface, Startable { + private readonly components: PingHTTPComponents + + constructor (components: PingHTTPComponents) { + this.components = components + + this.onHTTPRequest = this.onHTTPRequest.bind(this) + this.onWebSocket = this.onWebSocket.bind(this) + } + + readonly [Symbol.toStringTag] = '@libp2p/ping-http' + + readonly [serviceDependencies]: string[] = [ + '@libp2p/http' + ] + + start (): void { + this.components.http.handleHTTPProtocol(HTTP_PING_PROTOCOL, this.onHTTPRequest) + this.components.http.handleWebSocketProtocol(HTTP_PING_PROTOCOL, this.onWebSocket) + } + + stop (): void { + this.components.http.unhandleHTTPProtocol(HTTP_PING_PROTOCOL) + this.components.http.unhandleWebSocketProtocol(HTTP_PING_PROTOCOL) + } + + async onHTTPRequest (req: Request): Promise { + if (req.body == null) { + return new Response(null, { status: 400 }) + } + + const ab = await req.arrayBuffer() + const buf = new Uint8Array(ab, 0, ab.byteLength) + + if (buf.byteLength !== PING_SIZE) { + return new Response(null, { status: 400 }) + } + + return new Response(buf, { + headers: { + 'Content-Type': 'application/octet-stream', + 'Content-Length': `${PING_SIZE}` + } + }) + } + + onWebSocket (ws: WebSocket): void { + ws.addEventListener('message', (evt) => { + const buf = new Uint8Array(evt.data, 0, evt.data.byteLength) + + if (buf.length !== PING_SIZE) { + ws.close(400) + return + } + + ws.send(buf) + ws.close() + }) + } + + async ping (peer: PeerId | Multiaddr | Multiaddr[], options: PingOptions = {}): Promise { + const pingEndpoint = await this.components.http.getProtocolPath(peer, HTTP_PING_PROTOCOL, options) + const dialTarget = toMultiaddrs(peer) + .map(ma => ma.encapsulate(`/http-path/${encodeURIComponent(pingEndpoint.substring(1))}`)) + + const start = Date.now() + const buf = new Uint8Array(PING_SIZE) + // fill buffer with random data + crypto.getRandomValues(buf) + + const output = await raceSignal(options.webSocket === true ? this.webSocketPing(dialTarget, buf, options) : this.httpPing(dialTarget, buf, options), options?.signal) + const respBuf = new Uint8Array(output, 0, output.byteLength) + + if (respBuf.length !== PING_SIZE) { + throw new ProtocolError(`Unexpected response size: ${respBuf.length}`) + } + + if (!uint8ArrayEquals(respBuf, buf)) { + throw new ProtocolError('Ping body mismatch') + } + + return Date.now() - start + } + + async httpPing (dialTarget: Multiaddr[], buf: Uint8Array, options: AbortOptions): Promise { + const res = await this.components.http.fetch(dialTarget, { + ...options, + method: 'POST', + body: buf + }) + + if (res.status !== 200) { + throw new ProtocolError(`Unexpected status code: ${res.status}`) + } + + return res.arrayBuffer() + } + + async webSocketPing (dialTarget: Multiaddr[], buf: Uint8Array, options: AbortOptions): Promise { + const socket = this.components.http.connect(dialTarget, [], options) + + if (socket.readyState !== WebSocket.OPEN) { + await raceEvent(socket, 'open', options.signal) + } + + const p = new Promise((resolve, reject) => { + socket.addEventListener('message', (evt) => { + resolve(evt.data) + }) + socket.addEventListener('error', () => { + reject(new Error('An error occurred')) + }) + }) + + socket.send(buf) + + return p + } +} diff --git a/src/registrar.ts b/src/registrar.ts new file mode 100644 index 0000000..cf3dded --- /dev/null +++ b/src/registrar.ts @@ -0,0 +1,157 @@ +import { InvalidParametersError } from '@libp2p/interface' +import type { HTTPRequestHandler, WebSocketHandler } from './index.js' +import type { ComponentLogger, Logger } from '@libp2p/interface' + +export type ProtocolID = string + +export interface ProtocolLocation { + path: string +} + +export type ProtocolMap = Record + +export interface HTTPRegistrarComponents { + logger: ComponentLogger +} + +export class HTTPRegistrar { + private readonly log: Logger + private protocols: Array<{ protocol: string, path: string, http?: HTTPRequestHandler, ws?: WebSocketHandler }> + + constructor (components: HTTPRegistrarComponents) { + this.log = components.logger.forComponent('libp2p:http:registrar') + this.protocols = [] + } + + canHandleHTTP (req: { url?: string }): boolean { + return this.protocols.find(p => p.path === req.url && p.http != null) != null + } + + canHandleWebSocket (req: { url?: string }): boolean { + return this.protocols.find(p => p.path === req.url && p.ws != null) != null + } + + async handleHTTP (request: Request): Promise { + const url = new URL(request.url) + + this.log('search for handler on path %s', url.pathname) + + const result = this.protocols.find(p => p.path === url.pathname) + + if (result?.http == null) { + return new Response(null, { + status: 404, + statusText: 'Not Found' + }) + } + + this.log('found for handler for HTTP protocol %s on path %s', result.protocol, url.pathname) + + return result.http(request) + } + + handleWebSocket (ws: WebSocket): void { + this.log('search for handler on path %s', ws.url) + + const result = this.protocols.find(p => p.path === ws.url) + + if (result?.ws == null) { + ws.close(404, 'Not Found') + return + } + + this.log('found for handler for WebSocket protocol %s on path %s', result.protocol, ws.url) + + result.ws(ws) + } + + handleHTTPProtocol (protocol: string, handler: HTTPRequestHandler, path: string = crypto.randomUUID()): void { + for (const p of this.protocols) { + if (p.protocol === protocol) { + if (p.http != null) { + throw new InvalidParametersError(`HTTP protocol handler for ${protocol} already registered`) + } + + p.http = handler + return + } + } + + if (path === '' || !path.startsWith('/')) { + path = `/${path}` + } + + // add handler + this.protocols.push({ + protocol, + path, + http: handler + }) + + // sort by path length desc so the most specific handler is invoked first + this.protocols.sort(({ path: a }, { path: b }) => b.length - a.length) + } + + handleWebSocketProtocol (protocol: string, handler: WebSocketHandler, path: string = crypto.randomUUID()): void { + for (const p of this.protocols) { + if (p.protocol === protocol) { + if (p.ws != null) { + throw new InvalidParametersError(`WebSocket protocol handler for ${protocol} already registered`) + } + + p.ws = handler + return + } + } + + if (path === '' || !path.startsWith('/')) { + path = `/${path}` + } + + // add handler + this.protocols.push({ + protocol, + path, + ws: handler + }) + + // sort by path length desc so the most specific handler is invoked first + this.protocols.sort(({ path: a }, { path: b }) => b.length - a.length) + } + + unhandleHTTPProtocol (protocol: string): void { + this.protocols = this.protocols.filter(p => { + if (p.protocol === protocol) { + delete p.http + + return p.ws != null + } + + return true + }) + } + + unhandleWebSocketProtocol (protocol: string): void { + this.protocols = this.protocols.filter(p => { + if (p.protocol === protocol) { + delete p.ws + + return p.http != null + } + + return true + }) + } + + getProtocolMap (): ProtocolMap { + const output: ProtocolMap = {} + + for (const p of this.protocols) { + output[p.protocol] = { + path: p.path + } + } + + return output + } +} diff --git a/src/servers/fetch.ts b/src/servers/fetch.ts new file mode 100644 index 0000000..0bab821 --- /dev/null +++ b/src/servers/fetch.ts @@ -0,0 +1,24 @@ +import { responseToStream, streamToRequest } from '../utils.js' +import type { Endpoint, HeaderInfo } from '../index.js' +import type { Stream, Connection } from '@libp2p/interface' + +export interface Fetch { + (req: Request): Promise +} + +export interface FetchServerInit { + server: Fetch +} + +export class FetchServer implements Endpoint { + private readonly server: Fetch + + constructor (init: FetchServerInit) { + this.server = init.server + } + + async inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise { + const res = await this.server(streamToRequest(info, stream)) + await responseToStream(res, stream) + } +} diff --git a/src/servers/node.ts b/src/servers/node.ts new file mode 100644 index 0000000..c412f1a --- /dev/null +++ b/src/servers/node.ts @@ -0,0 +1,110 @@ +import { streamToSocket } from '../stream-to-socket.js' +import { readableToReadableStream } from '../utils.js' +import type { Endpoint, HeaderInfo } from '../index.js' +import type { Stream, Connection } from '@libp2p/interface' +import type { ServerResponse, IncomingMessage } from 'node:http' +import type { Socket } from 'node:net' + +export interface ConnectionHandler { + emit (event: 'connection', socket: Socket): void +} + +export interface NodeServerInit { + server: ConnectionHandler +} + +class NodeServer implements Endpoint { + private readonly server: ConnectionHandler + + constructor (init: NodeServerInit) { + this.server = init.server + } + + async inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise { + // re-yield the headers to enable node to set up the request properly + const streamSource = stream.source + stream.source = (async function * () { + yield info.raw + yield * streamSource + })() + + this.server.emit('connection', streamToSocket(stream, connection)) + } +} + +export function nodeServer (server: ConnectionHandler): Endpoint { + return new NodeServer({ server }) +} + +export function incomingMessageToRequest (req: IncomingMessage): Request { + const headers = incomingHttpHeadersToHeaders(req.headers) + const init: RequestInit = { + method: req.method, + headers + } + + if (req.method !== 'GET' && req.method !== 'HEAD') { + // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit + init.duplex = 'half' + init.body = readableToReadableStream(req) + } + + const url = new URL(`http://${headers.get('host') ?? 'example.com'}${req.url ?? '/'}`) + + return new Request(url, init) +} + +function incomingHttpHeadersToHeaders (input: IncomingMessage['headers']): Headers { + const headers = new Headers() + + for (const [key, value] of Object.entries(input)) { + if (value == null) { + continue + } + + if (Array.isArray(value)) { + for (const val of value) { + headers.append(key, val) + } + } else { + headers.set(key, value) + } + } + + return headers +} + +export function writeResponse (res: Response, ser: ServerResponse): void { + const headers: Record = {} + + res.headers.forEach((val, key) => { + headers[key] = val + }) + + ser.writeHead(res.status, res.statusText, headers) + + if (res.body == null) { + ser.end() + } else { + const reader = res.body.getReader() + + Promise.resolve().then(async () => { + while (true) { + const { done, value } = await reader.read() + + if (value != null) { + ser.write(value) + } + + if (done) { + break + } + } + + ser.end() + }) + .catch(err => { + ser.end(err) + }) + } +} diff --git a/src/stream-to-socket.ts b/src/stream-to-socket.ts new file mode 100644 index 0000000..972fa9f --- /dev/null +++ b/src/stream-to-socket.ts @@ -0,0 +1,200 @@ +import { Duplex } from 'node:stream' +import { byteStream } from 'it-byte-stream' +import type { Connection, Stream } from '@libp2p/interface' +import type { Socket, SocketConnectOpts, AddressInfo, SocketReadyState } from 'node:net' + +const MAX_TIMEOUT = 2_147_483_647 + +class Libp2pSocket extends Duplex { + public readonly autoSelectFamilyAttemptedAddresses = [] + public readonly connecting = false + public readonly pending = false + public readonly remoteAddress: string + public bytesRead: number + public bytesWritten: number + public timeout = MAX_TIMEOUT + public allowHalfOpen: boolean + + private readonly stream: Stream + + constructor (stream: Stream, connection: Connection) { + const bytes = byteStream(stream) + + super({ + write: (chunk, encoding, cb) => { + this.stream.log('write %d bytes', chunk.byteLength) + + this.bytesWritten += chunk.byteLength + bytes.write(chunk) + .then(() => { + cb() + }, err => { + cb(err) + }) + }, + read: (size) => { + this.stream.log('asked to read %d bytes', size) + + void Promise.resolve().then(async () => { + try { + while (true) { + const chunk = await bytes.read({ + signal: AbortSignal.timeout(this.timeout) + }) + + if (chunk == null) { + this.stream.log('socket readable end closed') + this.push(null) + return + } + + this.bytesRead += chunk.byteLength + + this.stream.log('socket read %d bytes', chunk.byteLength) + const more = this.push(chunk.subarray()) + + if (!more) { + break + } + } + } catch (err: any) { + this.destroy(err) + } + }) + }, + destroy: (err, cb) => { + this.stream.log('destroy with %d bytes buffered - %e', this.bufferSize, err) + + if (err != null) { + bytes.unwrap().abort(err) + cb() + } else { + bytes.unwrap().close() + .then(() => { + cb() + }) + .catch(err => { + stream.abort(err) + cb(err) + }) + } + }, + final: (cb) => { + this.stream.log('final') + + bytes.unwrap().closeWrite() + .then(() => { + cb() + }) + .catch(err => { + bytes.unwrap().abort(err) + cb(err) + }) + } + }) + + this.stream = stream + this.remoteAddress = connection.remoteAddr.toString() + this.bytesRead = 0 + this.bytesWritten = 0 + this.allowHalfOpen = true + } + + public get readyState (): SocketReadyState { + if (this.stream.status === 'closed') { + return 'closed' + } + + if (this.stream.writeStatus === 'closed' || this.stream.writeStatus === 'closing') { + return 'readOnly' + } + + if (this.stream.readStatus === 'closed' || this.stream.readStatus === 'closing') { + return 'writeOnly' + } + + return 'open' + } + + public get bufferSize (): number { + return this.writableLength + } + + destroySoon (): void { + this.stream.log('destroySoon with %d bytes buffered', this.bufferSize) + this.destroy() + } + + connect (options: SocketConnectOpts, connectionListener?: () => void): this + connect (port: number, host: string, connectionListener?: () => void): this + connect (port: number, connectionListener?: () => void): this + connect (path: string, connectionListener?: () => void): this + connect (...args: any[]): this { + this.stream.log('connect %o', args) + return this + } + + setEncoding (encoding?: BufferEncoding): this { + this.stream.log('setEncoding %s', encoding) + return this + } + + resetAndDestroy (): this { + this.stream.log('resetAndDestroy') + this.stream.abort(new Error('Libp2pSocket.resetAndDestroy')) + + return this + } + + setTimeout (timeout: number, callback?: () => void): this { + this.stream.log('setTimeout %d', timeout) + + if (callback != null) { + this.addListener('timeout', callback) + } + + this.timeout = timeout === 0 ? MAX_TIMEOUT : timeout + + return this + } + + setNoDelay (noDelay?: boolean): this { + this.stream.log('setNoDelay %b', noDelay) + + return this + } + + setKeepAlive (enable?: boolean, initialDelay?: number): this { + this.stream.log('setKeepAlive %b %d', enable, initialDelay) + + return this + } + + address (): AddressInfo | Record { + this.stream.log('address') + + return {} + } + + unref (): this { + this.stream.log('unref') + + return this + } + + ref (): this { + this.stream.log('ref') + + return this + } + + write (buffer: Uint8Array | string, cb?: (err?: Error) => void): boolean + write (str: Uint8Array | string, encoding?: BufferEncoding, cb?: (err?: Error) => void): boolean + write (chunk: any, encoding?: any, cb?: any): boolean { + return super.write(chunk, encoding, cb) + } +} + +export function streamToSocket (stream: Stream, connection: Connection): Socket { + return new Libp2pSocket(stream, connection) +} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..4258ae8 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,238 @@ +import { isPeerId } from '@libp2p/interface' +import { isMultiaddr, multiaddr } from '@multiformats/multiaddr' +import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' +import { uriToMultiaddr } from '@multiformats/uri-to-multiaddr' +import { queuelessPushable } from 'it-queueless-pushable' +import itToBrowserReadableStream from 'it-to-browser-readablestream' +import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import type { HeaderInfo } from './index.js' +import type { PeerId, Stream } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' +import type { Readable } from 'node:stream' +import type { Uint8ArrayList } from 'uint8arraylist' + +const HTTP_CODEC = 0x01e0 + +/** + * Normalizes byte-like input to a `Uint8Array` + */ +export function toUint8Array (obj: DataView | ArrayBuffer | Uint8Array): Uint8Array { + if (obj instanceof Uint8Array) { + return obj + } + + if (obj instanceof DataView) { + return new Uint8Array(obj.buffer, obj.byteOffset, obj.byteLength) + } + + return new Uint8Array(obj, 0, obj.byteLength) +} + +export function streamToRequest (info: HeaderInfo, stream: Stream): Request { + const init: RequestInit = { + method: info.method, + headers: info.headers + } + + if (info.method !== 'GET' && info.method !== 'HEAD') { + init.body = itToBrowserReadableStream(takeBytes(stream.source, info.headers.get('content-length'))) + // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit + init.duplex = 'half' + } + + const req = new Request(`http://${info.headers.get('host') ?? 'host'}${info.url}`, init) + + return req +} + +export async function responseToStream (res: Response, stream: Stream): Promise { + const pushable = queuelessPushable() + stream.sink(pushable) + .catch(err => { + stream.abort(err) + }) + + await pushable.push(uint8arrayFromString([ + `HTTP/1.1 ${res.status} ${res.statusText}`, + ...writeHeaders(res.headers), + '', + '' + ].join('\r\n'))) + + if (res.body == null) { + await pushable.end() + return + } + + const reader = res.body.getReader() + let result = await reader.read() + + while (true) { + if (result.value != null) { + await pushable.push(result.value) + } + + if (result.done) { + break + } + + result = await reader.read() + } + + await pushable.end() + + await stream.closeWrite() + .catch(err => { + stream.abort(err) + }) +} + +export const NOT_FOUND_RESPONSE = uint8arrayFromString([ + 'HTTP/1.1 404 Not Found', + 'Connection: close', + '', + '' +].join('\r\n')) + +export const BAD_REQUEST = uint8arrayFromString([ + 'HTTP/1.1 400 Bad Request', + 'Connection: close', + '', + '' +].join('\r\n')) + +export const INTERNAL_SERVER_ERROR = uint8arrayFromString([ + 'HTTP/1.1 500 Internal Server Error', + 'Connection: close', + '', + '' +].join('\r\n')) + +/** + * Normalizes the dial target to a list of multiaddrs with an optionally + * encapsulated suffix + */ +export function toMultiaddrs (peer: PeerId | Multiaddr | Multiaddr[], suffix?: string): Multiaddr[] { + let mas: Multiaddr[] + + if (isPeerId(peer)) { + mas = [ + multiaddr(`/p2p/${peer}`) + ] + } else if (Array.isArray(peer)) { + mas = peer + } else { + mas = [ + peer + ] + } + + if (suffix != null) { + mas = mas.map(ma => ma.encapsulate(suffix)) + } + + return mas +} + +function writeHeaders (headers: Headers): string[] { + const output = [] + + if (headers.get('Connection') == null) { + headers.set('Connection', 'close') + } + + for (const [key, value] of headers.entries()) { + output.push(`${key}: ${value}`) + } + + return output +} + +export function readableToReadableStream (readable: Readable): ReadableStream { + return new ReadableStream({ + start (controller) { + readable.on('data', buf => { + controller.enqueue(buf) + + // pause until more data requested (backpressure) + readable.pause() + }) + readable.on('end', () => { + controller.close() + }) + readable.on('error', (err) => { + controller.error(err) + }) + }, + pull () { + // let data flow again + readable.resume() + } + }) +} + +async function * takeBytes (source: AsyncGenerator, bytes?: number | string | null): AsyncGenerator { + bytes = parseInt(`${bytes ?? ''}`) + + if (bytes == null || isNaN(bytes)) { + return source + } + + let count = 0 + + for await (const buf of source) { + count += buf.byteLength + + if (count > bytes) { + yield buf.subarray(0, count - bytes) + return + } + + yield buf.subarray() + + if (count === bytes) { + return + } + } +} + +/** + * Attempts to convert the passed `resource` into a HTTP(s) URL or an array of + * multiaddrs. + * + * The returned URL should be handled by the global fetch, the multiaddr(s) + * should be handled by libp2p. + */ +export function toResource (resource: string | URL | Multiaddr | Multiaddr[]): URL | Multiaddr[] { + if (typeof resource === 'string') { + if (resource.startsWith('/')) { + resource = multiaddr(resource) + } else { + resource = new URL(resource) + } + } + + if (resource instanceof URL) { + if (resource.protocol === 'multiaddr:') { + resource = uriToMultiaddr(resource.toString()) + } + } + + if (isMultiaddr(resource)) { + resource = [resource] + } + + // check for `/http/` tuple and transform to URL if present + if (Array.isArray(resource)) { + for (const ma of resource) { + const stringTuples = ma.stringTuples() + + if (stringTuples.find(([codec]) => codec === HTTP_CODEC) != null) { + const uri = multiaddrToUri(ma) + return new URL(uri) + } + } + } + + return resource +} diff --git a/src/websocket/events.ts b/src/websocket/events.ts new file mode 100644 index 0000000..4803f83 --- /dev/null +++ b/src/websocket/events.ts @@ -0,0 +1,13 @@ +export class ErrorEvent extends Event { + public readonly message: string + public readonly error: Error + public readonly filename = '' + public readonly lineno = 0 + public readonly colno = 0 + + constructor (err: Error) { + super('error') + this.error = err + this.message = err.message + } +} diff --git a/src/websocket/index.ts b/src/websocket/index.ts new file mode 100644 index 0000000..16a5b41 --- /dev/null +++ b/src/websocket/index.ts @@ -0,0 +1,102 @@ +import { WebSocketServer as WebSocketServerClass } from './server.js' +import type { IncomingMessage } from '../http/incoming-message.js' +import type { TypedEventTarget } from '@libp2p/interface' +import type { Duplex } from 'node:stream' + +export interface WebSocketEvents { + 'close': CloseEvent + 'error': Event + 'message': MessageEvent + 'open': Event +} + +export interface CloseListener { + (evt: CloseEvent): void +} + +export interface ErrorListener { + (evt: Event): void +} + +export interface MessageListener { + (evt: MessageEvent): void +} + +export interface OpenListener { + (evt: Event): void +} + +export interface WebSocket extends TypedEventTarget { + CONNECTING: 0 + OPEN: 1 + CLOSING: 2 + CLOSED: 3 + binaryType: BinaryType + bufferedAmount: number + extensions: string + protocol: string + readyState: number + url: string + onopen: OpenListener | null + onmessage: MessageListener | null + onerror: ErrorListener | null + onclose: CloseListener | null + + close (code?: number, reason?: string): void + send (data: string | Blob | Uint8Array | ArrayBuffer | DataView): void +} + +export class ConnectionEvent extends Event { + webSocket: WebSocket + request: IncomingMessage + + constructor (ws: WebSocket, req: IncomingMessage) { + super('connection') + + this.webSocket = ws + this.request = req + } +} + +export interface WebSocketServerEvents { + connection: ConnectionEvent +} + +export interface WebSocketServer extends TypedEventTarget { + handleUpgrade (request: IncomingMessage, socket: Duplex, head: Uint8Array): void +} + +/** + * Creates a WebSocket server that can handle upgrade requests from clients. + * + * Add a listener for the `connection` event to receive incoming WebSocket + * connections. + * + * @example + * + * ```ts + * import { createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + * + * const wss = createWebSocketServer() + * wss.addEventListener('connection', (evt) => { + * const ws = evt.webSocket + * + * ws.on('message', (data) => { + * ws.send(data) + * }) + * }) + * + * const server = createServer((req, res) => { + * // handle HTTP request + * }) + * + * server.addListener('upgrade', (request, socket, head) => { + * wss.handleUpgrade(request, socket, head, (ws) => { + * wss.emit('connection', ws, request) + * }) + * }) + * `` + */ +export function createWebSocketServer (): WebSocketServer { + return new WebSocketServerClass() +} diff --git a/src/websocket/message.ts b/src/websocket/message.ts new file mode 100644 index 0000000..cb24fbf --- /dev/null +++ b/src/websocket/message.ts @@ -0,0 +1,236 @@ +import { Uint8ArrayList } from 'uint8arraylist' + +export type MESSAGE_TYPE = 'CONTINUATION' | 'TEXT' | 'BINARY' | 'CONNECTION_CLOSE' | 'PING' | 'PONG' + +const OP_CODES: Record = { + CONTINUATION: 0, + TEXT: 1, + BINARY: 2, + CONNECTION_CLOSE: 8, + PING: 9, + PONG: 10 +} + +const MESSAGE_TYPES: Record = { + 0: 'CONTINUATION', + 1: 'TEXT', + 2: 'BINARY', + 8: 'CONNECTION_CLOSE', + 9: 'PING', + 10: 'PONG' +} + +export const CLOSE_CODES = { + 1000: 'NORMAL_CLOSURE', + 1001: 'GOING_AWAY', + 1002: 'PROTOCOL_ERROR', + 1003: 'UNSUPPORTED_DATA', + 1004: 'RESERVED', + 1005: 'NO_STATUS_RECEIVED', + 1006: 'ABNORMAL_CLOSURE', + 1007: 'INVALID_FRAME_PAYLOAD_DATA', + 1008: 'POLICY_VIOLATION', + 1009: 'MESSAGE_TOO_BIG', + 1010: 'MANDATORY_EXT', + 1011: 'INTERNAL_SERVER_ERROR', + 1015: 'TLS_HANDSHAKE' +} + +export const CLOSE_MESSAGES = { + NORMAL_CLOSURE: 1000, + GOING_AWAY: 1001, + PROTOCOL_ERROR: 1002, + UNSUPPORTED_DATA: 1003, + RESERVED: 1004, + NO_STATUS_RECEIVED: 1005, + ABNORMAL_CLOSURE: 1006, + INVALID_FRAME_PAYLOAD_DATA: 1007, + POLICY_VIOLATION: 1008, + MESSAGE_TOO_BIG: 1009, + MANDATORY_EXT: 1010, + INTERNAL_SERVER_ERROR: 1011, + TLS_HANDSHAKE: 1015 +} + +interface Message { + type: MESSAGE_TYPE + data?: Uint8Array +} + +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 +// +-+-+-+-+------+-+-------------+-------------------------------+ +// |F|R|R|R|opcode|M| Payload len | Extended payload length | +// |I|S|S|S| (4) |A| (7) | (16/64) | +// |N|V|V|V| |S| | (if payload len==126/127) | +// | |1|2|3| |K| | | +// +-+-+-+-+------+-+-------------+ - - - - - - - - - - - - - - - + +// | Extended payload length continued, if payload len == 127 | +// + - - - - - - - - - - - - - - -+-------------------------------+ +// | |Masking-key, if MASK set to 1 | +// +------------------------------+-------------------------------+ +// | Masking-key (continued) | Payload Data | +// +------------------------------- - - - - - - - - - - - - - - - + +// : Payload Data continued ... : +// +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// | Payload Data continued ... | +// +--------------------------------------------------------------+ + +export function decodeMessage (buf: Uint8ArrayList): Message | undefined { + let offset = 0 + + if (buf.byteLength < (offset + 1)) { + return + } + + const byte0 = buf.get(offset) + const opcode = (byte0 & 0b00001111) + offset++ + + if (MESSAGE_TYPES[opcode] == null) { + throw new Error(`Unknown opcode: ${opcode}`) + } + + if (buf.byteLength < (offset + 1)) { + return + } + + const byte1 = buf.get(offset) + const isMasked = (byte1 & 0b10000000) === 0b10000000 + let length = (byte1 & 0b01111111) + offset++ + + if (length === 126) { + if (buf.byteLength < (offset + 2)) { + return + } + + length = buf.getUint16(offset) + offset += 2 + } else if (length === 127) { + if (buf.byteLength < (offset + 8)) { + return + } + + length = buf.getUint32(offset) + offset += 8 + } + + if (length === 0) { + buf.consume(offset) + + return { + type: MESSAGE_TYPES[opcode] + } + } + + let mask: Uint8Array | undefined + + if (isMasked) { + // check if we have the whole mask + if (buf.byteLength < (offset + 4)) { + return + } + + mask = buf.subarray(offset, offset + 4) + offset += 4 + } + + // check if we have all the data + if (buf.byteLength < (offset + length)) { + return + } + + let data = buf.subarray(offset, offset + length) + offset += length + + if (mask != null) { + data = applyMask(data, mask) + } + + buf.consume(offset) + + return { + type: MESSAGE_TYPES[opcode], + data + } +} + +function applyMask (data: Uint8Array, mask: Uint8Array): Uint8Array { + let m = 0 + + for (let i = 0; i < data.byteLength; i++) { + data[i] = data[i] ^ mask[m] + + m++ + if (m === mask.byteLength) { + m = 0 + } + } + + return data +} + +export async function * decodeMessages (source: AsyncGenerator): AsyncGenerator { + const buffer = new Uint8ArrayList() + + for await (const buf of source) { + buffer.append(buf) + + const message = decodeMessage(buffer) + + if (message != null) { + yield message + } + } +} + +export function encodeMessage (opcode: MESSAGE_TYPE, data?: Uint8Array, maskData?: boolean): Uint8ArrayList { + const fin = true + const message = new Uint8ArrayList( + Uint8Array.from([ + (fin ? 128 : 0) | OP_CODES[opcode] + ]) + ) + + const length = data?.byteLength ?? 0 + + if (length < 126) { + message.append( + Uint8Array.from([ + length | (maskData === true ? 128 : 0) + ]) + ) + } else if (length < 65_535) { + const l = new Uint8ArrayList( + new Uint8Array(3) + ) + l.set(0, 126 | (maskData === true ? 128 : 0)) + l.setUint16(1, length) + + message.append(l) + } else if (length < 18_446_744_073_709_552_000) { + const l = new Uint8ArrayList( + new Uint8Array(9) + ) + l.set(0, 127 | (maskData === true ? 128 : 0)) + l.setUint32(1, length) + + message.append(l) + } else { + throw new Error('Payload too largs') + } + + if (maskData === true && data != null) { + const maskingKey = Uint8Array.from([0, 0, 0, 0]) + message.append(maskingKey) + + data = applyMask(data, maskingKey) + } + + if (data != null) { + message.append(data) + } + + return message +} diff --git a/src/websocket/server.ts b/src/websocket/server.ts new file mode 100644 index 0000000..0d511b0 --- /dev/null +++ b/src/websocket/server.ts @@ -0,0 +1,37 @@ +import { TypedEventEmitter } from '@libp2p/interface' +import { raceEvent } from 'race-event' +import { INTERNAL_SERVER_ERROR } from '../utils.js' +import { ServerWebSocket } from './websocket.js' +import { ConnectionEvent, type WebSocketServerEvents } from './index.js' +import type { IncomingMessage } from '../http/incoming-message.js' +import type { Duplex } from 'node:stream' + +const DEFAULT_UPGRADE_TIMEOUT = 10_000 + +export interface WebSocketServerInit { + upgradeTimeout?: number +} + +export class WebSocketServer extends TypedEventEmitter { + private readonly upgradeTimeout: number + + constructor (init: WebSocketServerInit = {}) { + super() + + this.upgradeTimeout = init.upgradeTimeout ?? DEFAULT_UPGRADE_TIMEOUT + } + + handleUpgrade (request: IncomingMessage, socket: Duplex, head: Uint8Array): void { + Promise.resolve() + .then(async () => { + const ws = new ServerWebSocket(request, socket) + + await raceEvent(ws, 'open', AbortSignal.timeout(this.upgradeTimeout)) + + this.dispatchEvent(new ConnectionEvent(ws, request)) + }) + .catch(() => { + socket.write(INTERNAL_SERVER_ERROR) + }) + } +} diff --git a/src/websocket/utils.ts b/src/websocket/utils.ts new file mode 100644 index 0000000..d507553 --- /dev/null +++ b/src/websocket/utils.ts @@ -0,0 +1,166 @@ +import { HTTPParser } from '@achingbrain/http-parser-js' +import { InvalidParametersError, ProtocolError } from '@libp2p/interface' +import { base64pad } from 'multiformats/bases/base64' +import { sha1 } from 'multiformats/hashes/sha1' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { BAD_REQUEST, toUint8Array } from '../utils.js' +import { StreamWebSocket } from './websocket.js' +import type { HeaderInfo } from '../index.js' +import type { AbortOptions, Stream } from '@libp2p/interface' +import type { ByteStream } from 'it-byte-stream' + +export function toBytes (data: string | Blob | Uint8Array | ArrayBuffer | DataView): Uint8Array | Promise { + if (data instanceof Uint8Array || data instanceof ArrayBuffer || data instanceof DataView) { + return toUint8Array(data) + } + + if (typeof data === 'string') { + return uint8ArrayFromString(data) + } + + if (data instanceof Blob) { + return data.arrayBuffer() + .then(buf => toUint8Array(buf)) + } + + throw new InvalidParametersError('Unsupported data type') +} + +export class CodeError extends Error { + public readonly code: number + + constructor (message: string, code?: number) { + super(message) + this.code = code ?? 0 + } +} + +export interface Response { + status: number + statusText: string + headers: Headers +} + +export async function readResponse (bytes: ByteStream, options: AbortOptions): Promise { + return new Promise((resolve, reject) => { + let readHeaders = false + + const parser = new HTTPParser('RESPONSE') + parser[HTTPParser.kOnHeadersComplete] = (info) => { + readHeaders = true + + const headers: Array<[string, string]> = [] + + for (let i = 0; i < info.headers.length; i += 2) { + headers.push([info.headers[i], info.headers[i + 1]]) + } + + resolve({ + status: info.statusCode, + statusText: info.statusMessage, + headers: new Headers(headers) + }) + } + + Promise.resolve() + .then(async () => { + while (true) { + if (readHeaders) { + break + } + + const chunk = await bytes.read(options) + + if (chunk == null) { + throw new Error('Stream ended before headers were received') + } + + parser.execute(chunk.subarray(), 0, chunk.byteLength) + } + }) + .catch((err: Error) => { + reject(err) + }) + }) +} + +function getHeader (headers: Headers | Record, key: string): string | undefined { + if (headers instanceof Headers) { + return headers.get(key) ?? undefined + } + + const header = headers[key] + + if (Array.isArray(header)) { + return header.join(',') + } + + return header +} + +/** + * Implements the WebSocket handshake from the client's perspective + */ +export async function * performClientUpgrade (url: URL, protocols: string[] = []): AsyncGenerator { + const webSocketKey = base64pad.encode( + crypto.getRandomValues(new Uint8Array(16)) + ).substring(1) + + const headers = [ + `GET ${url.pathname ?? '/'} HTTP/1.1`, + `Host: ${url.hostname}`, + 'Connection: upgrade', + 'Upgrade: websocket', + 'Pragma: no-cache', + 'Cache-Control: no-cache', + 'Sec-WebSocket-Version: 13', + `Sec-WebSocket-Key: ${webSocketKey}` + ] + + if (protocols.length > 0) { + headers.push(`Sec-WebSocket-Protocol: ${protocols?.join(', ')}`) + } + + headers.push('', '') + + const req = uint8ArrayFromString(headers.join('\r\n')) + yield req +} + +/** + * Implements the WebSocket handshake from the server's perspective + */ +export async function * performServerUpgrade (headers: Headers | Record): AsyncGenerator { + if (getHeader(headers, 'sec-websocket-version') !== '13') { + yield BAD_REQUEST + throw new ProtocolError('Invalid version') + } + + const secWebSocketKey = getHeader(headers, 'sec-websocket-key') + + if (secWebSocketKey == null) { + yield BAD_REQUEST + throw new ProtocolError('Missing sec-websocket-key') + } + + const token = `${secWebSocketKey}258EAFA5-E914-47DA-95CA-C5AB0DC85B11` + const hash = await sha1.digest(uint8ArrayFromString(token)) + const webSocketAccept = base64pad.encode( + hash.digest + ).substring(1) + + const message = [ + 'HTTP/1.1 101 Switching Protocols', + 'Upgrade: websocket', + 'Connection: upgrade', + `Sec-WebSocket-Accept: ${webSocketAccept}`, + '', + '' + ] + + yield uint8ArrayFromString(message.join('\r\n')) +} + +export function streamToWebSocket (info: HeaderInfo, stream: Stream): WebSocket { + return new StreamWebSocket(info, stream) +} diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts new file mode 100644 index 0000000..60e3d40 --- /dev/null +++ b/src/websocket/websocket.ts @@ -0,0 +1,412 @@ +import { TypedEventEmitter } from '@libp2p/interface' +import { isPromise } from '@libp2p/utils/is-promise' +import { byteStream, type ByteStream } from 'it-byte-stream' +import { Uint8ArrayList } from 'uint8arraylist' +import { PROTOCOL } from '../constants.js' +import { ErrorEvent } from './events.js' +import { encodeMessage, decodeMessage, CLOSE_MESSAGES } from './message.js' +import { performClientUpgrade, performServerUpgrade, readResponse, toBytes } from './utils.js' +import type { CloseListener, ErrorListener, MessageListener, OpenListener, WebSocketEvents } from './index.js' +import type { MESSAGE_TYPE } from './message.js' +import type { HeaderInfo } from '../index.js' +import type { Stream, AbortOptions } from '@libp2p/interface' +import type { ConnectionManager } from '@libp2p/interface-internal' +import type { Multiaddr } from '@multiformats/multiaddr' +import type { IncomingMessage } from 'node:http' +import type { Duplex } from 'node:stream' + +const DATA_MESSAGES: MESSAGE_TYPE[] = ['BINARY', 'TEXT', 'CONTINUATION'] +const MAX_MESSAGE_SIZE = 10_485_760 +const DEFAULT_HOST = 'example.com' + +export interface WebSocketInit extends AbortOptions { + protocols?: string[] + isClient?: boolean + + /** + * The maximum message size to be sent or received over the socket in bytes + * + * @default 10_485_760 + */ + maxMessageSize?: number +} + +export abstract class AbstractWebSocket extends TypedEventEmitter { + public readonly binaryType = 'arraybuffer' + public bufferedAmount = 0 + public extensions = '' + public protocol: string = '' + public readyState: number + public url: string + + public CONNECTING: 0 = 0 + public OPEN: 1 = 1 + public CLOSING: 2 = 2 + public CLOSED: 3 = 3 + + private _onclose?: CloseListener + private _onerror?: ErrorListener + private _onmessage?: MessageListener + private _onopen?: OpenListener + + private sentClose: boolean + private readonly isClient: boolean + private readonly buffer: Uint8ArrayList + private readonly maxMessageSize: number + protected readonly _url?: URL + protected readonly closeController: AbortController + + constructor (url: URL, init: WebSocketInit = {}) { + super() + + this.readyState = this.CONNECTING + this.url = url.pathname + this.sentClose = false + this.isClient = init.isClient ?? true + this.buffer = new Uint8ArrayList() + this.closeController = new AbortController() + this.maxMessageSize = init.maxMessageSize ?? MAX_MESSAGE_SIZE + } + + send (data: string | Blob | Uint8Array | ArrayBuffer | DataView): void { + if (this.readyState !== this.OPEN) { + throw new Error('WebSocket was not open') + } + + const b = toBytes(data) + + if (isPromise(b)) { + b.then(b => { + this._send('BINARY', b) + }) + .catch(err => { + this._errored(err) + }) + } else { + this._send('BINARY', b) + } + } + + _send (type: MESSAGE_TYPE, data?: Uint8Array): void { + if (this.readyState !== this.OPEN) { + return + } + + const message = encodeMessage(type, data, this.isClient) + + const byteLength = message.byteLength + this.bufferedAmount += byteLength + + this._write(message, (err) => { + this.bufferedAmount -= byteLength + + if (err != null) { + this._errored(err) + } + }) + } + + close (code?: number, reason?: string): void { + if (this.readyState !== this.OPEN) { + throw new Error('WebSocket was not open') + } + + this.readyState = this.CLOSING + this.sentClose = true + this._send('CONNECTION_CLOSE') + } + + _errored (err: Error): void { + this.readyState = this.CLOSED + this.dispatchEvent(new ErrorEvent(err)) + } + + set onclose (listener: CloseListener) { + this._onclose = listener + this.addEventListener('close', listener) + } + + get onclose (): CloseListener | null { + return this._onclose ?? null + } + + set onerror (listener: ErrorListener) { + this._onerror = listener + this.addEventListener('error', listener) + } + + get onerror (): ErrorListener | null { + return this._onerror ?? null + } + + set onmessage (listener: MessageListener) { + this._onmessage = listener + this.addEventListener('message', listener) + } + + get onmessage (): MessageListener | null { + return this._onmessage ?? null + } + + set onopen (listener: OpenListener) { + this._onopen = listener + this.addEventListener('open', listener) + } + + get onopen (): OpenListener | null { + return this._onopen ?? null + } + + protected _push (buf: Uint8Array | Uint8ArrayList): void { + this.buffer.append(buf) + + if (this.buffer.byteLength > this.maxMessageSize) { + this.close(CLOSE_MESSAGES.MESSAGE_TOO_BIG, 'Max message size exceeded') + return + } + + while (true) { + const message = decodeMessage(this.buffer) + + if (message == null) { + break + } + + if (DATA_MESSAGES.includes(message.type) && message.data != null) { + this.dispatchEvent(new MessageEvent('message', { + data: message.data, + origin: this._url?.hostname + })) + } + + // respond to pings + if (message.type === 'PING') { + this._send('PONG', message.data) + } + + // close handshake + if (message.type === 'CONNECTION_CLOSE') { + if (!this.sentClose) { + this.close() + } + + this.closeController.abort() + this._close(undefined, () => { + this.readyState = this.CLOSED + this.dispatchEvent(new CloseEvent('close')) + }) + } + } + } + + /** + * To be invoked when the underlying transport is closed by the remote end + */ + protected _remoteClosed (err?: Error): void { + this.readyState = this.CLOSING + this._close(err, () => { + this.readyState = this.CLOSED + this.dispatchEvent(new CloseEvent('close')) + }) + } + + /** + * Invoked when data is to be sent over the socket, the passed callback should + * be called when the data has been written + */ + protected abstract _write (buf: Uint8ArrayList, cb: (err?: Error | null) => void): void + + /** + * The implementation of this method should close the underlying transport. If + * an error is passed, the transport should be closed immediately. + * + * The passed callback should be invoked when the transport has closed + */ + protected abstract _close (err: Error | undefined, cb: () => void): void +} + +export class ServerWebSocket extends AbstractWebSocket { + private readonly duplex: Duplex + + constructor (request: IncomingMessage, duplex: Duplex, init: WebSocketInit = {}) { + super(new URL(`http://${request.headers.host ?? DEFAULT_HOST}${request.url}`), { + ...init, + isClient: false + }) + + this.duplex = duplex + + this.duplex.on('data', (buf) => { + this._push(buf) + }) + this.duplex.on('close', () => { + this.close() + }) + this.duplex.on('error', (err) => { + this.close(CLOSE_MESSAGES.ABNORMAL_CLOSURE, err.message) + }) + + Promise.resolve().then(async () => { + for await (const buf of performServerUpgrade(request.headers)) { + this.duplex.write(buf) + } + + this.readyState = this.OPEN + this.dispatchEvent(new Event('open')) + }) + .catch(err => { + this.duplex.destroy(err) + }) + } + + _write (buf: Uint8ArrayList, cb: (err?: Error | null) => void): void { + this.duplex.write(buf.subarray(), cb) + } + + _close (err: Error, cb: () => void): void { + this.readyState = this.CLOSED + this.duplex.destroy(err) + cb() + } +} + +export class StreamWebSocket extends AbstractWebSocket { + private readonly bytes: ByteStream + + constructor (info: HeaderInfo, stream: Stream, init?: WebSocketInit) { + super(new URL(`http://${info.headers.get('host') ?? DEFAULT_HOST}${info.url}`), { + ...init, + isClient: false + }) + + this.bytes = byteStream(stream) + + Promise.resolve() + .then(async () => { + for await (const buf of performServerUpgrade(info.headers)) { + await this.bytes.write(buf) + } + + this.readyState = this.OPEN + this.dispatchEvent(new Event('open')) + + while (true) { + const buf = await this.bytes.read() + + if (buf == null) { + this._remoteClosed() + break + } + + this._push(buf) + } + }) + .catch(err => { + this._errored(err) + }) + } + + _write (buf: Uint8ArrayList, cb: (err?: Error | null) => void): void { + this.bytes?.write(buf) + .then(() => { + cb() + }, err => { + cb(err) + }) + } + + _close (err: Error, cb: () => void): void { + const stream = this.bytes?.unwrap() + + if (err != null) { + stream?.abort(err) + cb() + } else { + stream?.close() + .then(() => { + cb() + }, err => { + stream.abort(err) + cb() + }) + } + } +} + +export class WebSocket extends AbstractWebSocket { + private bytes?: ByteStream + + constructor (mas: Multiaddr[], url: URL, connectionManager: ConnectionManager, init: WebSocketInit = {}) { + super(url, { + ...init, + isClient: true + }) + + Promise.resolve() + .then(async () => { + const connection = await connectionManager.openConnection(mas, init) + const stream = await connection.newStream(PROTOCOL, init) + this.bytes = byteStream(stream) + + for await (const buf of performClientUpgrade(url, init.protocols)) { + await this.bytes.write(buf) + } + + const res = await readResponse(this.bytes, {}) + + if (res.status !== 101) { + throw new Error('Invalid WebSocket handshake') + } + + // if a protocol was selected by the server, expose it + this.protocol = res.headers.get('Sec-WebSocket-Protocol') ?? '' + + this.readyState = this.OPEN + this.dispatchEvent(new Event('open')) + + for await (const buf of stream.source) { + this._push(buf) + } + }) + .catch(err => { + this._errored(err) + }) + } + + _write (buf: Uint8ArrayList, cb: (err?: Error | null) => void): void { + if (this.bytes == null) { + cb(new Error('WebSocket was not open')) + return + } + + this.bytes.write(buf) + .then(() => { + cb() + }, (err) => { + cb(err) + }) + } + + _close (err: Error | undefined, cb: () => void): void { + if (this.bytes == null) { + cb() + return + } + + const stream = this.bytes.unwrap() + + if (err != null) { + stream.abort(err) + cb() + return + } + + stream.close() + .catch((err) => { + stream.abort(err) + }) + .finally(() => { + cb() + }) + } +} diff --git a/src/well-known-handler.ts b/src/well-known-handler.ts index 63c9bc6..a7d09ce 100644 --- a/src/well-known-handler.ts +++ b/src/well-known-handler.ts @@ -1,29 +1,37 @@ export type ProtocolID = string -export { WELL_KNOWN_PROTOCOLS } from './constants.js' -export type ProtosMap = Record + +export interface ProtocolLocation { + path: string +} + +export type ProtocolMap = Record export class WellKnownHandler { - private readonly myWellKnownProtos: ProtosMap = {} + private readonly protocols: ProtocolMap = {} public async handleRequest (request: Request): Promise { - return new Response(JSON.stringify(this.myWellKnownProtos), { + return new Response(JSON.stringify(this.protocols), { headers: { 'Content-Type': 'application/json' } }) } - // Register a protocol with a path and remember it so we can tell our peers - // about it via .well-known + /** + * Register a protocol with a path and remember it so we can tell our peers + * about it via a request to "/.well-known/libp2p/protocols" + */ public registerProtocol (protocol: string, path: string): void { if (path === '') { path = '/' } + if (!path.startsWith('/')) { path = `/${path}` } - if (this.myWellKnownProtos[protocol] != null) { + if (this.protocols[protocol] != null) { throw new Error(`Protocol ${protocol} already registered`) } - this.myWellKnownProtos[protocol] = { path } + + this.protocols[protocol] = { path } } } diff --git a/src/whatwg-fetch-service.ts b/src/whatwg-fetch-service.ts deleted file mode 100644 index aec0c0d..0000000 --- a/src/whatwg-fetch-service.ts +++ /dev/null @@ -1,265 +0,0 @@ -import { isPeerId, type Logger, type PeerId, type Startable } from '@libp2p/interface' -import { multiaddr, protocols, type Multiaddr } from '@multiformats/multiaddr' -import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' -import { PROTOCOL_NAME, WELL_KNOWN_PROTOCOLS } from './constants.js' -import { fetchViaDuplex, handleRequestViaDuplex, type HTTPHandler } from './fetch/index.js' -import { WellKnownHandler, type ProtosMap } from './well-known-handler.js' -import type { CustomHTTPHandlerInit, FetchComponents, HTTPInit, HTTP as WHATWGFetchInterface } from './index.js' -import type { IncomingStreamData } from '@libp2p/interface-internal' - -export type { ProtosMap } from './well-known-handler.js' - -const multiaddrURIPrefix = 'multiaddr:' - -type ProtocolID = string -type ProtoHandlers = Record - -export class WHATWGFetch implements Startable, WHATWGFetchInterface { - private readonly log: Logger - public readonly protocol: string = PROTOCOL_NAME - private readonly components: FetchComponents - private started: boolean - private readonly _fetch: (request: Request) => Promise - private readonly customHTTPHandler?: (request: Request) => Promise - private readonly wellKnownProtosCache = new LRUCache(100) - private readonly wellKnownHandler = new WellKnownHandler() - // Used when matching paths to protocols. We match from most specific to least specific. - private readonly myProtosSortedByLength: Array<{ proto: ProtocolID, path: string }> = [] - private readonly protoHandlers: ProtoHandlers = {} - - _hasCustomHandler (h: HTTPInit | CustomHTTPHandlerInit): h is CustomHTTPHandlerInit { - return (h as CustomHTTPHandlerInit).customHTTPHandler !== undefined - } - - constructor (components: FetchComponents, init: HTTPInit | (HTTPInit & CustomHTTPHandlerInit)) { - this.components = components - this.log = components.logger.forComponent('libp2p:http-fetch') - this.started = false - if (init.fetch != null) { - this._fetch = init.fetch - } else if (typeof globalThis.fetch === 'function') { - this._fetch = globalThis.fetch - } else { - throw new Error('No fetch implementation provided and global fetch is not available') - } - - if (this._hasCustomHandler(init)) { - this.customHTTPHandler = init.customHTTPHandler - } - } - - async start (): Promise { - await this.components.registrar.handle(this.protocol, (data: IncomingStreamData) => { - void this.handleMessage(data).catch((err) => { - this.log.error('error handling perf protocol message', err) - }) - }, {}) - this.started = true - } - - async stop (): Promise { - await this.components.registrar.unhandle(this.protocol) - this.started = false - } - - isStarted (): boolean { - return this.started - } - - private async handleMessage (data: IncomingStreamData): Promise { - const { stream } = data - try { - if (this.customHTTPHandler != null) { - await handleRequestViaDuplex(stream, this.customHTTPHandler) - return - } - await handleRequestViaDuplex(stream, this.defaultMuxer.bind(this)) - } catch (err) { - this.log.error('Error handling message', err) - } - } - - private async defaultMuxer (req: Request): Promise { - try { - const url = new URL(req.url) - if (url.pathname === WELL_KNOWN_PROTOCOLS) { - return await this.serveWellKnownProtocols(req) - } - for (const p of this.myProtosSortedByLength) { - if (url.pathname.startsWith(p.path)) { - const handler = this.protoHandlers[p.proto] - if (handler != null) { - return await handler(req) - } - } - } - - // No handler found, 404 - return new Response(null, { status: 404 }) - } catch (err) { - this.log.error('Error in defaultMuxer', err) - return new Response(null, { status: 500 }) - } - } - - async serveWellKnownProtocols (req: Request): Promise { - return this.wellKnownHandler.handleRequest(req) - } - - async fetch (request: string | Request, requestInit?: RequestInit): Promise { - if (typeof request === 'string') { - return this.innerFetch(new Request(request, requestInit ?? {})) - } - return this.innerFetch(request) - } - - private async innerFetch (request: Request): Promise { - // Get the peer from the request - const { url } = request - if (url.startsWith(multiaddrURIPrefix)) { - const ma = multiaddr(url.substring(multiaddrURIPrefix.length)) - const peerWithoutHTTPPath = ma.decapsulateCode(protocols('http-path').code) - - if (this.isHTTPTransportMultiaddr(peerWithoutHTTPPath)) { - if (peerWithoutHTTPPath.getPeerId() !== null) { - throw new Error('HTTP Transport does not yet support peer IDs. Use a stream based transport instead.') - } - const [, httpPathVal] = ma.stringTuples().find(([code]) => - code === protocols('http-path').code - ) ?? ['', ''] - let path = decodeURIComponent(httpPathVal ?? '') - if (!path.startsWith('/')) { - path = `/${path}` - } - const reqUrl = `${multiaddrToUri(peerWithoutHTTPPath)}${path}` - // We want to make a request over native fetch, so we need to copy the - // request and change the URL to be an HTTP URI - return this._fetch(new Request(reqUrl, { - body: request.body, - // @ts-expect-error - TS doesn't know about this property - duplex: request.duplex ?? 'half', - headers: request.headers, - cache: request.cache, - credentials: request.credentials, - integrity: request.integrity, - keepalive: request.keepalive, - method: request.method, - mode: request.mode, - redirect: request.redirect, - referrer: request.referrer, - referrerPolicy: request.referrerPolicy, - signal: request.signal - })) - } else { - const conn = await this.components.connectionManager.openConnection(peerWithoutHTTPPath) - - const s = await conn.newStream(PROTOCOL_NAME) - return fetchViaDuplex(s)(request) - } - } - // Use browser fetch or polyfill... - return this._fetch(request) - } - - private isHTTPTransportMultiaddr (peer: Multiaddr): boolean { - const parts = peer.protos() - if (parts.length === 0) { - throw new Error('peer multiaddr must have at least one part') - } - - // Reverse order for faster common case (/http is near the end) - for (let i = parts.length - 1; i >= 0; i--) { - if (parts[i].name === 'http' || parts[i].name === 'https') { - return true - } - } - return false - } - - // Register a protocol with a path and remember it so we can tell our peers - // about it via .well-known - registerProtocol (protocol: string, path: string): void { - if (path === '') { - path = '/' - } - if (!path.startsWith('/')) { - path = `/${path}` - } - this.wellKnownHandler.registerProtocol(protocol, path) - this.myProtosSortedByLength.push({ proto: protocol, path }) - this.myProtosSortedByLength.sort(({ path: a }, { path: b }) => b.length - a.length) - } - - handleHTTPProtocol (protocol: ProtocolID, path: string, handler: (req: Request) => Promise): void { - this.registerProtocol(protocol, path) - this.protoHandlers[protocol] = handler - } - - async getPeerMeta (peerOrMultiaddr: PeerId | Multiaddr): Promise { - const peerAddr: Multiaddr = isPeerId(peerOrMultiaddr) ? multiaddr(`/p2p/${peerOrMultiaddr.toString()}`) : peerOrMultiaddr - let cacheKey = peerAddr - - if (!isPeerId(peerOrMultiaddr)) { - const peerIdStr = peerAddr.getPeerId() - if (peerIdStr !== null) { - // If we have a peer ID, we should use it as the key, since the same peer can have multiple addresses - cacheKey = multiaddr(`/p2p/${peerIdStr}`) - } - } - - const cached = this.wellKnownProtosCache.get(cacheKey) - if (cached !== undefined) { - return cached - } - - const reqUrl = multiaddrURIPrefix + peerAddr.encapsulate(`/http-path/${encodeURIComponent(WELL_KNOWN_PROTOCOLS)}`).toString() - const resp = await this.fetch(new Request(reqUrl, { - method: 'GET', - headers: { - Accept: 'application/json' - } - })) - if (resp.status !== 200) { - throw new Error(`Unexpected status code: ${resp.status}`) - } - const peerMeta = await resp.json() - this.wellKnownProtosCache.set(cacheKey, peerMeta) - return peerMeta - } - - async prefixForProtocol (peer: PeerId | Multiaddr, protocol: string): Promise { - const peerMeta = await this.getPeerMeta(peer) - if (peerMeta[protocol] == null) { - throw new Error(`Peer does not serve protocol: ${protocol}`) - } - return peerMeta[protocol].path - } -} - -class LRUCache { - private readonly size: number - private readonly cache: Map - constructor (size: number) { - this.size = size - this.cache = new Map() - } - - get (key: K): V | undefined { - const v = this.cache.get(key) - if (v != null) { - // Move to front - this.cache.delete(key) - this.cache.set(key, v) - } - return v - } - - set (key: K, value: V): void { - if (this.cache.has(key)) { - this.cache.delete(key) - } else if (this.cache.size >= this.size) { - this.cache.delete(this.cache.keys().next().value) - } - this.cache.set(key, value) - } -} diff --git a/test/auth.spec.ts b/test/auth.spec.ts new file mode 100644 index 0000000..7a5c5c2 --- /dev/null +++ b/test/auth.spec.ts @@ -0,0 +1,111 @@ +/* eslint-disable max-nested-callbacks */ +import http from 'node:http' +import { generateKeyPair } from '@libp2p/crypto/keys' +import './websockets.spec.js' +import './fetch.spec.js' +import './ping.spec.js' +import './websocket/message.spec.js' +import { peerIdFromPrivateKey } from '@libp2p/peer-id' +import { expect } from 'aegir/chai' +import pDefer from 'p-defer' +import { isNode, isElectronMain } from 'wherearewe' +import { ClientAuth, ServerAuth } from '../src/auth/index.js' +import type { PeerId, PrivateKey } from '@libp2p/interface' + +describe('client auth', () => { + let clientKey: PrivateKey + let serverKey: PrivateKey + let server: http.Server + + beforeEach(async () => { + clientKey = await generateKeyPair('Ed25519') + serverKey = await generateKeyPair('Ed25519') + }) + + afterEach(async () => { + server?.close() + server?.closeAllConnections() + }) + + it('should perform auth from client', async () => { + if (!isNode && !isElectronMain) { + return + } + + const clientAuth = new ClientAuth(clientKey) + const serverAuth = new ServerAuth(serverKey, h => h.startsWith('127.0.0.1')) + const clientPeer = pDefer() + const echoListener = serverAuth.requestListener((clientId, req, res) => { + clientPeer.resolve(clientId) + req.pipe(res) + }) + + server = http.createServer(echoListener) + + const port = await new Promise((resolve, reject) => { + const listener = server.listen(0, () => { + const address = listener.address() + + if (address == null || typeof address === 'string') { + reject(new Error('Could not listen on port')) + return + } + + resolve(address.port) + }) + }) + + await expect(clientAuth.authenticateServer(`http://127.0.0.1:${port}`)).to.eventually.deep.equal(peerIdFromPrivateKey(serverKey)) + await expect(clientPeer.promise).to.eventually.deep.equal(peerIdFromPrivateKey(clientKey)) + }) + + it('should respect cookies during auth', async () => { + if (!isNode && !isElectronMain) { + return + } + + const clientAuth = new ClientAuth(clientKey) + const serverAuth = new ServerAuth(serverKey, h => h.startsWith('127.0.0.1')) + const cookie = pDefer() + const echoListener = serverAuth.requestListener((clientId, req, res) => { + req.pipe(res) + }) + const cookieName = 'test-cookie-name' + const cookieValue = 'test-cookie-value' + let requests = 0 + + server = http.createServer((req, res) => { + requests++ + + const cookieHeader = req.headers.cookie + + if (cookieHeader == null) { + if (requests === 2) { + cookie.reject(new Error('No cookie header found on second request')) + } + + res.setHeader('set-cookie', `${cookieName}=${cookieValue}; Expires=${new Date(Date.now() + 86_400_000).toString()}; HttpOnly`) + } else { + cookie.resolve(cookieHeader) + } + + echoListener(req, res) + }) + + const port = await new Promise((resolve, reject) => { + const listener = server.listen(0, () => { + const address = listener.address() + + if (address == null || typeof address === 'string') { + reject(new Error('Could not listen on port')) + return + } + + resolve(address.port) + }) + }) + + await expect(clientAuth.authenticateServer(`http://127.0.0.1:${port}`)).to.eventually.deep.equal(peerIdFromPrivateKey(serverKey)) + await expect(cookie.promise).to.eventually.equal(`${cookieName}=${cookieValue}`) + }) +}) diff --git a/test/fetch.spec.ts b/test/fetch.spec.ts new file mode 100644 index 0000000..9289057 --- /dev/null +++ b/test/fetch.spec.ts @@ -0,0 +1,257 @@ +import { stop } from '@libp2p/interface' +import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import { createServer } from '../src/http/index.js' +import { nodeServer } from '../src/servers/node.js' +import { getClient, getListener } from './fixtures/get-libp2p.js' +import { getServer } from './fixtures/get-server.js' +import type { HTTP } from '../src/index.js' +import type { Libp2p } from 'libp2p' + +interface Test { + name: string + startServer(): Promise + stopServer(): Promise +} + +let listener: Libp2p<{ http: HTTP }> + +const tests: Test[] = [{ + name: 'in-process server', + startServer: async () => { + const server = getServer(createServer) + listener = await getListener(nodeServer(server)) + + return listener.getMultiaddrs() + }, + stopServer: async () => { + await stop(listener) + } +}, { + name: 'js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_HTTP_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_HTTP_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'express/js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_EXPRESS_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'express/node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_EXPRESS_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'fastify/js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_FASTIFY_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'fastify/node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_FASTIFY_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}] + +for (const test of tests) { + describe(`fetch - ${test.name}`, () => { + let client: Libp2p<{ http: HTTP }> + let listenerMultiaddrs: Multiaddr[] + + beforeEach(async () => { + client = await getClient() + listenerMultiaddrs = await test.startServer() + }) + + afterEach(async () => { + await stop(client) + await test.stopServer() + }) + + it('should fetch GET', async () => { + const response = await client.services.http.fetch(listenerMultiaddrs, { + headers: { + host: 'example.com' + } + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal('Hello World!') + }) + + it('should fetch POST with string', async () => { + const body = 'echo body' + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(body) + }) + + it('should fetch POST with ArrayBuffer', async () => { + const body = Uint8Array.from([0, 1, 2, 3, 4]).buffer + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body + }) + expect(response.status).to.equal(200) + await expect(response.arrayBuffer()).to.eventually.deep.equal(body) + }) + + it('should fetch POST with Blob', async () => { + const body = Uint8Array.from([0, 1, 2, 3, 4]).buffer + const blob = new Blob([body]) + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body: blob + }) + expect(response.status).to.equal(200) + await expect(response.arrayBuffer()).to.eventually.deep.equal(body) + }) + + it('should fetch POST with DataView', async () => { + const body = Uint8Array.from([0, 1, 2, 3, 4]).buffer + const view = new DataView(body) + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body: view + }) + expect(response.status).to.equal(200) + await expect(response.arrayBuffer()).to.eventually.deep.equal(body) + }) + + it('should fetch POST with File', async () => { + const body = Uint8Array.from([0, 1, 2, 3, 4]).buffer + const file = new File([body], 'file.txt') + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body: file + }) + expect(response.status).to.equal(200) + await expect(response.arrayBuffer()).to.eventually.deep.equal(body) + }) + + it('should fetch POST with FormData', async () => { + const data = Uint8Array.from([0, 1, 2, 3, 4]).buffer + const blob = new Blob([data]) + const body = new FormData() + body.append('foo', 'bar') + body.append('baz', blob) + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body + }) + expect(response.status).to.equal(200) + }) + + it('should fetch POST with TypedArray', async () => { + const body = Uint8Array.from([0, 1, 2, 3, 4]) + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body + }) + expect(response.status).to.equal(200) + await expect(response.arrayBuffer()).to.eventually.deep.equal(body.buffer) + }) + + it('should fetch POST with URLSearchParams', async () => { + const body = new URLSearchParams() + body.set('foo', 'bar') + body.set('baz', 'qux') + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.deep.equal(body.toString()) + }) + + it('should fetch POST with ReadableStream', async () => { + const buf = Uint8Array.from([0, 1, 2, 3, 4]) + const body = new ReadableStream({ + start (controller) { + controller.enqueue(buf) + controller.close() + } + }) + + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/echo')), { + method: 'POST', + headers: { + host: 'example.com' + }, + body + }) + expect(response.status).to.equal(200) + await expect(response.arrayBuffer()).to.eventually.deep.equal(buf.buffer) + }) + }) +} diff --git a/test/fetch/index.spec.ts b/test/fetch/index.spec.ts index 22fb400..432cc19 100644 --- a/test/fetch/index.spec.ts +++ b/test/fetch/index.spec.ts @@ -4,7 +4,7 @@ import { expect } from 'aegir/chai' import { duplexPair } from 'it-pair/duplex' import { type Uint8ArrayList, isUint8ArrayList } from 'uint8arraylist' -import { fetchViaDuplex, handleRequestViaDuplex } from '../../src/fetch/index.js' +import { fetchViaDuplex, handleRequestViaDuplex } from '../../src/fetch.js' import { cases } from './cases/cases.js' describe('Roundtrips', () => { @@ -12,7 +12,6 @@ describe('Roundtrips', () => { const [client, server] = duplexPair() const serverHandler = handleRequestViaDuplex(server, async (req) => { - console.log('Got request', req) return new Response('Hello World') }).catch((err) => { console.error('Error handling request', err) @@ -41,7 +40,6 @@ describe('Make a fetch request via duplex', () => { reqToServer += decoder.decode(chunk) } - console.log(reqToServer) expect(reqToServer).to.equal('GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n') void server.sink((async function * () { @@ -87,7 +85,6 @@ describe('Make a fetch request via duplex', () => { reqToServer += decoder.decode(chunk) } - console.log(reqToServer) expect(reqToServer).to.equal('POST /?foo=bar HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\ncontent-type: text/plain;charset=UTF-8\r\nx-test: foo\r\nTransfer-Encoding: chunked\r\n\r\nb\r\nhello world\r\n0\r\n\r\n') void server.sink((async function * () { diff --git a/test/fixtures/create-express.ts b/test/fixtures/create-express.ts new file mode 100644 index 0000000..3798e4b --- /dev/null +++ b/test/fixtures/create-express.ts @@ -0,0 +1,38 @@ +import express from 'express' +import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { Server } from 'node:http' + +/** + * Creates an Express server that optionally delegates request handling to a + * Libp2p Over HTTP handler + */ +export function createExpress (server: Server, handler?: Libp2pOverHTTPHandler): Server { + const app = express() + app.get('/', (req, res) => { + res.send('Hello World!') + }) + app.post('/echo', (req, res) => { + req.on('data', (buf) => { + res.write(buf) + }) + req.on('end', () => { + res.end() + }) + req.on('error', (err) => { + res.destroy(err) + }) + }) + + server.on('request', (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (handler?.(req, res) !== true) { + app(req, res) + } + }) + + return server +} diff --git a/test/fixtures/create-fastify-http.ts b/test/fixtures/create-fastify-http.ts new file mode 100644 index 0000000..d04af29 --- /dev/null +++ b/test/fixtures/create-fastify-http.ts @@ -0,0 +1,54 @@ +import { fastify } from 'fastify' +import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { FastifyRequest } from 'fastify' +import type { Server, IncomingMessage } from 'node:http' + +export async function createFastifyHTTP (server: Server, handler?: Libp2pOverHTTPHandler): Promise { + const app = fastify({ + serverFactory: (app, opts) => { + server.addListener('request', (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (handler?.(req, res) !== true) { + app(req, res) + } + }) + + return server + } + }) + + // fastify only supports 'application/json' and 'text/plain' by default + app.addContentTypeParser('*', async (req: FastifyRequest, payload: IncomingMessage) => { + return payload + }) + app.get('/', async (req, reply) => { + await reply.send('Hello World!') + }) + app.post('/echo', (req, reply) => { + if (typeof req.body === 'string') { + return reply.send(req.body) + } + + req.raw.on('data', (buf) => { + reply.raw.write(buf) + }) + req.raw.on('end', () => { + reply.raw.end() + }) + req.raw.on('error', (err) => { + reply.raw.destroy(err) + }) + }) + + await app.ready() + + if (server == null) { + throw new Error('Server not created') + } + + return server +} diff --git a/test/fixtures/create-fastify-websocket.ts b/test/fixtures/create-fastify-websocket.ts new file mode 100644 index 0000000..06efe5c --- /dev/null +++ b/test/fixtures/create-fastify-websocket.ts @@ -0,0 +1,48 @@ +import fastifyWebSocket from '@fastify/websocket' +import { fastify } from 'fastify' +import { toWebSocket } from './to-websocket.js' +import type { Libp2pOverHTTPHandler, Libp2pOverWSHandler } from './get-libp2p-over-http-handler.js' +import type { Server } from 'node:http' + +export async function createFastifyWebSocket (server: Server, httpHandler?: Libp2pOverHTTPHandler, wsHandler?: Libp2pOverWSHandler): Promise { + const app = fastify({ + serverFactory: (app, opts) => { + server.addListener('request', (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (httpHandler?.(req, res) !== true) { + app(req, res) + } + }) + + return server + } + }) + await app.register(fastifyWebSocket) + await app.register(async function (fastify) { + fastify.get('/echo', { websocket: true }, (socket, req) => { + socket.on('message', message => { + socket.send(message) + }) + }) + fastify.get('/*', { websocket: true }, (socket, req) => { + if (wsHandler?.(toWebSocket(socket, req)) === true) { + return + } + + socket.send('Hello world!') + socket.close() + }) + }) + + await app.ready() + + if (server == null) { + throw new Error('Server not created') + } + + return server +} diff --git a/test/fixtures/create-http.ts b/test/fixtures/create-http.ts new file mode 100644 index 0000000..ef9522e --- /dev/null +++ b/test/fixtures/create-http.ts @@ -0,0 +1,27 @@ +import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { Server, RequestListener } from 'node:http' + +export function createHttp (server: Server, handler?: Libp2pOverHTTPHandler): Server { + const app: RequestListener = (req, res) => { + if (req.url === '/echo') { + req.pipe(res) + + return + } + + res.end('Hello World!') + } + + server.on('request', (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (handler?.(req, res) !== true) { + app(req, res) + } + }) + + return server +} diff --git a/test/fixtures/create-websocket-server.ts b/test/fixtures/create-websocket-server.ts new file mode 100644 index 0000000..01b4eeb --- /dev/null +++ b/test/fixtures/create-websocket-server.ts @@ -0,0 +1,42 @@ +import { createWebSocketServer as createWss } from '../../src/websocket/index.js' +import type { Libp2pOverHTTPHandler, Libp2pOverWSHandler } from './get-libp2p-over-http-handler.js' +import type { Server } from 'node:http' + +export function createWebSocketServer (server: Server, httpHandler?: Libp2pOverHTTPHandler, wsHandler?: Libp2pOverWSHandler): Server { + const wss = createWss() + wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + if (wsHandler?.(ws) === true) { + return + } + + if (ws.url === '/echo') { + ws.addEventListener('message', (evt) => { + ws.send(evt.data) + }) + } else { + ws.send('Hello world!') + ws.close() + } + }) + + server.on('request', (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (httpHandler?.(req, res) === true) { + return + } + + res.writeHead(400) + res.end() + }) + server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head) + }) + + return server +} diff --git a/test/fixtures/create-wss.ts b/test/fixtures/create-wss.ts new file mode 100644 index 0000000..f06ed23 --- /dev/null +++ b/test/fixtures/create-wss.ts @@ -0,0 +1,43 @@ +import { WebSocketServer } from 'ws' +import { toWebSocket } from './to-websocket.js' +import type { Libp2pOverHTTPHandler, Libp2pOverWSHandler } from './get-libp2p-over-http-handler.js' +import type { Server } from 'node:http' + +export function createWss (server: Server, httpHandler?: Libp2pOverHTTPHandler, wsHandler?: Libp2pOverWSHandler): Server { + const wss = new WebSocketServer({ noServer: true }) + wss.on('connection', (ws, req) => { + if (wsHandler?.(toWebSocket(ws, req)) === true) { + return + } + + if (req.url === '/echo') { + ws.on('message', (data) => { + ws.send(data) + }) + } else { + ws.send('Hello world!') + ws.close() + } + }) + + server.on('request', (req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (httpHandler?.(req, res) === true) { + return + } + + res.writeHead(400) + res.end() + }) + server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) + }) + + return server +} diff --git a/test/fixtures/get-libp2p-over-http-handler.ts b/test/fixtures/get-libp2p-over-http-handler.ts new file mode 100644 index 0000000..6a510f6 --- /dev/null +++ b/test/fixtures/get-libp2p-over-http-handler.ts @@ -0,0 +1,74 @@ +import { createLibp2p } from 'libp2p' +import { http } from '../../src/index.js' +import { pingHTTP, type PingHTTP } from '../../src/ping/index.js' +import { incomingMessageToRequest, writeResponse } from '../../src/servers/node.js' +import type { HTTP } from '../../src/index.js' +import type { Libp2p } from '@libp2p/interface' +import type { IncomingMessage, ServerResponse } from 'node:http' + +export interface Libp2pOverHTTPHandler { + /** + * Returns `true` if the libp2p HTTP service will handle this request (e.g. it + * is for protocol map published at the `/.well-known` location or there is a + * protocol handler registered for this path). + */ + (req: IncomingMessage, res: ServerResponse): boolean +} + +export interface Libp2pOverWSHandler { + /** + * Returns `true` if the libp2p HTTP service will handle this request (e.g. it + * is for protocol map published at the `/.well-known` location or there is a + * protocol handler registered for this path). + */ + (ws: WebSocket): boolean +} + +export interface Libp2pOverHttpHandlerResults { + http: Libp2pOverHTTPHandler + ws: Libp2pOverWSHandler + libp2p: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> +} + +export async function getLibp2pOverHttpHandler (): Promise { + const libp2p = await createLibp2p({ + services: { + http: http(), + pingHTTP: pingHTTP() + }, + connectionManager: { + inboundConnectionThreshold: Infinity + } + }) + + const httpHandler = (req: IncomingMessage, res: ServerResponse): boolean => { + if (libp2p.services.http.canHandleHTTP(req)) { + libp2p.services.http.handleHTTP(incomingMessageToRequest(req)) + .then(result => { + writeResponse(result, res) + }) + .catch(err => { + res.writeHead(500, err.toString()) + res.end() + }) + return true + } + + return false + } + + const wsHandler = (ws: WebSocket): boolean => { + if (libp2p.services.http.canHandleWebSocket(ws)) { + libp2p.services.http.handleWebSocket(ws) + return true + } + + return false + } + + return { + libp2p, + http: httpHandler, + ws: wsHandler + } +} diff --git a/test/fixtures/get-libp2p.ts b/test/fixtures/get-libp2p.ts new file mode 100644 index 0000000..880842b --- /dev/null +++ b/test/fixtures/get-libp2p.ts @@ -0,0 +1,58 @@ +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { memory } from '@libp2p/memory' +import { ping } from '@libp2p/ping' +import { webSockets } from '@libp2p/websockets' +import { createLibp2p } from 'libp2p' +import { http } from '../../src/index.js' +import { pingHTTP } from '../../src/ping/index.js' +import type { Endpoint, HTTP } from '../../src/index.js' +import type { Libp2p } from '@libp2p/interface' + +export async function getListener (server: Endpoint, listen: string = '/memory/address-1'): Promise> { + return createLibp2p({ + addresses: { + listen: [ + listen + ] + }, + transports: [ + webSockets(), + memory() + ], + connectionEncrypters: [ + noise() + ], + streamMuxers: [ + yamux() + ], + services: { + http: http({ server }), + ping: ping(), + pingHTTP: pingHTTP() + }, + connectionManager: { + inboundConnectionThreshold: Infinity + } + }) +} + +export async function getClient (): Promise> { + return createLibp2p({ + transports: [ + webSockets(), + memory() + ], + connectionEncrypters: [ + noise() + ], + streamMuxers: [ + yamux() + ], + services: { + http: http(), + ping: ping(), + pingHTTP: pingHTTP() + } + }) +} diff --git a/test/fixtures/get-server.ts b/test/fixtures/get-server.ts new file mode 100644 index 0000000..8a5bf23 --- /dev/null +++ b/test/fixtures/get-server.ts @@ -0,0 +1,26 @@ +import type { createServer } from 'node:http' + +export function getServer (s: typeof createServer): ReturnType { + return s((req, res) => { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + + if (req.url === '/echo') { + req.on('data', buf => { + res.write(buf) + }) + req.on('end', () => { + res.end() + }) + req.on('error', err => { + res.destroy(err) + }) + + return + } + + res.end('Hello World!') + }) +} diff --git a/test/fixtures/to-websocket.ts b/test/fixtures/to-websocket.ts new file mode 100644 index 0000000..f23efa5 --- /dev/null +++ b/test/fixtures/to-websocket.ts @@ -0,0 +1,32 @@ +import type { WebSocket as WSSWebSocket } from 'ws' + +export function toWebSocket (ws: WSSWebSocket, req: { url?: string }): WebSocket { + Object.defineProperty(ws, 'url', { + value: req.url, + writable: false + }) + + // @ts-expect-error not a WS/WebSocket method + ws.dispatchEvent = (evt: Event) => { + if (evt.type === 'close') { + ws.emit('close') + } + + if (evt.type === 'open') { + ws.emit('open') + } + + if (evt.type === 'message') { + const m = evt as MessageEvent + ws.emit('data', m.data) + } + + if (evt.type === 'error') { + ws.emit('error', new Error('An error occurred')) + } + ws.emit(evt.type, evt) + } + + // @ts-expect-error ws is now WebSocket + return ws +} diff --git a/test/index.spec.ts b/test/index.spec.ts deleted file mode 100644 index 9830e21..0000000 --- a/test/index.spec.ts +++ /dev/null @@ -1,109 +0,0 @@ -/* eslint-env mocha */ - -import { isPeerId, start, stop } from '@libp2p/interface' -import { streamPair } from '@libp2p/interface-compliance-tests/mocks' -import { defaultLogger } from '@libp2p/logger' -import { peerIdFromString } from '@libp2p/peer-id' -import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' -import { expect } from 'aegir/chai' -import { duplexPair } from 'it-pair/duplex' -import { type Libp2p } from 'libp2p' -import pDefer from 'p-defer' -import { stubInterface, type StubbedInstance } from 'sinon-ts' -import { http, type HTTP } from '../src/index.js' -import * as ping from '../src/ping.js' -import type { ComponentLogger, Connection, PeerId, StreamHandler } from '@libp2p/interface' -import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' - -interface StubbedHTTPComponents { - registrar: StubbedInstance - connectionManager: StubbedInstance - logger: ComponentLogger -} - -export function createComponents (): StubbedHTTPComponents { - return { - registrar: stubInterface(), - connectionManager: stubInterface(), - logger: defaultLogger() - } -} - -describe('whatwg-fetch', () => { - let serverComponents: StubbedHTTPComponents - let clientComponents: StubbedHTTPComponents - let server: HTTP - let client: HTTP - const serverPeerID: PeerId = peerIdFromString('12D3KooWJRSrypvnpHgc6ZAgyCni4KcSmbV7uGRaMw5LgMKT18fq') - const serverMultiaddr: Multiaddr = multiaddr('/ip4/1.2.3.4/tcp/1234' + '/p2p/' + serverPeerID.toString()) - - beforeEach(async () => { - serverComponents = createComponents() - clientComponents = createComponents() - await start(serverComponents) - await start(clientComponents) - - let serverCB: StreamHandler - const serverCBRegistered = pDefer() - serverComponents.registrar.handle.callsFake(async (protocol: string, cb: StreamHandler) => { - serverCB = cb - serverCBRegistered.resolve() - }) - - const conn = stubInterface() - conn.newStream.callsFake(async (protos: string | string[], options?: any) => { - const duplexes = duplexPair() - const streams = streamPair({ duplex: duplexes[0] }, { duplex: duplexes[1] }) - serverCB({ stream: streams[0], connection: conn }) - return streams[1] - }) - - clientComponents.connectionManager.openConnection.callsFake(async (peer: PeerId | Multiaddr | Multiaddr[]) => { - if (Array.isArray(peer)) { - peer = peer[0] - } - - if (isPeerId(peer) ? peer.equals(serverPeerID) : peer.getPeerId() === serverMultiaddr.getPeerId()) { - await serverCBRegistered.promise - return conn - } - throw new Error('Unexpected peer: ' + peer.toString()) - }) - - server = http()(serverComponents) - client = http()(clientComponents) - await start(client) - await start(server) - }) - - afterEach(async () => { - await stop(serverComponents) - await stop(clientComponents) - await stop(server) - await stop(client) - }) - - it('Standard ping roundtrip', async () => { - // Mount the ping handler on the server under /ping - server.handleHTTPProtocol(ping.PING_PROTOCOL_ID, '/ping', ping.servePing) - - const clientNode = stubInterface>({ services: { http: client } }) - - await ping.sendPing(clientNode, serverMultiaddr) - }) - - it('Standard ping roundtrip with peer id', async () => { - // Mount the ping handler on the server under /ping - server.handleHTTPProtocol(ping.PING_PROTOCOL_ID, '/ping', ping.servePing) - - const clientNode = stubInterface>({ services: { http: client } }) - - await ping.sendPing(clientNode, serverPeerID) - }) - - it('Throws an error if using an http transport with a peer id component', async () => { - const clientNode = stubInterface>({ services: { http: client } }) - - await expect(ping.sendPing(clientNode, multiaddr('/ip4/127.0.0.1/http/p2p/' + serverPeerID.toString()))).to.be.rejectedWith('HTTP Transport does not yet support peer IDs') - }) -}) diff --git a/test/node.ts b/test/node.ts deleted file mode 100644 index 7894ed5..0000000 --- a/test/node.ts +++ /dev/null @@ -1,99 +0,0 @@ -import http from 'node:http' -import { generateKeyPair } from '@libp2p/crypto/keys' -import { peerIdFromPrivateKey } from '@libp2p/peer-id' -import { expect } from 'aegir/chai' -import pDefer from 'p-defer' -import { ClientAuth, ServerAuth } from '../src/auth/index.js' -import type { PeerId, PrivateKey } from '@libp2p/interface' - -describe('@libp2p/http-fetch', () => { - describe('client auth', () => { - let clientKey: PrivateKey - let serverKey: PrivateKey - let server: http.Server - - beforeEach(async () => { - clientKey = await generateKeyPair('Ed25519') - serverKey = await generateKeyPair('Ed25519') - }) - - afterEach(async () => { - server?.close() - server?.closeAllConnections() - }) - - it('should perform auth from client', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h.startsWith('127.0.0.1')) - const clientPeer = pDefer() - const echoListener = serverAuth.requestListener((clientId, req, res) => { - clientPeer.resolve(clientId) - req.pipe(res) - }) - - server = http.createServer(echoListener) - - const port = await new Promise((resolve, reject) => { - const listener = server.listen(0, () => { - const address = listener.address() - - if (address == null || typeof address === 'string') { - reject(new Error('Could not listen on port')) - return - } - - resolve(address.port) - }) - }) - - await expect(clientAuth.authenticateServer(`http://127.0.0.1:${port}`)).to.eventually.deep.equal(peerIdFromPrivateKey(serverKey)) - await expect(clientPeer.promise).to.eventually.deep.equal(peerIdFromPrivateKey(clientKey)) - }) - - it('should respect cookies during auth', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h.startsWith('127.0.0.1')) - const cookie = pDefer() - const echoListener = serverAuth.requestListener((clientId, req, res) => { - req.pipe(res) - }) - const cookieName = 'test-cookie-name' - const cookieValue = 'test-cookie-value' - let requests = 0 - - server = http.createServer((req, res) => { - requests++ - - const cookieHeader = req.headers.cookie - - if (cookieHeader == null) { - if (requests === 2) { - cookie.reject(new Error('No cookie header found on second request')) - } - - res.setHeader('set-cookie', `${cookieName}=${cookieValue}; Expires=${new Date(Date.now() + 86_400_000).toString()}; HttpOnly`) - } else { - cookie.resolve(cookieHeader) - } - - echoListener(req, res) - }) - - const port = await new Promise((resolve, reject) => { - const listener = server.listen(0, () => { - const address = listener.address() - - if (address == null || typeof address === 'string') { - reject(new Error('Could not listen on port')) - return - } - - resolve(address.port) - }) - }) - - await expect(clientAuth.authenticateServer(`http://127.0.0.1:${port}`)).to.eventually.deep.equal(peerIdFromPrivateKey(serverKey)) - await expect(cookie.promise).to.eventually.equal(`${cookieName}=${cookieValue}`) - }) - }) -}) diff --git a/test/ping.spec.ts b/test/ping.spec.ts new file mode 100644 index 0000000..5842838 --- /dev/null +++ b/test/ping.spec.ts @@ -0,0 +1,318 @@ +/* eslint-env mocha */ + +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { generateKeyPair } from '@libp2p/crypto/keys' +import { NotFoundError, peerRoutingSymbol, stop } from '@libp2p/interface' +import { memory } from '@libp2p/memory' +import { peerIdFromPrivateKey } from '@libp2p/peer-id' +import { webSockets } from '@libp2p/websockets' +import { multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import { createLibp2p } from 'libp2p' +import { http } from '../src/index.js' +import { pingHTTP } from '../src/ping/index.js' +import type { HTTP } from '../src/index.js' +import type { PingHTTP } from '../src/ping/index.js' +import type { Libp2p, PeerId, PeerInfo } from '@libp2p/interface' + +describe('pingHTTP', () => { + let client: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> + let listener: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> + + beforeEach(async () => { + listener = await createLibp2p({ + addresses: { + listen: [ + '/memory/address-1' + ] + }, + transports: [ + memory() + ], + streamMuxers: [ + yamux() + ], + connectionEncrypters: [ + noise() + ], + services: { + http: http(), + pingHTTP: pingHTTP() + } + }) + + client = await createLibp2p({ + transports: [ + memory() + ], + streamMuxers: [ + yamux() + ], + connectionEncrypters: [ + noise() + ], + services: { + http: http(), + pingHTTP: pingHTTP() + }, + peerRouters: [ + () => { + const routing: any = { + async findPeer (peerId: PeerId): Promise { + if (peerId.equals(listener.peerId)) { + return { + id: listener.peerId, + multiaddrs: listener.getMultiaddrs() + } + } + + throw new NotFoundError() + }, + async * getClosestPeers () {} + } + routing[peerRoutingSymbol] = routing + + return routing + } + ] + }) + }) + + afterEach(async () => { + await stop(client, listener) + }) + + it('should perform ping with multiaddr', async () => { + await expect(client.services.pingHTTP.ping(listener.getMultiaddrs()[0])).to.eventually.be.a('number') + }) + + it('should perform ping with multiaddrs', async () => { + await expect(client.services.pingHTTP.ping(listener.getMultiaddrs())).to.eventually.be.a('number') + }) + + it('should perform ping with a peer id', async () => { + await expect(client.services.pingHTTP.ping(listener.peerId)).to.eventually.be.a('number') + }) +}) + +const LIBP2P_SERVERS = [{ + name: 'node:http', + address: multiaddr(process.env.LIBP2P_JS_HTTP_MULTIADDR) +}, { + name: 'js', + address: multiaddr(process.env.LIBP2P_NODE_HTTP_MULTIADDR) +}, { + name: 'express/js', + address: multiaddr(process.env.LIBP2P_JS_EXPRESS_MULTIADDR) +}, { + name: 'express/node:http', + address: multiaddr(process.env.LIBP2P_NODE_EXPRESS_MULTIADDR) +}, { + name: 'fastify/js', + address: multiaddr(process.env.LIBP2P_JS_FASTIFY_MULTIADDR) +}, { + name: 'fastify/node:http', + address: multiaddr(process.env.LIBP2P_NODE_FASTIFY_MULTIADDR) +}] + +describe('ping - HTTP over libp2p', () => { + let client: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> + + beforeEach(async () => { + client = await createLibp2p({ + transports: [ + webSockets() + ], + streamMuxers: [ + yamux() + ], + connectionEncrypters: [ + noise() + ], + services: { + http: http(), + pingHTTP: pingHTTP() + } + }) + }) + + afterEach(async () => { + await stop(client) + }) + + LIBP2P_SERVERS.forEach(test => { + it(`should perform ping with ${test.name} server`, async () => { + await expect(client.services.pingHTTP.ping(multiaddr(test.address))).to.eventually.be.a('number') + }) + + it('should perform ping with multiaddrs', async () => { + await expect(client.services.pingHTTP.ping(multiaddr(test.address))).to.eventually.be.a('number') + }) + + it('should perform ping with a peer id', async () => { + await expect(client.services.pingHTTP.ping(multiaddr(test.address))).to.eventually.be.a('number') + }) + }) +}) + +const HTTP_SERVERS = [{ + name: 'node:http', + address: multiaddr(process.env.HTTP_NODE_HTTP_MULTIADDR) +}, { + name: 'express', + address: multiaddr(process.env.HTTP_EXPRESS_MULTIADDR) +}, { + name: 'fastify', + address: multiaddr(process.env.HTTP_FASTIFY_MULTIADDR) +}] + +describe('ping - libp2p over HTTP', () => { + let client: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> + + beforeEach(async () => { + client = await createLibp2p({ + services: { + http: http(), + pingHTTP: pingHTTP() + } + }) + }) + + afterEach(async () => { + await stop(client) + }) + + HTTP_SERVERS.forEach(test => { + it(`should perform ping with the HTTP address of a ${test.name} server`, async () => { + const httpAddr = multiaddr(test.address) + + await expect(client.services.pingHTTP.ping(httpAddr)).to.eventually.be.a('number') + }) + + it(`should perform ping with a HTTP address with a peer id of a ${test.name} server`, async () => { + const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${process.env.HTTP_PEER_ID}`) + + await expect(client.services.pingHTTP.ping(httpAddr)).to.eventually.be.a('number') + }) + + it.skip(`should reject when performing ping with a HTTP address with the wrong peer id of a ${test.name} server`, async () => { + // TODO: detect PeerID in HTTP multiaddr and apply peer id auth + // https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + const privateKey = await generateKeyPair('Ed25519') + const peerId = peerIdFromPrivateKey(privateKey) + + const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${peerId}`) + + await expect(client.services.pingHTTP.ping(httpAddr)).to.eventually.be.rejected + .with.property('name', 'InvalidPeerIdError') + }) + }) +}) + +const WS_SERVERS = [{ + name: 'ws', + address: multiaddr(process.env.WS_WSS_MULTIADDR) +}, { + name: '@fastify/websocket', + address: multiaddr(process.env.WS_FASTIFY_MULTIADDR) +}] + +describe('ping - libp2p over WebSockets', () => { + let client: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> + + beforeEach(async () => { + client = await createLibp2p({ + services: { + http: http(), + pingHTTP: pingHTTP() + } + }) + }) + + afterEach(async () => { + await stop(client) + }) + + WS_SERVERS.forEach(test => { + it(`should perform ping with the HTTP address of a ${test.name} server`, async () => { + const httpAddr = multiaddr(test.address) + + await expect(client.services.pingHTTP.ping(httpAddr, { + webSocket: true + })).to.eventually.be.a('number') + }) + + it(`should perform ping with a HTTP address with a peer id of a ${test.name} server`, async () => { + const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${process.env.HTTP_PEER_ID}`) + + await expect(client.services.pingHTTP.ping(httpAddr, { + webSocket: true + })).to.eventually.be.a('number') + }) + + it.skip(`should reject when performing ping with a HTTP address with the wrong peer id of a ${test.name} server`, async () => { + // TODO: detect PeerID in HTTP multiaddr and apply peer id auth + // https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + const privateKey = await generateKeyPair('Ed25519') + const peerId = peerIdFromPrivateKey(privateKey) + + const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${peerId}`) + + await expect(client.services.pingHTTP.ping(httpAddr, { + webSocket: true + })).to.eventually.be.rejected + .with.property('name', 'InvalidPeerIdError') + }) + }) +}) + +const LIBP2P_WS_SERVERS = [{ + name: 'ws/js', + address: multiaddr(process.env.LIBP2P_JS_WSS_MULTIADDR) +}, { + name: 'ws/node:http', + address: multiaddr(process.env.LIBP2P_NODE_WSS_MULTIADDR) +}, { + name: '@fastify/websocket/js', + address: multiaddr(process.env.LIBP2P_JS_FASTIFY_WS_MULTIADDR) +}, { + name: '@fastify/websocket/node:http', + address: multiaddr(process.env.LIBP2P_NODE_FASTIFY_WS_MULTIADDR) +}] + +describe('ping - WebSockets over libp2p', () => { + let client: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> + + beforeEach(async () => { + client = await createLibp2p({ + transports: [ + webSockets() + ], + streamMuxers: [ + yamux() + ], + connectionEncrypters: [ + noise() + ], + services: { + http: http(), + pingHTTP: pingHTTP() + } + }) + }) + + afterEach(async () => { + await stop(client) + }) + + LIBP2P_WS_SERVERS.forEach(test => { + it(`should perform ping with the HTTP address of a ${test.name} server`, async () => { + const httpAddr = multiaddr(test.address) + + await expect(client.services.pingHTTP.ping(httpAddr, { + webSocket: true + })).to.eventually.be.a('number') + }) + }) +}) diff --git a/test/websocket/message.spec.ts b/test/websocket/message.spec.ts new file mode 100644 index 0000000..10ce3b7 --- /dev/null +++ b/test/websocket/message.spec.ts @@ -0,0 +1,113 @@ +import { expect } from 'aegir/chai' +import { Uint8ArrayList } from 'uint8arraylist' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { decodeMessage, encodeMessage } from '../../src/websocket/message.js' + +describe('websocket messages', () => { + it('should encode and decode a small message', () => { + const data = Uint8Array.from([0, 1, 2, 3, 4]) + const input = encodeMessage('BINARY', data, true) + + const output = decodeMessage(new Uint8ArrayList(input.subarray())) + expect(output).to.have.property('type', 'BINARY') + expect(output).to.have.property('data').that.equalBytes(data) + }) + + it('should encode and decode a medium message', () => { + const data = new Uint8Array(49_391).map((v, i) => i) + const input = encodeMessage('BINARY', data, true) + + const output = decodeMessage(new Uint8ArrayList(input.subarray())) + expect(output).to.have.property('type', 'BINARY') + expect(output).to.have.property('data').that.equalBytes(data) + }) + + it('should encode and decode a large message', () => { + const data = new Uint8Array(123_392_198).map((v, i) => i) + const input = encodeMessage('BINARY', data, true) + + const output = decodeMessage(new Uint8ArrayList(input.subarray())) + expect(output).to.have.property('type', 'BINARY') + expect(output).to.have.property('data').that.equalBytes(data) + }) + + describe('rfc6455 examples', () => { + it('A single-frame unmasked text message', () => { + const input = Uint8Array.from([ + 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f + ]) + const output = decodeMessage(new Uint8ArrayList(input)) + + expect(output).to.have.property('type', 'TEXT') + expect(output).to.have.property('data').that.equalBytes(uint8ArrayFromString('Hello')) + }) + + it('A single-frame masked text message', () => { + const input = Uint8Array.from([ + 0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58 + ]) + const output = decodeMessage(new Uint8ArrayList(input)) + + expect(output).to.have.property('type', 'TEXT') + expect(output).to.have.property('data').that.equalBytes(uint8ArrayFromString('Hello')) + }) + + it('A fragmented unmasked text message', () => { + const input1 = Uint8Array.from([ + 0x01, 0x03, 0x48, 0x65, 0x6c + ]) + const output1 = decodeMessage(new Uint8ArrayList(input1)) + + expect(output1).to.have.property('type', 'TEXT') + expect(output1).to.have.property('data').that.equalBytes(uint8ArrayFromString('Hel')) + + const input2 = Uint8Array.from([ + 0x80, 0x02, 0x6c, 0x6f + ]) + const output2 = decodeMessage(new Uint8ArrayList(input2)) + + expect(output2).to.have.property('type', 'CONTINUATION') + expect(output2).to.have.property('data').that.equalBytes(uint8ArrayFromString('lo')) + }) + + it('Unmasked Ping request and masked Ping response', () => { + const input1 = Uint8Array.from([ + 0x89, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f + ]) + const output1 = decodeMessage(new Uint8ArrayList(input1)) + + expect(output1).to.have.property('type', 'PING') + expect(output1).to.have.property('data').that.equalBytes(uint8ArrayFromString('Hello')) + + const input2 = Uint8Array.from([ + 0x8a, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58 + ]) + const output2 = decodeMessage(new Uint8ArrayList(input2)) + + expect(output2).to.have.property('type', 'PONG') + expect(output2).to.have.property('data').that.equalBytes(uint8ArrayFromString('Hello')) + }) + + it('256 bytes binary message in a single unmasked frame', () => { + const data = new Uint8Array(256).map(((v, i) => i)) + const input = Uint8Array.from([ + 0x82, 0x7E, 0x01, 0x00 + ]) + const output = decodeMessage(new Uint8ArrayList(input, data)) + + expect(output).to.have.property('type', 'BINARY') + expect(output).to.have.property('data').that.equalBytes(data) + }) + + it.skip('64KiB binary message in a single unmasked frame', () => { + const data = new Uint8Array(Math.pow(2, 16)).map(((v, i) => i)) + const input = Uint8Array.from([ + 0x82, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 + ]) + const output = decodeMessage(new Uint8ArrayList(input, data)) + + expect(output).to.have.property('type', 'BINARY') + expect(output).to.have.property('data').that.equalBytes(data) + }) + }) +}) diff --git a/test/websockets.spec.ts b/test/websockets.spec.ts new file mode 100644 index 0000000..a573886 --- /dev/null +++ b/test/websockets.spec.ts @@ -0,0 +1,155 @@ +import { stop } from '@libp2p/interface' +import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { createServer } from '../src/http/index.js' +import { nodeServer } from '../src/servers/node.js' +import { createWebSocketServer } from './fixtures/create-websocket-server.js' +import { getClient, getListener } from './fixtures/get-libp2p.js' +import type { HTTP } from '../src/index.js' +import type { Libp2p } from 'libp2p' + +interface Test { + name: string + startServer(): Promise + stopServer(): Promise +} + +let listener: Libp2p<{ http: HTTP }> + +const LIBP2P_SERVERS: Test[] = [{ + name: 'in-process server', + startServer: async () => { + const server = createWebSocketServer(createServer()) + + listener = await getListener(nodeServer(server)) + return listener.getMultiaddrs()[0] + }, + stopServer: async () => { + await stop(listener) + } +}, { + name: 'ws/js', + startServer: async () => { + return multiaddr(process.env.LIBP2P_JS_WSS_MULTIADDR ?? '') + }, + stopServer: async () => { + + } +}, { + name: 'ws/node:http', + startServer: async () => { + return multiaddr(process.env.LIBP2P_NODE_WSS_MULTIADDR ?? '') + }, + stopServer: async () => { + + } +}, { + name: '@fastify/websocket/js', + startServer: async () => { + return multiaddr(process.env.LIBP2P_JS_FASTIFY_WS_MULTIADDR ?? '') + }, + stopServer: async () => { + + } +}, { + name: '@fastify/websocket/node:http', + startServer: async () => { + return multiaddr(process.env.LIBP2P_NODE_FASTIFY_WS_MULTIADDR ?? '') + }, + stopServer: async () => { + + } +}] + +for (const test of LIBP2P_SERVERS) { + describe(`WebSockets over libp2p - ${test.name}`, () => { + let client: Libp2p<{ http: HTTP }> + let address: Multiaddr + + beforeEach(async () => { + client = await getClient() + address = await test.startServer() + }) + + afterEach(async () => { + await stop(client) + await test.stopServer() + }) + + it('should make an WebSocket request to echo', (cb) => { + const message = 'This should be echoed' + const socket = client.services.http.connect(address.encapsulate('/http-path/echo'), [], { + headers: { + host: 'example.com' + } + }) + socket.addEventListener('error', (evt: any) => { + cb(evt.error) + }) + socket.addEventListener('message', (evt) => { + expect(evt.data).to.equalBytes(uint8ArrayFromString(message)) + cb() + }) + socket.addEventListener('open', () => { + socket.send(message) + }) + }) + }) +} + +const HTTP_SERVERS: Test[] = [{ + name: 'ws', + startServer: async () => { + return multiaddr(process.env.WS_WSS_MULTIADDR ?? '') + }, + stopServer: async () => { + + } +}, { + name: '@fastify/websocket', + startServer: async () => { + return multiaddr(process.env.WS_FASTIFY_MULTIADDR ?? '') + }, + stopServer: async () => { + + } +}] + +for (const test of HTTP_SERVERS) { + describe(`libp2p over WebSockets - ${test.name}`, () => { + let client: Libp2p<{ http: HTTP }> + let address: Multiaddr + let socket: WebSocket + + beforeEach(async () => { + client = await getClient() + address = await test.startServer() + }) + + afterEach(async () => { + socket?.close() + await stop(client) + await test.stopServer() + }) + + it('should make an WebSocket request to echo', (cb) => { + const message = 'This should be echoed' + socket = client.services.http.connect(address.encapsulate('/http-path/echo'), [], { + headers: { + host: 'example.com' + } + }) + socket.addEventListener('error', (evt: any) => { + cb(evt.error) + }) + socket.addEventListener('message', (evt) => { + expect(new Uint8Array(evt.data)).to.equalBytes(uint8ArrayFromString(message)) + cb() + }) + socket.addEventListener('open', () => { + socket.send(message) + }) + }) + }) +} From 174979cc69042031800dca2445345e38c3f660a8 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Fri, 4 Apr 2025 07:45:22 +0200 Subject: [PATCH 02/22] chore: simplify registrar --- .aegir.js | 10 +- README.md | 321 ++++++++++++++++++ src/auth/client.ts | 3 + src/constants.ts | 2 + src/http.browser.ts | 247 +++----------- src/index.ts | 85 +++-- src/ping/index.ts | 3 +- src/ping/ping.ts | 21 +- src/registrar.ts | 249 +++++++++----- src/utils.ts | 41 ++- src/websocket-handler.ts | 67 ++++ src/websocket/utils.ts | 42 ++- src/websocket/websocket.ts | 72 +++- src/well-known-handler.ts | 52 +-- test/auth.spec.ts | 4 - test/fixtures/create-fastify-websocket.ts | 8 +- test/fixtures/create-websocket-server.ts | 8 +- test/fixtures/create-wss.ts | 8 +- test/fixtures/get-libp2p-over-http-handler.ts | 57 ++-- 19 files changed, 872 insertions(+), 428 deletions(-) create mode 100644 src/websocket-handler.ts diff --git a/.aegir.js b/.aegir.js index 1640c72..cfd5ccc 100644 --- a/.aegir.js +++ b/.aegir.js @@ -63,13 +63,13 @@ export default { // --- libp2p-over-http const libp2pOverHttpHandler = await getLibp2pOverHttpHandler() - const express = createExpress(http.createServer(), libp2pOverHttpHandler.http) - const nodeHttp = createHttp(http.createServer(), libp2pOverHttpHandler.http) - const fastify = await createFastifyHTTP(http.createServer(), libp2pOverHttpHandler.http) + const express = createExpress(http.createServer(), libp2pOverHttpHandler.handler) + const nodeHttp = createHttp(http.createServer(), libp2pOverHttpHandler.handler) + const fastify = await createFastifyHTTP(http.createServer(), libp2pOverHttpHandler.handler) // --- libp2p-over-ws - const wss = createWss(http.createServer(), libp2pOverHttpHandler.http, libp2pOverHttpHandler.ws) - const fastifyWs = await createFastifyWebSocket(http.createServer(), libp2pOverHttpHandler.http, libp2pOverHttpHandler.ws) + const wss = createWss(http.createServer(), libp2pOverHttpHandler.handler) + const fastifyWs = await createFastifyWebSocket(http.createServer(), libp2pOverHttpHandler.handler) return { // http-over-libp2p diff --git a/README.md b/README.md index 21c6d89..48e4caa 100644 --- a/README.md +++ b/README.md @@ -782,6 +782,327 @@ const listener = await createLibp2p({ ## Example - ws WebSocket server +```ts +import { createLibp2p } from 'libp2p' +import { httpServer } from '@libp2p/http' +import { createServer } from 'node:http' +import { WebSocketServer } from 'ws' + +const wss = new WebSocketServer({ noServer: true }) +wss.on('connection', (ws) => { + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.on('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Clients + +You can use the built-in `.fetch` and `.connect` methods to make HTTP or +WebSocket requests respectively, or you can create a Node.js `http.Agent` for +use with the `node:http`, or a `Dispatcher` for use with `undici`. + +## Example - Using fetch to make a HTTP request + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import { multiaddr } from '@multiformats/multiaddr' + +const client = await createLibp2p({ + // ...other options + services: { + http: http() + } +}) + +const peerId = peerIdFromString('12DKoo') +const ma = multiaddr(`/p2p/${peerId}/http`) +const response = await client.services.httpClient.fetch(ma, { + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +## Example - Using connect to create a WebSocket + +This example works in all JavaScript environments, Node.js and browsers too! + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') +const webSocket = await client.services.httpClient.connect(peerId, url, { + signal: AbortSignal.timeout(10_000) +}) + +webSocket.addEventListener('message', (evt) => { + console.info(response.data) + // +}) +``` + +## Example - Using a http.Agent to make a request with node:http + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import * as http from 'node:http' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const agent = client.services.httpClient.agent(peerId) + +const req = http.request({ host: 'example.com', agent }, (res) => { + let result = '' + + res.setEncoding('utf8') + res.on('data', (chunk) => { + result += chunk + }) + res.on('end', () => { + console.info(result) + // Hello world! + }) +}) + +req.end() +``` + +## Example - Using a Dispatcher to make a request with undici + +This example only works in Node.js-compatible environments. + +```ts +import { createLibp2p } from 'libp2p' +import { httpClient } from '@libp2p/http' +import { peerIdFromString } from '@libp2p/peer-id' +import { fetch } from 'undici' + +const client = await createLibp2p({ + // ...other options + services: { + httpClient: httpClient() + } +}) + +const peerId = peerIdFromString('12DKoo') +const url = new URL('http://example.com') + +const dispatcher = client.services.httpClient.dispatcher(peerId) +const response = await fetch(url, { + dispatcher, + signal: AbortSignal.timeout(10_000) +}) + +console.info('Response:', response.status) +// Response: 200 + +console.info(await response.text()) +// Hello world! +``` + +# Browsers + +Making requests to servers is all good and well, but what if you could also +run a web or WebSocket server in a browser? + +## Example - A HTTP server running in a browser + +Once configured you can make requests to this server in the same was as the +fetch example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer } from '@libp2p/http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +## Example - A WebSocket server running in a browser + +Once configured you can make requests to this server in the same was as the +WebSocket example near the top of this README. + +```ts +import { createLibp2p } from 'libp2p' +import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' + +const wss = createWebSocketServer() +wss.addEventListener('connection', (evt) => { + const ws = evt.webSocket + + ws.on('message', (data) => { + ws.send(data) + }) +}) + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +server.addListener('upgrade', (request, socket, head) => { + wss.handleUpgrade(request, socket, head, (ws) => { + wss.emit('connection', ws, request) + }) +}) + +const listener = await createLibp2p({ + // ...other options + services: { + httpServer: httpServer({ server }) + } +}) +``` + +# Servers + +You can create HTTP and WebSocket servers using the framework of your choice, +as long as it accepts a Node.js `http.Server` instance. + +## Example - Node HTTP server + +```ts +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +const server = createServer((req, res) => { + req.end('Hello world!') +}) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Express server + +```ts +import express from 'express' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +// create an express app +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +const server = createServer(app) + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - Fastify server + +```ts +import { fastify } from 'fastify' +import { createLibp2p } from 'libp2p' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http/servers/node' +import { createServer } from 'node:http' + +let server + +// create a fastify app +const app = fastify({ + serverFactory: (handler, opts) => { + server = createServer((req, res) => { + handler(req, res) + }) + + return server + } + }) +app.get('/', async (req, res) => { + await res.send('Hello World!') +}) +await app.ready() + +if (server == null) { + throw new Error('Server not created') + } + +const listener = await createLibp2p({ + // ...other options + services: { + http: http({ + server: nodeServer(server) + }) + } +}) +``` + +## Example - ws WebSocket server + ```ts import { createLibp2p } from 'libp2p' import { httpServer } from '@ipshipyard/libp2p-http' diff --git a/src/auth/client.ts b/src/auth/client.ts index cf51567..2e72dd9 100644 --- a/src/auth/client.ts +++ b/src/auth/client.ts @@ -86,13 +86,16 @@ export class ClientAuth { public bearerAuthHeaderWithPeer (hostname: string): { 'authorization': string, peer: PeerId, agent: CookieAgent, jar: CookieJar } | undefined { const token = this.tokens.get(hostname) + if (token == null) { return undefined } + if (Date.now() - token.creationTime.getTime() > this.tokenTTL) { this.tokens.delete(hostname) return undefined } + return { authorization: `${PeerIDAuthScheme} bearer="${token.bearer}"`, peer: token.peer, diff --git a/src/constants.ts b/src/constants.ts index f3949f7..9a79cb9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,2 +1,4 @@ export const PROTOCOL = '/http/1.1' export const WELL_KNOWN_PROTOCOLS = '/.well-known/libp2p/protocols' +export const DEFAULT_HOST = 'example.com' +export const WEBSOCKET_HANDLER = Symbol.for('@libp2p/http/websocket-handler') diff --git a/src/http.browser.ts b/src/http.browser.ts index e217e41..a5c47f0 100644 --- a/src/http.browser.ts +++ b/src/http.browser.ts @@ -1,23 +1,19 @@ -import { HTTPParser } from '@achingbrain/http-parser-js' import { UnsupportedOperationError, serviceCapabilities } from '@libp2p/interface' import { fromStringTuples } from '@multiformats/multiaddr' -import { queuelessPushable } from 'it-queueless-pushable' -import { Uint8ArrayList } from 'uint8arraylist' import { PROTOCOL, WELL_KNOWN_PROTOCOLS } from './constants.js' import { fetch } from './fetch/index.js' import { HTTPRegistrar } from './registrar.js' -import { NOT_FOUND_RESPONSE, responseToStream, streamToRequest, toMultiaddrs, toResource } from './utils.js' -import { streamToWebSocket } from './websocket/utils.js' +import { getHost, toMultiaddrs, toResource } from './utils.js' import { WebSocket as WebSocketClass } from './websocket/websocket.js' -import type { Endpoint, HTTPInit, HTTP as HTTPInterface, WebSocketInit, HeaderInfo, HTTPRequestHandler, WebSocketHandler } from './index.js' -import type { ProtocolMap } from './well-known-handler.js' -import type { ComponentLogger, IncomingStreamData, Logger, PeerId, Startable, Stream } from '@libp2p/interface' +import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, HTTPRequestHandler, ProtocolMap, RequestHandlerOptions } from './index.js' +import type { ComponentLogger, Logger, PeerId, PrivateKey, Startable } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' const HTTP_PATH_CODEC = 0x01e1 export interface HTTPComponents { + privateKey: PrivateKey registrar: Registrar connectionManager: ConnectionManager logger: ComponentLogger @@ -26,15 +22,13 @@ export interface HTTPComponents { export class HTTP implements HTTPInterface, Startable { private readonly log: Logger protected readonly components: HTTPComponents - private readonly endpoint?: Endpoint + private readonly httpRegistrar: HTTPRegistrar constructor (components: HTTPComponents, init: HTTPInit = {}) { this.components = components this.log = components.logger.forComponent('libp2p:http') - this.httpRegistrar = new HTTPRegistrar(components) - this.endpoint = init.server - this.onStream = this.onStream.bind(this) + this.httpRegistrar = new HTTPRegistrar(components, init) } readonly [Symbol.toStringTag] = '@libp2p/http' @@ -44,117 +38,11 @@ export class HTTP implements HTTPInterface, Startable { ] async start (): Promise { - await this.components.registrar.handle(PROTOCOL, (data) => { - this.onStream(data) - .catch(err => { - this.log.error('could not handle incoming stream - %e', err) - }) - }) + await this.httpRegistrar.start() } async stop (): Promise { - await this.components.registrar.unhandle(PROTOCOL) - } - - private async onStream ({ stream, connection }: IncomingStreamData): Promise { - const info = await readHeaders(stream) - const isWebSocketRequest = info.headers.get('upgrade') === 'websocket' - - if (isWebSocketRequest && this.canHandleWebSocket(info)) { - this.log('handling incoming request %s %s', info.method, info.url) - this.handleWebSocket(streamToWebSocket(info, stream)) - return - } - - if (!isWebSocketRequest && this.canHandleHTTP(info)) { - this.log('handling incoming request %s %s', info.method, info.url) - const res = await this.handleHTTP(streamToRequest(info, stream)) - await responseToStream(res, stream) - await stream.close() - return - } - - // pass request to endpoint if available - if (this.endpoint == null) { - this.log('cannot handle incoming request %s %s and no endpoint configured', info.method, info.url) - await stream.sink([NOT_FOUND_RESPONSE]) - return - } - - this.log('passing incoming request %s %s to endpoint', info.method, info.url) - this.endpoint.inject(info, stream, connection) - .catch(err => { - this.log.error('error injecting request to endpoint - %e', err) - stream.abort(err) - }) - } - - canHandleHTTP (req: { url?: string }): boolean { - if (req.url == null) { - return false - } - - if (req.url === WELL_KNOWN_PROTOCOLS) { - return true - } - - // try handler registered with registrar - if (this.httpRegistrar.canHandleHTTP(req)) { - return true - } - - return false - } - - canHandleWebSocket (req: { url?: string }): boolean { - if (req.url == null) { - return false - } - - if (req.url === WELL_KNOWN_PROTOCOLS) { - return true - } - - // try handler registered with registrar - if (this.httpRegistrar.canHandleWebSocket(req)) { - return true - } - - return false - } - - /** - * Handle an incoming HTTP request - */ - async handleHTTP (req: Request): Promise { - const url = new URL(req.url) - - // serve protocol map - if (url.pathname === WELL_KNOWN_PROTOCOLS) { - const map = JSON.stringify(this.getProtocolMap()) - return new Response(map, { - headers: { - 'Content-Type': 'application/json', - 'Content-Length': `${map.length}` - } - }) - } - - // pass request to handler - return this.httpRegistrar.handleHTTP(req) - } - - handleWebSocket (ws: WebSocket): void { - // serve protocol map - if (ws.url === WELL_KNOWN_PROTOCOLS) { - const map = JSON.stringify(this.getProtocolMap()) - ws.send(map) - ws.close() - return - } - - // pass request to handler - this.httpRegistrar.handleWebSocket(ws) + await this.httpRegistrar.stop() } agent (...args: any[]): any { @@ -166,7 +54,7 @@ export class HTTP implements HTTPInterface, Startable { } connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init?: WebSocketInit): globalThis.WebSocket { - let url = toResource(resource) + const url = toResource(resource) if (url instanceof URL) { const socket = new globalThis.WebSocket(url, protocols) @@ -176,20 +64,9 @@ export class HTTP implements HTTPInterface, Startable { } // strip http-path tuple but record the value if set - let httpPath = '/' - url = url.map(ma => { - return fromStringTuples( - ma.stringTuples().filter(t => { - if (t[0] === HTTP_PATH_CODEC && t[1] != null) { - httpPath = `/${t[1]}` - } - - return t[0] !== HTTP_PATH_CODEC - }) - ) - }) + const { addresses, httpPath } = stripHTTPPath(url) - return new WebSocketClass(url, new URL(`http://example.com${decodeURIComponent(httpPath)}`), this.components.connectionManager, { + return new WebSocketClass(addresses, new URL(`http://${getHost(init?.headers)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, { ...init, protocols, isClient: true @@ -197,34 +74,23 @@ export class HTTP implements HTTPInterface, Startable { } async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: RequestInit = {}): Promise { - let url = toResource(resource) + const url = toResource(resource) if (url instanceof URL) { return globalThis.fetch(url, init) } // strip http-path tuple but record the value if set - let httpPath = '/' - url = url.map(ma => { - return fromStringTuples( - ma.stringTuples().filter(t => { - if (t[0] === HTTP_PATH_CODEC && t[1] != null) { - httpPath = `/${t[1]}` - } - - return t[0] !== HTTP_PATH_CODEC - }) - ) - }) + const { addresses, httpPath } = stripHTTPPath(url) - const connection = await this.components.connectionManager.openConnection(url, { + const connection = await this.components.connectionManager.openConnection(addresses, { signal: init.signal ?? undefined }) const stream = await connection.newStream(PROTOCOL, { signal: init.signal ?? undefined }) - return fetch(stream, new URL(`http://example.com${decodeURIComponent(httpPath)}`), { + return fetch(stream, new URL(`http://${getHost(init?.headers)}${decodeURIComponent(httpPath)}`), { ...init, logger: this.components.logger }) @@ -256,20 +122,24 @@ export class HTTP implements HTTPInterface, Startable { return peerMeta[protocol].path } - handleHTTPProtocol (protocol: string, handler: HTTPRequestHandler, path?: string): void { - this.httpRegistrar.handleHTTPProtocol(protocol, handler, path) + canHandle (req: { url?: string }): boolean { + return this.httpRegistrar.canHandle(req) + } + + async onRequest (req: Request): Promise { + return this.httpRegistrar.onRequest(req) } - handleWebSocketProtocol (protocol: string, handler: WebSocketHandler, path?: string): void { - this.httpRegistrar.handleWebSocketProtocol(protocol, handler, path) + onWebSocket (ws: WebSocket): void { + this.httpRegistrar.onWebSocket(ws) } - unhandleHTTPProtocol (protocol: string): void { - this.httpRegistrar.unhandleHTTPProtocol(protocol) + handle (protocol: string, handler: HTTPRequestHandler, options?: RequestHandlerOptions): void { + this.httpRegistrar.handle(protocol, handler, options) } - unhandleWebSocketProtocol (protocol: string): void { - this.httpRegistrar.unhandleWebSocketProtocol(protocol) + unhandle (protocol: string): void { + this.httpRegistrar.unhandle(protocol) } getProtocolMap (): ProtocolMap { @@ -277,56 +147,23 @@ export class HTTP implements HTTPInterface, Startable { } } -/** - * Reads HTTP headers from an incoming stream - */ -async function readHeaders (stream: Stream): Promise { - return new Promise((resolve, reject) => { - const parser = new HTTPParser('REQUEST') - const source = queuelessPushable() - const earlyData = new Uint8ArrayList() - let headersComplete = false - - parser[HTTPParser.kOnHeadersComplete] = (info) => { - headersComplete = true - const headers = new Headers() - - // set incoming headers - for (let i = 0; i < info.headers.length; i += 2) { - headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) - } - - resolve({ - ...info, - headers, - raw: earlyData, - method: HTTPParser.methods[info.method] - }) - } - - // replace source with request body - const streamSource = stream.source - stream.source = source - - Promise.resolve().then(async () => { - for await (const chunk of streamSource) { - // only use the message parser until the headers have been read - if (!headersComplete) { - earlyData.append(chunk) - parser.execute(chunk.subarray()) - } else { - await source.push(new Uint8ArrayList(chunk)) +function stripHTTPPath (addresses: Multiaddr[]): { httpPath: string, addresses: Multiaddr[] } { + // strip http-path tuple but record the value if set + let httpPath = '/' + addresses = addresses.map(ma => { + return fromStringTuples( + ma.stringTuples().filter(t => { + if (t[0] === HTTP_PATH_CODEC && t[1] != null) { + httpPath = `/${t[1]}` } - } - await source.end() - }) - .catch((err: Error) => { - stream.abort(err) - reject(err) - }) - .finally(() => { - parser.finish() + return t[0] !== HTTP_PATH_CODEC }) + ) }) + + return { + httpPath, + addresses + } } diff --git a/src/index.ts b/src/index.ts index 7e58160..3239279 100644 --- a/src/index.ts +++ b/src/index.ts @@ -346,10 +346,9 @@ import { HTTP as HTTPClass } from './http.js' import type { HTTPComponents } from './http.js' -import type { ProtocolMap } from './well-known-handler.js' import type { AbortOptions, Connection, PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' -import type { Agent, AgentOptions } from 'node:http' +import type { Agent, AgentOptions, IncomingMessage } from 'node:http' import type { Uint8ArrayList } from 'uint8arraylist' import type { Dispatcher, Agent as UnidiciAgent } from 'undici' @@ -363,12 +362,34 @@ export interface WebSocketInit extends AbortOptions { */ maxMessageSize?: number + /** + * If true, perform PeerId auth for the remote server before making the + * request. + * + * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + * + * @default false + */ + authenticate?: boolean + /** * Headers to send with the initial upgrade request */ headers?: HeadersInit } +export interface FetchInit extends RequestInit { + /** + * If true, perform PeerId auth for the remote server before making the + * request. + * + * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + * + * @default false + */ + authenticate?: boolean +} + export interface HTTPRequestHandler { (req: Request): Promise } @@ -377,6 +398,34 @@ export interface WebSocketHandler { (ws: WebSocket): void } +export type ProtocolID = string + +export interface ProtocolDescriptor { + path: string +} + +export type ProtocolMap = Record + +export interface RequestHandlerOptions { + /** + * If true, all requests to this handler will be authenticated using peer id + * auth before they are passed to the handler. + * + * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + * + * @default false + */ + authenticate?: boolean + + /** + * Specify a path to serve the protocol from. If omitted a random one will be + * generated which can be looked up from the protocol map using + * `getProtocolMap()` or by making a GET request to + * `/.well-known/libp2p/protocols`. + */ + path?: string +} + /** * HTTP service interface */ @@ -438,22 +487,12 @@ export interface HTTP { /** * Register a listener for a HTTP protocol */ - handleHTTPProtocol (protocol: string, handler: HTTPRequestHandler, path?: string): void - - /** - * Register a listener for a WebSocket protocol - */ - handleWebSocketProtocol (protocol: string, handler: WebSocketHandler, path?: string): void + handle (protocol: string, handler: HTTPRequestHandler, options?: RequestHandlerOptions): void /** * Remove a listener for a HTTP protocol */ - unhandleHTTPProtocol (protocol: string): void - - /** - * Remove a listener for a WebSocket protocol - */ - unhandleWebSocketProtocol (protocol: string): void + unhandle (protocol: string): void /** * Return the protocol->path mappings supported by this server @@ -462,25 +501,23 @@ export interface HTTP { /** * Returns true if there is a handler registered for the incoming Request or - * WebSocket - */ - canHandleHTTP (req: { url?: string }): boolean - - /** - * Returns true if there is a handler registered for the incoming Request or - * WebSocket + * WebSocket. + * + * Note - the `.url` property must be set on the WebSocket for this to work. + * Not all server-side WebSocket frameworks do this out of the box so the + * caller may have to add the property. */ - canHandleWebSocket (req: { url?: string }): boolean + canHandle (req: Request | IncomingMessage | WebSocket): boolean /** * Handle an incoming HTTP request */ - handleHTTP: HTTPRequestHandler + onRequest: HTTPRequestHandler /** * Handle an incoming WebSocket */ - handleWebSocket: WebSocketHandler + onWebSocket: WebSocketHandler } /** diff --git a/src/ping/index.ts b/src/ping/index.ts index 6891c3a..0a23ffa 100644 --- a/src/ping/index.ts +++ b/src/ping/index.ts @@ -1,13 +1,14 @@ // http-ping implementation import { PingHTTPService as PingHTTPServiceClass } from './ping.js' import type { HTTP } from '../index.js' -import type { AbortOptions, PeerId } from '@libp2p/interface' +import type { AbortOptions, ComponentLogger, PeerId } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' export const HTTP_PING_PROTOCOL = '/http-ping/1' export interface PingHTTPComponents { http: HTTP + logger: ComponentLogger } export interface PingOptions extends AbortOptions { diff --git a/src/ping/ping.ts b/src/ping/ping.ts index 811ba46..9468782 100644 --- a/src/ping/ping.ts +++ b/src/ping/ping.ts @@ -4,18 +4,21 @@ import { raceEvent } from 'race-event' import { raceSignal } from 'race-signal' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' import { toMultiaddrs } from '../utils.js' +import { webSocketHandler } from '../websocket-handler.js' import { HTTP_PING_PROTOCOL } from './index.js' import type { PingHTTPComponents, PingHTTP as PingHTTPInterface, PingOptions } from './index.js' -import type { PeerId, Startable } from '@libp2p/interface' +import type { Logger, PeerId, Startable } from '@libp2p/interface' import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr' const PING_SIZE = 32 export class PingHTTPService implements PingHTTPInterface, Startable { private readonly components: PingHTTPComponents + private readonly log: Logger constructor (components: PingHTTPComponents) { this.components = components + this.log = components.logger.forComponent('libp2p:http:ping') this.onHTTPRequest = this.onHTTPRequest.bind(this) this.onWebSocket = this.onWebSocket.bind(this) @@ -28,13 +31,13 @@ export class PingHTTPService implements PingHTTPInterface, Startable { ] start (): void { - this.components.http.handleHTTPProtocol(HTTP_PING_PROTOCOL, this.onHTTPRequest) - this.components.http.handleWebSocketProtocol(HTTP_PING_PROTOCOL, this.onWebSocket) + this.components.http.handle(HTTP_PING_PROTOCOL, webSocketHandler(this.onWebSocket, { + fallback: this.onHTTPRequest + })) } stop (): void { - this.components.http.unhandleHTTPProtocol(HTTP_PING_PROTOCOL) - this.components.http.unhandleWebSocketProtocol(HTTP_PING_PROTOCOL) + this.components.http.unhandle(HTTP_PING_PROTOCOL) } async onHTTPRequest (req: Request): Promise { @@ -81,6 +84,7 @@ export class PingHTTPService implements PingHTTPInterface, Startable { // fill buffer with random data crypto.getRandomValues(buf) + this.log('ping %o', peer) const output = await raceSignal(options.webSocket === true ? this.webSocketPing(dialTarget, buf, options) : this.httpPing(dialTarget, buf, options), options?.signal) const respBuf = new Uint8Array(output, 0, output.byteLength) @@ -110,21 +114,26 @@ export class PingHTTPService implements PingHTTPInterface, Startable { } async webSocketPing (dialTarget: Multiaddr[], buf: Uint8Array, options: AbortOptions): Promise { + this.log('opening websocket connection to %a', dialTarget) const socket = this.components.http.connect(dialTarget, [], options) if (socket.readyState !== WebSocket.OPEN) { await raceEvent(socket, 'open', options.signal) + this.log('websocket connection to %a open', dialTarget) } const p = new Promise((resolve, reject) => { socket.addEventListener('message', (evt) => { + this.log('received ping response from %a', dialTarget) resolve(evt.data) }) - socket.addEventListener('error', () => { + socket.addEventListener('error', (evt: any) => { + this.log('ping to %a errored - %e', dialTarget, evt.error ?? evt) reject(new Error('An error occurred')) }) }) + this.log('send ping message to %a', dialTarget) socket.send(buf) return p diff --git a/src/registrar.ts b/src/registrar.ts index cf3dded..12d9545 100644 --- a/src/registrar.ts +++ b/src/registrar.ts @@ -1,107 +1,151 @@ +import { HTTPParser } from '@achingbrain/http-parser-js' import { InvalidParametersError } from '@libp2p/interface' -import type { HTTPRequestHandler, WebSocketHandler } from './index.js' -import type { ComponentLogger, Logger } from '@libp2p/interface' +import { queuelessPushable } from 'it-queueless-pushable' +import { Uint8ArrayList } from 'uint8arraylist' +import { PROTOCOL, WEBSOCKET_HANDLER, WELL_KNOWN_PROTOCOLS } from './constants.js' +import { NOT_FOUND_RESPONSE, responseToStream, streamToRequest } from './utils.js' +import { wellKnownHandler } from './well-known-handler.js' +import type { Endpoint, HTTPRequestHandler, HeaderInfo, ProtocolMap, RequestHandlerOptions, WebSocketHandler } from './index.js' +import type { ComponentLogger, IncomingStreamData, Logger, Stream } from '@libp2p/interface' +import type { Registrar } from '@libp2p/interface-internal' -export type ProtocolID = string - -export interface ProtocolLocation { - path: string +export interface HTTPRegistrarComponents { + logger: ComponentLogger + registrar: Registrar } -export type ProtocolMap = Record +export interface HTTPRegistrarInit { + server?: Endpoint +} -export interface HTTPRegistrarComponents { - logger: ComponentLogger +interface ProtocolHandler { + protocol: string + path: string + handler: HTTPRequestHandler + authenticated?: boolean } export class HTTPRegistrar { private readonly log: Logger - private protocols: Array<{ protocol: string, path: string, http?: HTTPRequestHandler, ws?: WebSocketHandler }> + private readonly components: HTTPRegistrarComponents + private protocols: ProtocolHandler[] + private readonly endpoint?: Endpoint + private readonly wellKnownHandler: ProtocolHandler - constructor (components: HTTPRegistrarComponents) { + constructor (components: HTTPRegistrarComponents, init: HTTPRegistrarInit = {}) { + this.components = components this.log = components.logger.forComponent('libp2p:http:registrar') this.protocols = [] + this.onStream = this.onStream.bind(this) + this.endpoint = init.server + this.wellKnownHandler = { + protocol: '', + path: WELL_KNOWN_PROTOCOLS, + handler: wellKnownHandler(this) + } } - canHandleHTTP (req: { url?: string }): boolean { - return this.protocols.find(p => p.path === req.url && p.http != null) != null + async start (): Promise { + await this.components.registrar.handle(PROTOCOL, (data) => { + this.onStream(data) + .catch(err => { + this.log.error('could not handle incoming stream - %e', err) + }) + }) } - canHandleWebSocket (req: { url?: string }): boolean { - return this.protocols.find(p => p.path === req.url && p.ws != null) != null + async stop (): Promise { + await this.components.registrar.unhandle(PROTOCOL) } - async handleHTTP (request: Request): Promise { - const url = new URL(request.url) + private async onStream ({ stream, connection }: IncomingStreamData): Promise { + const info = await readHeaders(stream) - this.log('search for handler on path %s', url.pathname) + if (this.canHandle(info)) { + this.log('handling incoming request %s %s', info.method, info.url) + const res = await this.onRequest(streamToRequest(info, stream)) + await responseToStream(res, stream) + await stream.close() + return + } - const result = this.protocols.find(p => p.path === url.pathname) + // pass request to endpoint if available + if (this.endpoint == null) { + this.log('cannot handle incoming request %s %s and no endpoint configured', info.method, info.url) + await stream.sink([NOT_FOUND_RESPONSE]) + return + } - if (result?.http == null) { - return new Response(null, { - status: 404, - statusText: 'Not Found' + this.log('passing incoming request %s %s to endpoint', info.method, info.url) + this.endpoint.inject(info, stream, connection) + .catch(err => { + this.log.error('error injecting request to endpoint - %e', err) + stream.abort(err) }) - } + } - this.log('found for handler for HTTP protocol %s on path %s', result.protocol, url.pathname) + canHandle (req: { url?: string }): boolean { + if (req.url === WELL_KNOWN_PROTOCOLS || this.protocols.find(p => p.path === req.url) != null) { + this.log('can handle %s', req.url) + return true + } - return result.http(request) + this.log('cannot handle %s', req.url) + return false } - handleWebSocket (ws: WebSocket): void { - this.log('search for handler on path %s', ws.url) + async onRequest (request: Request): Promise { + const result = this.findHandler(request.url) - const result = this.protocols.find(p => p.path === ws.url) - - if (result?.ws == null) { - ws.close(404, 'Not Found') - return + if (result?.handler != null) { + return result.handler(request) } - this.log('found for handler for WebSocket protocol %s on path %s', result.protocol, ws.url) - - result.ws(ws) + return new Response(null, { + status: 404, + statusText: 'Not Found' + }) } - handleHTTPProtocol (protocol: string, handler: HTTPRequestHandler, path: string = crypto.randomUUID()): void { - for (const p of this.protocols) { - if (p.protocol === protocol) { - if (p.http != null) { - throw new InvalidParametersError(`HTTP protocol handler for ${protocol} already registered`) - } + onWebSocket (ws: WebSocket): void { + const result = this.findHandler(ws.url) + + if (result != null) { + // @ts-expect-error hidden field + const wsHandler: WebSocketHandler = result.handler[WEBSOCKET_HANDLER] - p.http = handler + if (wsHandler != null) { + wsHandler(ws) return } } - if (path === '' || !path.startsWith('/')) { - path = `/${path}` + ws.close(404, 'Not Found') + } + + private findHandler (url: string): ProtocolHandler | undefined { + const pathname = url.startsWith('/') ? url : new URL(url).pathname + + if (pathname === WELL_KNOWN_PROTOCOLS) { + return this.wellKnownHandler } - // add handler - this.protocols.push({ - protocol, - path, - http: handler - }) + this.log('search for handler on path %s', pathname) - // sort by path length desc so the most specific handler is invoked first - this.protocols.sort(({ path: a }, { path: b }) => b.length - a.length) + const handler = this.protocols.find(p => p.path === pathname) + + if (handler != null) { + this.log('found handler for HTTP protocol %s on path %s', handler.protocol, url) + } + + return handler } - handleWebSocketProtocol (protocol: string, handler: WebSocketHandler, path: string = crypto.randomUUID()): void { - for (const p of this.protocols) { - if (p.protocol === protocol) { - if (p.ws != null) { - throw new InvalidParametersError(`WebSocket protocol handler for ${protocol} already registered`) - } + handle (protocol: string, handler: HTTPRequestHandler, options: RequestHandlerOptions = {}): void { + let path = options.path ?? crypto.randomUUID() - p.ws = handler - return - } + if (this.protocols.find(p => p.protocol === protocol) != null) { + throw new InvalidParametersError(`HTTP protocol handler for ${protocol} already registered`) } if (path === '' || !path.startsWith('/')) { @@ -112,35 +156,16 @@ export class HTTPRegistrar { this.protocols.push({ protocol, path, - ws: handler + handler, + authenticated: options.authenticate }) // sort by path length desc so the most specific handler is invoked first this.protocols.sort(({ path: a }, { path: b }) => b.length - a.length) } - unhandleHTTPProtocol (protocol: string): void { - this.protocols = this.protocols.filter(p => { - if (p.protocol === protocol) { - delete p.http - - return p.ws != null - } - - return true - }) - } - - unhandleWebSocketProtocol (protocol: string): void { - this.protocols = this.protocols.filter(p => { - if (p.protocol === protocol) { - delete p.ws - - return p.http != null - } - - return true - }) + unhandle (protocol: string): void { + this.protocols = this.protocols.filter(p => p.protocol === protocol) } getProtocolMap (): ProtocolMap { @@ -155,3 +180,57 @@ export class HTTPRegistrar { return output } } + +/** + * Reads HTTP headers from an incoming stream + */ +async function readHeaders (stream: Stream): Promise { + return new Promise((resolve, reject) => { + const parser = new HTTPParser('REQUEST') + const source = queuelessPushable() + const earlyData = new Uint8ArrayList() + let headersComplete = false + + parser[HTTPParser.kOnHeadersComplete] = (info) => { + headersComplete = true + const headers = new Headers() + + // set incoming headers + for (let i = 0; i < info.headers.length; i += 2) { + headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) + } + + resolve({ + ...info, + headers, + raw: earlyData, + method: HTTPParser.methods[info.method] + }) + } + + // replace source with request body + const streamSource = stream.source + stream.source = source + + Promise.resolve().then(async () => { + for await (const chunk of streamSource) { + // only use the message parser until the headers have been read + if (!headersComplete) { + earlyData.append(chunk) + parser.execute(chunk.subarray()) + } else { + await source.push(new Uint8ArrayList(chunk)) + } + } + + await source.end() + }) + .catch((err: Error) => { + stream.abort(err) + reject(err) + }) + .finally(() => { + parser.finish() + }) + }) +} diff --git a/src/utils.ts b/src/utils.ts index 4258ae8..f85ad63 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,6 +5,7 @@ import { uriToMultiaddr } from '@multiformats/uri-to-multiaddr' import { queuelessPushable } from 'it-queueless-pushable' import itToBrowserReadableStream from 'it-to-browser-readablestream' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { DEFAULT_HOST } from './constants.js' import type { HeaderInfo } from './index.js' import type { PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -34,15 +35,23 @@ export function streamToRequest (info: HeaderInfo, stream: Stream): Request { headers: info.headers } - if (info.method !== 'GET' && info.method !== 'HEAD') { - init.body = itToBrowserReadableStream(takeBytes(stream.source, info.headers.get('content-length'))) + if (info.upgrade) { + init.method = 'UPGRADE' + } + + if (init.method !== 'GET' && init.method !== 'HEAD') { + let source: AsyncGenerator = stream.source + + if (!info.upgrade) { + source = takeBytes(stream.source, info.headers.get('content-length')) + } + + init.body = itToBrowserReadableStream(source) // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit init.duplex = 'half' } - const req = new Request(`http://${info.headers.get('host') ?? 'host'}${info.url}`, init) - - return req + return new Request(`http://${info.headers.get('host') ?? 'host'}${info.url}`, init) } export async function responseToStream (res: Response, stream: Stream): Promise { @@ -134,7 +143,7 @@ export function toMultiaddrs (peer: PeerId | Multiaddr | Multiaddr[], suffix?: s return mas } -function writeHeaders (headers: Headers): string[] { +export function writeHeaders (headers: Headers): string[] { const output = [] if (headers.get('Connection') == null) { @@ -236,3 +245,23 @@ export function toResource (resource: string | URL | Multiaddr | Multiaddr[]): U return resource } + +export function getHost (init?: HeadersInit): string { + if (init == null) { + return DEFAULT_HOST + } + + if (init instanceof Headers) { + return init.get('host') ?? DEFAULT_HOST + } + + let entries: Array<[string, string]> + + if (Array.isArray(init)) { + entries = init + } else { + entries = Object.entries(init) + } + + return entries.find(([key]) => key.toLowerCase() === 'host')?.[1] ?? DEFAULT_HOST +} diff --git a/src/websocket-handler.ts b/src/websocket-handler.ts new file mode 100644 index 0000000..949e71b --- /dev/null +++ b/src/websocket-handler.ts @@ -0,0 +1,67 @@ +import { WEBSOCKET_HANDLER } from './constants.js' +import { getServerUpgradeHeaders } from './websocket/utils.js' +import { RequestWebSocket } from './websocket/websocket.js' +import type { HTTPRequestHandler, WebSocketHandler } from './index.js' + +export interface WebSocketHandlerOptions { + /** + * If the request does not have a `Connection: upgrade` header, pass a + * fallback here to handle the request normally, otherwise the request + * will be rejected with a 400 error. + */ + fallback?: HTTPRequestHandler + + /** + * The maximum message size to be sent or received over the socket in bytes + * + * @default 10_485_760 + */ + maxMessageSize?: number +} + +/** + * Negotiate a connection upgrade to the WebSocket protocol and call the passed + * handler + */ +export function webSocketHandler (handler: WebSocketHandler, options?: WebSocketHandlerOptions): HTTPRequestHandler { + const fn = async (req: Request): Promise => { + // check upgrade has been requested + if (req.headers.get('connection') !== 'upgrade' && req.headers.get('upgrade') !== 'websocket') { + if (options?.fallback != null) { + return options.fallback(req) + } + + return new Response(null, { + status: 400, + statusText: 'Bad Request' + }) + } + + const transform = new TransformStream() + + try { + const res = { + status: 101, + statusText: 'Switching Protocols', + headers: await getServerUpgradeHeaders(req.headers), + body: transform.readable + } + + const ws = new RequestWebSocket(req, transform.writable, options) + handler(ws) + + // @ts-expect-error the Undici Response class requires statuses to be + // 200-500 so we can't use it, just return an object with the correct + // properties instead + return res + } catch { + return new Response(null, { + status: 400, + statusText: 'Bad Request' + }) + } + } + fn[WEBSOCKET_HANDLER] = handler + + return fn +} diff --git a/src/websocket/utils.ts b/src/websocket/utils.ts index d507553..a81ffbd 100644 --- a/src/websocket/utils.ts +++ b/src/websocket/utils.ts @@ -3,7 +3,7 @@ import { InvalidParametersError, ProtocolError } from '@libp2p/interface' import { base64pad } from 'multiformats/bases/base64' import { sha1 } from 'multiformats/hashes/sha1' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { BAD_REQUEST, toUint8Array } from '../utils.js' +import { BAD_REQUEST, toUint8Array, writeHeaders } from '../utils.js' import { StreamWebSocket } from './websocket.js' import type { HeaderInfo } from '../index.js' import type { AbortOptions, Stream } from '@libp2p/interface' @@ -127,19 +127,14 @@ export async function * performClientUpgrade (url: URL, protocols: string[] = [] yield req } -/** - * Implements the WebSocket handshake from the server's perspective - */ -export async function * performServerUpgrade (headers: Headers | Record): AsyncGenerator { +export async function getServerUpgradeHeaders (headers: Headers | Record): Promise { if (getHeader(headers, 'sec-websocket-version') !== '13') { - yield BAD_REQUEST throw new ProtocolError('Invalid version') } const secWebSocketKey = getHeader(headers, 'sec-websocket-key') if (secWebSocketKey == null) { - yield BAD_REQUEST throw new ProtocolError('Missing sec-websocket-key') } @@ -149,16 +144,31 @@ export async function * performServerUpgrade (headers: Headers | Record): AsyncGenerator { + try { + const responseHeaders = await getServerUpgradeHeaders(headers) + + const message = [ + 'HTTP/1.1 101 Switching Protocols', + ...writeHeaders(responseHeaders), + '', + '' + ] + + yield uint8ArrayFromString(message.join('\r\n')) + } catch { + yield BAD_REQUEST + } } export function streamToWebSocket (info: HeaderInfo, stream: Stream): WebSocket { diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts index 60e3d40..268bf3f 100644 --- a/src/websocket/websocket.ts +++ b/src/websocket/websocket.ts @@ -1,8 +1,9 @@ -import { TypedEventEmitter } from '@libp2p/interface' +import { InvalidParametersError, TypedEventEmitter } from '@libp2p/interface' import { isPromise } from '@libp2p/utils/is-promise' import { byteStream, type ByteStream } from 'it-byte-stream' import { Uint8ArrayList } from 'uint8arraylist' import { PROTOCOL } from '../constants.js' +import { getHost } from '../utils.js' import { ErrorEvent } from './events.js' import { encodeMessage, decodeMessage, CLOSE_MESSAGES } from './message.js' import { performClientUpgrade, performServerUpgrade, readResponse, toBytes } from './utils.js' @@ -333,6 +334,75 @@ export class StreamWebSocket extends AbstractWebSocket { } } +export class RequestWebSocket extends AbstractWebSocket { + private readonly writer: WritableStreamDefaultWriter + private readonly writable: WritableStream + + constructor (request: Request, writable: WritableStream, init?: WebSocketInit) { + super(new URL(`http://${getHost(request.headers)}${request.url}`), { + ...init, + isClient: false + }) + + if (request.body == null) { + throw new InvalidParametersError('Request body cannot be null') + } + + this.writable = writable + this.writer = writable.getWriter() + const reader = request.body.getReader() + + Promise.resolve() + .then(async () => { + this.readyState = this.OPEN + this.dispatchEvent(new Event('open')) + + while (true) { + const { value, done } = await reader.read() + + if (value != null) { + this._push(value) + } + + if (done) { + this._remoteClosed() + break + } + } + }) + .catch(err => { + this._errored(err) + }) + } + + _write (buf: Uint8ArrayList, cb: (err?: Error | null) => void): void { + this.writer?.write(buf) + .then(() => { + cb() + }, err => { + cb(err) + }) + } + + _close (err: Error, cb: () => void): void { + if (err != null) { + this.writable.abort(err) + .then(() => { + cb() + }, () => { + cb() + }) + } else { + this.writable.close() + .then(() => { + cb() + }, () => { + cb() + }) + } + } +} + export class WebSocket extends AbstractWebSocket { private bytes?: ByteStream diff --git a/src/well-known-handler.ts b/src/well-known-handler.ts index a7d09ce..ca3cdfb 100644 --- a/src/well-known-handler.ts +++ b/src/well-known-handler.ts @@ -1,37 +1,21 @@ -export type ProtocolID = string +import { webSocketHandler } from './websocket-handler.js' +import type { HTTPRequestHandler } from './index.js' +import type { HTTPRegistrar } from './registrar.js' -export interface ProtocolLocation { - path: string -} - -export type ProtocolMap = Record -export class WellKnownHandler { - private readonly protocols: ProtocolMap = {} - public async handleRequest (request: Request): Promise { - return new Response(JSON.stringify(this.protocols), { - headers: { - 'Content-Type': 'application/json' - } - }) - } - - /** - * Register a protocol with a path and remember it so we can tell our peers - * about it via a request to "/.well-known/libp2p/protocols" - */ - public registerProtocol (protocol: string, path: string): void { - if (path === '') { - path = '/' - } - - if (!path.startsWith('/')) { - path = `/${path}` - } - - if (this.protocols[protocol] != null) { - throw new Error(`Protocol ${protocol} already registered`) +export function wellKnownHandler (registrar: HTTPRegistrar): HTTPRequestHandler { + return webSocketHandler(ws => { + const map = JSON.stringify(registrar.getProtocolMap()) + ws.send(map) + ws.close() + }, { + fallback: async (req) => { + const map = JSON.stringify(registrar.getProtocolMap()) + return new Response(map, { + headers: { + 'Content-Type': 'application/json', + 'Content-Length': `${map.length}` + } + }) } - - this.protocols[protocol] = { path } - } + }) } diff --git a/test/auth.spec.ts b/test/auth.spec.ts index 7a5c5c2..78a5d6a 100644 --- a/test/auth.spec.ts +++ b/test/auth.spec.ts @@ -1,10 +1,6 @@ /* eslint-disable max-nested-callbacks */ import http from 'node:http' import { generateKeyPair } from '@libp2p/crypto/keys' -import './websockets.spec.js' -import './fetch.spec.js' -import './ping.spec.js' -import './websocket/message.spec.js' import { peerIdFromPrivateKey } from '@libp2p/peer-id' import { expect } from 'aegir/chai' import pDefer from 'p-defer' diff --git a/test/fixtures/create-fastify-websocket.ts b/test/fixtures/create-fastify-websocket.ts index 06efe5c..a70b043 100644 --- a/test/fixtures/create-fastify-websocket.ts +++ b/test/fixtures/create-fastify-websocket.ts @@ -1,10 +1,10 @@ import fastifyWebSocket from '@fastify/websocket' import { fastify } from 'fastify' import { toWebSocket } from './to-websocket.js' -import type { Libp2pOverHTTPHandler, Libp2pOverWSHandler } from './get-libp2p-over-http-handler.js' +import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' import type { Server } from 'node:http' -export async function createFastifyWebSocket (server: Server, httpHandler?: Libp2pOverHTTPHandler, wsHandler?: Libp2pOverWSHandler): Promise { +export async function createFastifyWebSocket (server: Server, handler?: Libp2pOverHTTPHandler): Promise { const app = fastify({ serverFactory: (app, opts) => { server.addListener('request', (req, res) => { @@ -13,7 +13,7 @@ export async function createFastifyWebSocket (server: Server, httpHandler?: Libp res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') res.setHeader('Access-Control-Allow-Headers', '*') - if (httpHandler?.(req, res) !== true) { + if (handler?.(req, res) !== true) { app(req, res) } }) @@ -29,7 +29,7 @@ export async function createFastifyWebSocket (server: Server, httpHandler?: Libp }) }) fastify.get('/*', { websocket: true }, (socket, req) => { - if (wsHandler?.(toWebSocket(socket, req)) === true) { + if (handler?.(toWebSocket(socket, req)) === true) { return } diff --git a/test/fixtures/create-websocket-server.ts b/test/fixtures/create-websocket-server.ts index 01b4eeb..86ff713 100644 --- a/test/fixtures/create-websocket-server.ts +++ b/test/fixtures/create-websocket-server.ts @@ -1,13 +1,13 @@ import { createWebSocketServer as createWss } from '../../src/websocket/index.js' -import type { Libp2pOverHTTPHandler, Libp2pOverWSHandler } from './get-libp2p-over-http-handler.js' +import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' import type { Server } from 'node:http' -export function createWebSocketServer (server: Server, httpHandler?: Libp2pOverHTTPHandler, wsHandler?: Libp2pOverWSHandler): Server { +export function createWebSocketServer (server: Server, handler?: Libp2pOverHTTPHandler): Server { const wss = createWss() wss.addEventListener('connection', (evt) => { const ws = evt.webSocket - if (wsHandler?.(ws) === true) { + if (handler?.(ws) === true) { return } @@ -27,7 +27,7 @@ export function createWebSocketServer (server: Server, httpHandler?: Libp2pOverH res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') res.setHeader('Access-Control-Allow-Headers', '*') - if (httpHandler?.(req, res) === true) { + if (handler?.(req, res) === true) { return } diff --git a/test/fixtures/create-wss.ts b/test/fixtures/create-wss.ts index f06ed23..c667b83 100644 --- a/test/fixtures/create-wss.ts +++ b/test/fixtures/create-wss.ts @@ -1,12 +1,12 @@ import { WebSocketServer } from 'ws' import { toWebSocket } from './to-websocket.js' -import type { Libp2pOverHTTPHandler, Libp2pOverWSHandler } from './get-libp2p-over-http-handler.js' +import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' import type { Server } from 'node:http' -export function createWss (server: Server, httpHandler?: Libp2pOverHTTPHandler, wsHandler?: Libp2pOverWSHandler): Server { +export function createWss (server: Server, handler?: Libp2pOverHTTPHandler): Server { const wss = new WebSocketServer({ noServer: true }) wss.on('connection', (ws, req) => { - if (wsHandler?.(toWebSocket(ws, req)) === true) { + if (handler?.(toWebSocket(ws, req)) === true) { return } @@ -26,7 +26,7 @@ export function createWss (server: Server, httpHandler?: Libp2pOverHTTPHandler, res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') res.setHeader('Access-Control-Allow-Headers', '*') - if (httpHandler?.(req, res) === true) { + if (handler?.(req, res) === true) { return } diff --git a/test/fixtures/get-libp2p-over-http-handler.ts b/test/fixtures/get-libp2p-over-http-handler.ts index 6a510f6..37cbd84 100644 --- a/test/fixtures/get-libp2p-over-http-handler.ts +++ b/test/fixtures/get-libp2p-over-http-handler.ts @@ -8,25 +8,22 @@ import type { IncomingMessage, ServerResponse } from 'node:http' export interface Libp2pOverHTTPHandler { /** - * Returns `true` if the libp2p HTTP service will handle this request (e.g. it - * is for protocol map published at the `/.well-known` location or there is a - * protocol handler registered for this path). + * Returns `true` if the libp2p HTTP service will handle this WebSocket (e.g. + * it is for protocol map published at the `/.well-known` location or there is + * a protocol handler registered for this path). */ - (req: IncomingMessage, res: ServerResponse): boolean -} + (ws: WebSocket): boolean -export interface Libp2pOverWSHandler { /** * Returns `true` if the libp2p HTTP service will handle this request (e.g. it * is for protocol map published at the `/.well-known` location or there is a * protocol handler registered for this path). */ - (ws: WebSocket): boolean + (req: IncomingMessage, res: ServerResponse): boolean } export interface Libp2pOverHttpHandlerResults { - http: Libp2pOverHTTPHandler - ws: Libp2pOverWSHandler + handler: Libp2pOverHTTPHandler libp2p: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> } @@ -41,26 +38,29 @@ export async function getLibp2pOverHttpHandler (): Promise { - if (libp2p.services.http.canHandleHTTP(req)) { - libp2p.services.http.handleHTTP(incomingMessageToRequest(req)) - .then(result => { - writeResponse(result, res) - }) - .catch(err => { - res.writeHead(500, err.toString()) - res.end() - }) - return true - } + const handler = (...args: any[]): boolean => { + if (args.length === 1) { + const ws: WebSocket = args[0] - return false - } + if (libp2p.services.http.canHandle(ws)) { + libp2p.services.http.onWebSocket(ws) + return true + } + } else if (args.length === 2) { + const req: IncomingMessage = args[0] + const res: ServerResponse = args[1] - const wsHandler = (ws: WebSocket): boolean => { - if (libp2p.services.http.canHandleWebSocket(ws)) { - libp2p.services.http.handleWebSocket(ws) - return true + if (libp2p.services.http.canHandle(req)) { + libp2p.services.http.onRequest(incomingMessageToRequest(req)) + .then(result => { + writeResponse(result, res) + }) + .catch(err => { + res.writeHead(500, err.toString()) + res.end() + }) + return true + } } return false @@ -68,7 +68,6 @@ export async function getLibp2pOverHttpHandler (): Promise Date: Tue, 8 Apr 2025 13:53:57 +0100 Subject: [PATCH 03/22] chore: support cookies --- package.json | 4 + src/constants.ts | 17 ++- src/cookies.ts | 128 +++++++++++++++++++ src/fetch/index.ts | 9 ++ src/fetch/read-response.ts | 6 +- src/fetch/response.ts | 15 +++ src/fetch/send-request.ts | 15 +-- src/http.browser.ts | 99 ++++++++------- src/http/server-response.ts | 20 ++- src/http/server.ts | 11 +- src/index.ts | 77 +++++++++--- src/peer-id-auth.ts | 177 +++++++++++++++++++++++++++ src/ping/ping.ts | 1 + src/registrar.ts | 1 + src/utils.ts | 152 ++++++++++++++++++++--- src/websocket-handler.ts | 1 + src/websocket/utils.ts | 31 +++-- src/websocket/websocket.ts | 29 ++--- src/well-known-handler.ts | 1 + test/cookies.spec.ts | 148 ++++++++++++++++++++++ test/fetch.spec.ts | 4 +- test/fixtures/create-express.ts | 11 ++ test/fixtures/create-fastify-http.ts | 15 +++ test/fixtures/create-http.ts | 15 +++ test/fixtures/get-server.ts | 26 ---- 25 files changed, 846 insertions(+), 167 deletions(-) create mode 100644 src/cookies.ts create mode 100644 src/fetch/response.ts create mode 100644 src/peer-id-auth.ts create mode 100644 test/cookies.spec.ts delete mode 100644 test/fixtures/get-server.ts diff --git a/package.json b/package.json index 4b69c55..159caf9 100644 --- a/package.json +++ b/package.json @@ -176,6 +176,7 @@ "@multiformats/multiaddr": "^12.3.0", "@multiformats/multiaddr-to-uri": "^11.0.0", "@multiformats/uri-to-multiaddr": "^9.0.1", + "cookie": "^1.0.2", "http-cookie-agent": "^6.0.7", "it-byte-stream": "^2.0.1", "it-queueless-pushable": "^2.0.0", @@ -193,13 +194,16 @@ "devDependencies": { "@chainsafe/libp2p-noise": "^16.1.0", "@chainsafe/libp2p-yamux": "^7.0.1", + "@fastify/cookie": "^11.0.2", "@fastify/websocket": "^11.0.2", "@libp2p/memory": "^1.1.4", "@libp2p/ping": "^2.0.27", "@libp2p/websockets": "^9.2.8", + "@types/cookie-parser": "^1.4.8", "@types/express": "^5.0.1", "@types/ws": "^8.18.0", "aegir": "^45.0.0", + "cookie-parser": "^1.4.7", "express": "^4.21.2", "fastify": "^5.2.2", "it-pair": "^2.0.6", diff --git a/src/constants.ts b/src/constants.ts index 9a79cb9..87257a1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,19 @@ export const PROTOCOL = '/http/1.1' export const WELL_KNOWN_PROTOCOLS = '/.well-known/libp2p/protocols' -export const DEFAULT_HOST = 'example.com' export const WEBSOCKET_HANDLER = Symbol.for('@libp2p/http/websocket-handler') +export const PEER_ID_AUTH_SCHEME = 'libp2p-PeerID' +export const HTTP_PEER_ID_AUTH_PROTO = '/http-peer-id-auth/1.0.0' +export const DEFAULT_AUTH_TOKEN_TTL = 60 * 60 * 1000 // 1 hour +export const HTTP_PATH_CODEC = 0x01e1 +export const HTTP_CODEC = 0x01e0 +export const DNS_CODEC = 0x35 +export const DNS4_CODEC = 0x36 +export const DNS6_CODEC = 0x37 +export const DNSADDR_CODEC = 0x38 +export const DNS_CODECS = [ + DNS_CODEC, + DNS4_CODEC, + DNS6_CODEC, + DNSADDR_CODEC +] +export const DEFAULT_COOKIE_EXPIRY_CHECK_INTERVAL = 60_000 diff --git a/src/cookies.ts b/src/cookies.ts new file mode 100644 index 0000000..7891703 --- /dev/null +++ b/src/cookies.ts @@ -0,0 +1,128 @@ +import cookie from 'cookie' +import { toURL } from './http.browser.js' +import { getHeaders } from './utils.js' +import type { FetchInit, RequestProcessor } from './index.js' +import type { ComponentLogger, Logger } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' + +interface CookiesComponents { + logger: ComponentLogger +} + +interface CookiesInit { + cookieExpiryCheckInterval?: number +} + +interface Cookie { + name: string + value: string + expires?: number + domain?: string + path?: string +} + +export class Cookies implements RequestProcessor { + private readonly log: Logger + private readonly cookies: Map + + constructor (components: CookiesComponents, init: CookiesInit = {}) { + this.log = components.logger.forComponent('libp2p:http:cookies') + this.cookies = new Map() + } + + async prepareRequest (resource: URL | Multiaddr[], init: FetchInit): Promise { + if (init.ignoreCookies === true) { + return + } + + const url = toURL(resource, init) + const cookies = (this.cookies.get(url.hostname) ?? []).filter(cookie => { + if (cookie.expires != null && cookie.expires < Date.now()) { + return false + } + + if (cookie.path != null && !url.pathname.startsWith(cookie.path)) { + return false + } + + return true + }) + .map(cookie => `${cookie.name}=${cookie.value}`) + .join('; ') + + if (cookies.length > 0) { + const headers = getHeaders(init) + headers.set('cookie', cookies) + } + } + + async processResponse (resource: URL | Multiaddr[], init: FetchInit, response: Response): Promise { + if (init.ignoreCookies === true) { + removeSetCookie(response) + + return + } + + const url = toURL(resource, init) + + for (const value of response.headers.getSetCookie()) { + const cookies = [ + ...(this.cookies.get(url.hostname) ?? []), + ...toCookies(cookie.parse(value)) + ] + + this.cookies.set(url.hostname, cookies) + } + + removeSetCookie(response) + } +} + +/** + * the fetch spec requires not exposing set-cookie to client code + */ +function removeSetCookie (response: Response): Response { + if (response.headers.has('set-cookie')) { + response.headers.delete('set-cookie') + } + + return response +} + +function toCookies (parsed: Record): Cookie[] { + const metadata: Omit = {} + const output: Cookie[] = [] + + Object.entries(parsed).forEach(([name, value]) => { + if (name.toLowerCase() === 'domain' && value != null) { + metadata.domain = value + } + + if (name.toLowerCase() === 'max-age' && value != null) { + metadata.expires = Date.now() + (parseInt(value, 10) * 1000) + } + + if (!COOKIE_FIELDS.includes(name.toLowerCase()) && value != null) { + output.push({ + name, + value + }) + } + }) + + return output.map(c => ({ + ...c, + ...metadata + })) +} + +const COOKIE_FIELDS = [ + 'domain', + 'expires', + 'httponly', + 'max-age', + 'partitioned', + 'path', + 'samesite', + 'secure' +] diff --git a/src/fetch/index.ts b/src/fetch/index.ts index 7113a8f..ab487df 100644 --- a/src/fetch/index.ts +++ b/src/fetch/index.ts @@ -5,10 +5,19 @@ import type { ComponentLogger, Logger, Stream } from '@libp2p/interface' export interface FetchInit extends RequestInit { logger: ComponentLogger + + /** + * The maximum number of bytes that will be parsed as headers, defaults to + * 80KB + * + * @default 81_920 + */ + maxHeaderSize?: number } export interface SendRequestInit extends RequestInit { log: Logger + maxHeaderSize?: number } export async function fetch (stream: Stream, resource: string | URL, init: FetchInit): Promise { diff --git a/src/fetch/read-response.ts b/src/fetch/read-response.ts index 173d9fe..9bdd1cf 100644 --- a/src/fetch/read-response.ts +++ b/src/fetch/read-response.ts @@ -1,4 +1,5 @@ import { HTTPParser } from '@achingbrain/http-parser-js' +import { Response } from './response.js' import type { SendRequestInit } from './index.js' import type { Stream } from '@libp2p/interface' import type { ByteStream } from 'it-byte-stream' @@ -10,13 +11,14 @@ export async function readResponse (bytes: ByteStream, resource: URL, in let headersComplete = false const parser = new HTTPParser('RESPONSE') + parser.maxHeaderSize = init.maxHeaderSize ?? HTTPParser.maxHeaderSize parser[HTTPParser.kOnHeadersComplete] = (info) => { init.log('response headers complete') headersComplete = true - const headers: Array<[string, string]> = [] + const headers = new Headers() for (let i = 0; i < info.headers.length; i += 2) { - headers.push([info.headers[i], info.headers[i + 1]]) + headers.append(info.headers[i], info.headers[i + 1]) } const response = new Response(body.readable, { diff --git a/src/fetch/response.ts b/src/fetch/response.ts new file mode 100644 index 0000000..9b9c933 --- /dev/null +++ b/src/fetch/response.ts @@ -0,0 +1,15 @@ +/** + * Extends the native Response class to preserve the passed headers - the fetch + * spec restricts access to certain headers that we need access to - + * `set-cookie`, `Access-Control-*`, etc, and the native Response implementation + * in browsers removes them + */ +export class Response extends globalThis.Response { + public readonly headers: Headers + + constructor (body: BodyInit | null, init?: ResponseInit) { + super(body, init) + + this.headers = new Headers(init?.headers) + } +} diff --git a/src/fetch/send-request.ts b/src/fetch/send-request.ts index ce101da..13b079f 100644 --- a/src/fetch/send-request.ts +++ b/src/fetch/send-request.ts @@ -1,4 +1,5 @@ import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { writeHeaders } from '../utils.js' import { blobBody } from './body/blob.js' import { bytesBody } from './body/bytes.js' import { formDataBody } from './body/form-data.js' @@ -79,20 +80,6 @@ function normalizeContent (body: BodyInit, headers: Headers): ReadableStream { throw new Error('Unsupported body type') } -function writeHeaders (headers: Headers): string[] { - const output = [] - - if (headers.get('Connection') == null) { - headers.set('Connection', 'close') - } - - for (const [key, value] of headers.entries()) { - output.push(`${key}: ${value}`) - } - - return output -} - function isBytes (obj?: any): obj is Uint8Array { if (obj == null) { return false diff --git a/src/http.browser.ts b/src/http.browser.ts index a5c47f0..8165296 100644 --- a/src/http.browser.ts +++ b/src/http.browser.ts @@ -1,17 +1,15 @@ -import { UnsupportedOperationError, serviceCapabilities } from '@libp2p/interface' -import { fromStringTuples } from '@multiformats/multiaddr' +import { UnsupportedOperationError, serviceCapabilities, start, stop } from '@libp2p/interface' import { PROTOCOL, WELL_KNOWN_PROTOCOLS } from './constants.js' +import { Cookies } from './cookies.js' import { fetch } from './fetch/index.js' import { HTTPRegistrar } from './registrar.js' -import { getHost, toMultiaddrs, toResource } from './utils.js' +import { getHost, prepareAndSendRequest, processResponse, stripHTTPPath, toMultiaddrs, toResource } from './utils.js' import { WebSocket as WebSocketClass } from './websocket/websocket.js' -import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, HTTPRequestHandler, ProtocolMap, RequestHandlerOptions } from './index.js' +import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, HTTPRequestHandler, ProtocolMap, RequestHandlerOptions, FetchInit, RequestProcessor } from './index.js' import type { ComponentLogger, Logger, PeerId, PrivateKey, Startable } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' -const HTTP_PATH_CODEC = 0x01e1 - export interface HTTPComponents { privateKey: PrivateKey registrar: Registrar @@ -22,13 +20,16 @@ export interface HTTPComponents { export class HTTP implements HTTPInterface, Startable { private readonly log: Logger protected readonly components: HTTPComponents - private readonly httpRegistrar: HTTPRegistrar + private readonly processors: RequestProcessor[] constructor (components: HTTPComponents, init: HTTPInit = {}) { this.components = components this.log = components.logger.forComponent('libp2p:http') this.httpRegistrar = new HTTPRegistrar(components, init) + this.processors = [ + new Cookies(components, init) + ] } readonly [Symbol.toStringTag] = '@libp2p/http' @@ -38,11 +39,17 @@ export class HTTP implements HTTPInterface, Startable { ] async start (): Promise { - await this.httpRegistrar.start() + await start( + this.httpRegistrar, + ...this.processors + ) } async stop (): Promise { - await this.httpRegistrar.stop() + await stop( + this.httpRegistrar, + ...this.processors + ) } agent (...args: any[]): any { @@ -53,7 +60,7 @@ export class HTTP implements HTTPInterface, Startable { throw new UnsupportedOperationError('This method is not supported in browsers') } - connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init?: WebSocketInit): globalThis.WebSocket { + connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init: WebSocketInit = {}): globalThis.WebSocket { const url = toResource(resource) if (url instanceof URL) { @@ -66,34 +73,21 @@ export class HTTP implements HTTPInterface, Startable { // strip http-path tuple but record the value if set const { addresses, httpPath } = stripHTTPPath(url) - return new WebSocketClass(addresses, new URL(`http://${getHost(init?.headers)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, { + return new WebSocketClass(addresses, new URL(`http://${getHost(url, init)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, { ...init, protocols, isClient: true }) } - async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: RequestInit = {}): Promise { + async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: FetchInit = {}): Promise { const url = toResource(resource) - if (url instanceof URL) { - return globalThis.fetch(url, init) - } - - // strip http-path tuple but record the value if set - const { addresses, httpPath } = stripHTTPPath(url) - - const connection = await this.components.connectionManager.openConnection(addresses, { - signal: init.signal ?? undefined - }) - const stream = await connection.newStream(PROTOCOL, { - signal: init.signal ?? undefined + const response = await prepareAndSendRequest(url, init, init.processors ?? this.processors, async () => { + return this.sendRequest(url, init) }) - return fetch(stream, new URL(`http://${getHost(init?.headers)}${decodeURIComponent(httpPath)}`), { - ...init, - logger: this.components.logger - }) + return processResponse(url, init, init.processors ?? this.processors, response) } async getSupportedProtocols (peer: PeerId | Multiaddr | Multiaddr[]): Promise { @@ -145,25 +139,38 @@ export class HTTP implements HTTPInterface, Startable { getProtocolMap (): ProtocolMap { return this.httpRegistrar.getProtocolMap() } -} -function stripHTTPPath (addresses: Multiaddr[]): { httpPath: string, addresses: Multiaddr[] } { - // strip http-path tuple but record the value if set - let httpPath = '/' - addresses = addresses.map(ma => { - return fromStringTuples( - ma.stringTuples().filter(t => { - if (t[0] === HTTP_PATH_CODEC && t[1] != null) { - httpPath = `/${t[1]}` - } - - return t[0] !== HTTP_PATH_CODEC - }) - ) - }) + private async sendRequest (resource: Multiaddr[] | URL, init: FetchInit): Promise { + if (resource instanceof URL) { + return globalThis.fetch(resource, init) + } + + const host = getHost(resource, init) - return { - httpPath, - addresses + // strip http-path tuple but record the value if set + const { addresses, httpPath } = stripHTTPPath(resource) + + const connection = await this.components.connectionManager.openConnection(addresses, { + signal: init.signal ?? undefined + }) + const stream = await connection.newStream(PROTOCOL, { + signal: init.signal ?? undefined + }) + + return fetch(stream, new URL(`http://${host}${decodeURIComponent(httpPath)}`), { + ...init, + logger: this.components.logger + }) } } + +export function toURL (resource: URL | Multiaddr[], init: FetchInit): URL { + if (resource instanceof URL) { + return resource + } + + const host = getHost(resource, init) + const { httpPath } = stripHTTPPath(resource) + + return new URL(`http://${host}${httpPath}`) +} diff --git a/src/http/server-response.ts b/src/http/server-response.ts index 3d76977..8d9fe8e 100644 --- a/src/http/server-response.ts +++ b/src/http/server-response.ts @@ -108,12 +108,15 @@ export class ServerResponse e } _write (chunk: any, encoding: BufferEncoding, callback: (error?: Error | null) => void): void { - this.flushHeaders() - this.socket?.write(chunk, encoding, callback) + this.flushHeaders(() => { + this.socket?.write(chunk, encoding, callback) + }) } _final (callback: (error?: Error | null) => void): void { - this.socket?.end(callback) + this.flushHeaders(() => { + this.socket?.end(callback) + }) } _destroy (error: Error | null, callback: (error?: Error | null) => void): void { @@ -197,8 +200,9 @@ export class ServerResponse e } - flushHeaders (): void { + flushHeaders (callback?: () => void): void { if (this.sentHeaders) { + callback?.() return } @@ -211,7 +215,7 @@ export class ServerResponse e '' ] - this.socket?.write(uint8arrayFromString(res.join('\r\n'))) + this.socket?.write(uint8arrayFromString(res.join('\r\n')), callback) } writeContinue (callback?: () => void): void { @@ -256,6 +260,8 @@ export class ServerResponse e throw new InvalidParametersError(`Unknown status code ${statusCode}`) } + this.statusCode = statusCode + this.flushHeaders() return this @@ -300,7 +306,9 @@ function writeHeaders (headers: Record { + output.push(`${key}: ${value}`) + }) } else { output.push(`${key}: ${value}`) } diff --git a/src/http/server.ts b/src/http/server.ts index d40fd3d..ee56e36 100644 --- a/src/http/server.ts +++ b/src/http/server.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'node:events' import { HTTPParser } from '@achingbrain/http-parser-js' -import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { NOT_IMPLEMENTED_ERROR } from '../utils.js' import { IncomingMessage as IncomingMessageClass } from './incoming-message.js' import { ServerResponse as ServerResponseClass } from './server-response.js' import type { ServerOptions, ServerResponse, IncomingMessage } from 'node:http' @@ -15,6 +15,7 @@ export class HTTPServer < Response extends typeof ServerResponse> = typeof ServerResponse > extends EventEmitter { public maxHeadersCount: number | null + public maxHeaderSize: number | null public maxRequestsPerSocket: number | null public timeout: number public headersTimeout: number @@ -34,6 +35,7 @@ export class HTTPServer < this.headersTimeout = 120_000 this.keepAliveTimeout = options.keepAliveTimeout ?? 0 this.requestTimeout = options.requestTimeout ?? 120_000 + this.maxHeaderSize = options.maxHeaderSize ?? HTTPParser.maxHeaderSize this.maxConnections = 0 this.connections = 0 this._listening = false @@ -43,15 +45,16 @@ export class HTTPServer < } private _handleConnection (socket: Socket): void { - const parser = new HTTPParser('REQUEST') let req: IncomingMessage | undefined + const parser = new HTTPParser('REQUEST') + parser.maxHeaderSize = this.maxHeaderSize ?? HTTPParser.maxHeaderSize parser[HTTPParser.kOnHeadersComplete] = (info) => { const headers = new Headers() // set incoming headers for (let i = 0; i < info.headers.length; i += 2) { - headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) + headers.append(info.headers[i].toLowerCase(), info.headers[i + 1]) } req = new IncomingMessageClass(socket, { @@ -64,7 +67,7 @@ export class HTTPServer < const listeners = this.listenerCount('upgrade') if (listeners === 0) { - socket.write(uint8arrayFromString('HTTP/1.1 501 Not Implemented\r\n\r\n')) + socket.write(NOT_IMPLEMENTED_ERROR) // socket.end() return } else { diff --git a/src/index.ts b/src/index.ts index 3239279..737c8d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -363,31 +363,44 @@ export interface WebSocketInit extends AbortOptions { maxMessageSize?: number /** - * If true, perform PeerId auth for the remote server before making the - * request. - * - * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md - * - * @default false + * Headers to send with the initial upgrade request */ - authenticate?: boolean + headers?: HeadersInit /** - * Headers to send with the initial upgrade request + * A list of request processors that can augment requests - if specified will + * override any processors passed to the `http` service */ - headers?: HeadersInit + processors?: RequestProcessor[] + + /** + * If true, cookies will not be used for this request + * + * @default false + */ + ignoreCookies?: boolean } export interface FetchInit extends RequestInit { /** - * If true, perform PeerId auth for the remote server before making the - * request. - * - * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + * A list of request processors that can augment requests - if specified will + * override any processors passed to the `http` service + */ + processors?: RequestProcessor[] + + /** + * If true, cookies will not be used for this request * * @default false */ - authenticate?: boolean + ignoreCookies?: boolean + + /** + * The maximum number of bytes that will be parsed as response headers + * + * @default 81_920 + */ + maxHeaderSize?: number } export interface HTTPRequestHandler { @@ -440,7 +453,7 @@ export interface HTTP { * URLs can start with the `multiaddr:` scheme if the global URL class in the * runtime environment supports it. */ - fetch(resource: string | URL | Multiaddr | Multiaddr[], init?: RequestInit): Promise + fetch(resource: string | URL | Multiaddr | Multiaddr[], init?: FetchInit): Promise /** * Open a WebSocket connection to an HTTP server over libp2p. @@ -545,6 +558,16 @@ export interface Endpoint { inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise } +/** + * Request/response middleware that allows augmenting the request/response with + * additional fields or headers. + */ +export interface RequestProcessor { + prepareRequest?(resource: URL | Multiaddr[], init: FetchInit): void | Promise + + processResponse?(resource: URL | Multiaddr[], init: FetchInit, response: Response): void | Promise +} + /** * Options to configure the HTTP service. * @@ -556,6 +579,30 @@ export interface HTTPInit { * A server that will receive incoming requests */ server?: Endpoint + + /** + * How long in ms an auth token for a server will be valid for, defaults to + * one hour + * + * @default 360_000 + */ + authTokenTTL?: number + + /** + * A list of request processors that can augment requests + */ + processors?: RequestProcessor[] + + /** + * How often to evict stale cookies from the cache in ms. + * + * Nb. cookies are checked for expiry before sending, this setting just + * prevents persisting cookies indefinitely for servers that are contacted + * infrequently. + * + * @default 60_000 + */ + cookieExpiryCheckInterval?: number } /** diff --git a/src/peer-id-auth.ts b/src/peer-id-auth.ts new file mode 100644 index 0000000..d24ba7e --- /dev/null +++ b/src/peer-id-auth.ts @@ -0,0 +1,177 @@ +import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' +import { InvalidParametersError } from '@libp2p/interface' +import { peerIdFromPublicKey } from '@libp2p/peer-id' +import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' +import { parseHeader, sign, verify } from './auth/common.js' +import { InvalidPeerError, InvalidSignatureError, MissingAuthHeaderError } from './auth/errors.js' +import { DEFAULT_AUTH_TOKEN_TTL, PEER_ID_AUTH_SCHEME } from './constants.js' +import { getCacheKey, getHeaders, getHost } from './utils.js' +import type { FetchInit, HTTP, RequestProcessor } from './index.js' +import type { AbortOptions, ComponentLogger, Logger, PeerId, PrivateKey } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' + +interface AuthToken { + peer: PeerId + expires: number + bearer: string +} + +interface PeerIdAuthComponents { + privateKey: PrivateKey + logger: ComponentLogger + http: HTTP +} + +interface PeerIdAuthInit { + verifyPeer?(peerId: PeerId): boolean | Promise + ttl?: number +} + +class PeerIdAuth implements RequestProcessor { + private readonly components: PeerIdAuthComponents + private readonly log: Logger + private readonly tokens: Map + private readonly tokenTTL: number + private readonly verifyPeer: (peerId: PeerId, options?: AbortOptions) => boolean | Promise + + constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit = {}) { + this.components = components + this.log = components.logger.forComponent('libp2p:http:peer-id-auth') + this.tokens = new Map() + this.tokenTTL = init.ttl ?? DEFAULT_AUTH_TOKEN_TTL + this.verifyPeer = init.verifyPeer ?? (() => true) + } + + async prepareRequest (resource: URL | Multiaddr[], init: FetchInit): Promise { + const headers = getHeaders(init) + + if (headers.get('authorization') != null) { + throw new InvalidParametersError('Will not overwrite existing Authorization header') + } + + const token = await this.getOrCreateAuthToken(resource, init) + headers.set('Authorization', token.bearer) + } + + async getOrCreateAuthToken (resource: URL | Multiaddr[], init: FetchInit): Promise { + const key = getCacheKey(resource, init) + let token = this.tokens.get(key) + + // check token expiry + if (token?.expires != null && token?.expires < Date.now()) { + this.tokens.delete(key) + token = undefined + } + + // create new token + if (token == null) { + token = await this.createAuthToken(resource, init) + } + + return token + } + + async createAuthToken (resource: URL | Multiaddr[], init: FetchInit): Promise { + const hostname = getHost(resource, init) + const headers = getHeaders(init) + + // Client initiated handshake (server initiated is not implemented yet) + const marshalledClientPubKey = publicKeyToProtobuf(this.components.privateKey.publicKey) + const publicKeyStr = uint8ArrayToString(marshalledClientPubKey, 'base64urlpad') + const challengeServer = generateChallenge() + + // copy existing headers + const challengeHeaders = new Headers(headers) + challengeHeaders.set('authorization', encodeAuthParams({ + 'challenge-server': challengeServer, + 'public-key': publicKeyStr + })) + + const resp = await this.components.http.fetch(resource, { + method: 'OPTIONS', + headers: challengeHeaders, + signal: init.signal, + processors: init.processors?.filter(proc => proc !== this) ?? undefined + }) + + // verify the server's challenge + const authHeader = resp.headers.get('www-authenticate') + if (authHeader == null) { + throw new MissingAuthHeaderError('No auth header') + } + const authFields = parseHeader(authHeader) + const serverPubKeyBytes = uint8ArrayFromString(authFields['public-key'], 'base64urlpad') + const serverPubKey = publicKeyFromProtobuf(serverPubKeyBytes) + + const valid = await verify(serverPubKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', hostname], + ['client-public-key', marshalledClientPubKey], + ['challenge-server', challengeServer]], uint8ArrayFromString(authFields.sig, 'base64urlpad')) + + if (!valid) { + throw new InvalidSignatureError('Invalid signature') + } + + const serverPublicKey = publicKeyFromProtobuf(serverPubKeyBytes) + const serverID = peerIdFromPublicKey(serverPublicKey) + + if (!await this.verifyPeer(serverID, { signal: init.signal ?? undefined })) { + throw new InvalidPeerError('Id check failed') + } + + const sig = await sign(this.components.privateKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', hostname], + ['server-public-key', serverPubKeyBytes], + ['challenge-client', authFields['challenge-client']]]) + + const authenticateSelfHeaders = encodeAuthParams({ + opaque: authFields.opaque, + sig: uint8ArrayToString(sig, 'base64urlpad') + }) + + const authToken = { + peer: serverID, + expires: Date.now() + this.tokenTTL, + bearer: authenticateSelfHeaders + } + + const key = getCacheKey(resource, init) + this.tokens.set(key, authToken) + + return authToken + } + + processResponse (resource: URL | Multiaddr[], init: FetchInit, response: Response): void { + const serverAuthHeader = response.headers.get('Authentication-Info') + + if (serverAuthHeader != null) { + const key = getCacheKey(resource, init) + const token = this.tokens.get(key) + + if (token != null) { + const serverAuthFields = parseHeader(serverAuthHeader) + token.bearer = serverAuthFields.bearer + } + } + } +} + +export function peerIdAuth (init: PeerIdAuthInit = {}): (components: PeerIdAuthComponents) => RequestProcessor { + return (components) => { + return new PeerIdAuth(components, init) + } +} + +function generateChallenge (): string { + const randomBytes = new Uint8Array(32) + crypto.getRandomValues(randomBytes) + return uint8ArrayToString(randomBytes, 'base64urlpad') +} + +function encodeAuthParams (params: Record): string { + const encodedParams = Object.entries(params) + .map(([key, value]) => `${key}="${value}"`) + .join(', ') + + return `${PEER_ID_AUTH_SCHEME} ${encodedParams}` +} diff --git a/src/ping/ping.ts b/src/ping/ping.ts index 9468782..e7a08c0 100644 --- a/src/ping/ping.ts +++ b/src/ping/ping.ts @@ -3,6 +3,7 @@ import { ProtocolError, serviceDependencies } from '@libp2p/interface' import { raceEvent } from 'race-event' import { raceSignal } from 'race-signal' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' +import { Response } from '../fetch/response.js' import { toMultiaddrs } from '../utils.js' import { webSocketHandler } from '../websocket-handler.js' import { HTTP_PING_PROTOCOL } from './index.js' diff --git a/src/registrar.ts b/src/registrar.ts index 12d9545..4e7c612 100644 --- a/src/registrar.ts +++ b/src/registrar.ts @@ -3,6 +3,7 @@ import { InvalidParametersError } from '@libp2p/interface' import { queuelessPushable } from 'it-queueless-pushable' import { Uint8ArrayList } from 'uint8arraylist' import { PROTOCOL, WEBSOCKET_HANDLER, WELL_KNOWN_PROTOCOLS } from './constants.js' +import { Response } from './fetch/response.js' import { NOT_FOUND_RESPONSE, responseToStream, streamToRequest } from './utils.js' import { wellKnownHandler } from './well-known-handler.js' import type { Endpoint, HTTPRequestHandler, HeaderInfo, ProtocolMap, RequestHandlerOptions, WebSocketHandler } from './index.js' diff --git a/src/utils.ts b/src/utils.ts index f85ad63..6a54da2 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,19 +1,19 @@ -import { isPeerId } from '@libp2p/interface' -import { isMultiaddr, multiaddr } from '@multiformats/multiaddr' +import { InvalidParametersError, isPeerId } from '@libp2p/interface' +import { peerIdFromString } from '@libp2p/peer-id' +import { fromStringTuples, isMultiaddr, multiaddr } from '@multiformats/multiaddr' import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' import { uriToMultiaddr } from '@multiformats/uri-to-multiaddr' import { queuelessPushable } from 'it-queueless-pushable' import itToBrowserReadableStream from 'it-to-browser-readablestream' +import { base36 } from 'multiformats/bases/base36' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' -import { DEFAULT_HOST } from './constants.js' -import type { HeaderInfo } from './index.js' +import { DNS_CODECS, HTTP_CODEC, HTTP_PATH_CODEC } from './constants.js' +import type { FetchInit, HeaderInfo, RequestProcessor } from './index.js' import type { PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Readable } from 'node:stream' import type { Uint8ArrayList } from 'uint8arraylist' -const HTTP_CODEC = 0x01e0 - /** * Normalizes byte-like input to a `Uint8Array` */ @@ -117,6 +117,13 @@ export const INTERNAL_SERVER_ERROR = uint8arrayFromString([ '' ].join('\r\n')) +export const NOT_IMPLEMENTED_ERROR = uint8arrayFromString([ + 'HTTP/1.1 501 Not Implemented', + 'Connection: close', + '', + '' +].join('\r\n')) + /** * Normalizes the dial target to a list of multiaddrs with an optionally * encapsulated suffix @@ -246,22 +253,133 @@ export function toResource (resource: string | URL | Multiaddr | Multiaddr[]): U return resource } -export function getHost (init?: HeadersInit): string { - if (init == null) { - return DEFAULT_HOST +export function getHeaders (init: RequestInit = {}): Headers { + if (init.headers instanceof Headers) { + return init.headers } - if (init instanceof Headers) { - return init.get('host') ?? DEFAULT_HOST + init.headers = new Headers(init.headers) + + return init.headers +} + +export function getHeader (header: string, headers: HeadersInit = {}): string | undefined { + if (headers instanceof Headers) { + return headers.get(header) ?? undefined } - let entries: Array<[string, string]> + if (Array.isArray(headers)) { + return headers.find(([key, value]) => { + if (key === header) { + return value + } - if (Array.isArray(init)) { - entries = init - } else { - entries = Object.entries(init) + return undefined + })?.[1] + } + + return headers[header] +} + +function isValidHost (host?: string): host is string { + return host != null && host !== '' +} + +export function getHost (addresses: URL | Multiaddr[], init: RequestInit): string { + let host: string | undefined + + if (addresses instanceof URL) { + host = addresses.hostname + } + + if (!isValidHost(host)) { + const headers = getHeaders(init) + host = headers.get('host') ?? undefined + } + + // try to extract domain from DNS addresses + if (!isValidHost(host) && Array.isArray(addresses)) { + for (const address of addresses) { + const stringTuples = address.stringTuples() + const filtered = stringTuples.filter(([key]) => DNS_CODECS.includes(key))?.[0]?.[1] + + if (filtered != null) { + host = filtered + break + } + } + } + + // try to use remote PeerId as domain + if (!isValidHost(host) && Array.isArray(addresses)) { + for (const address of addresses) { + const peerStr = address.getPeerId() + + if (peerStr != null) { + const peerId = peerIdFromString(peerStr) + // host has to be case-insensitive + host = peerId.toCID().toString(base36) + break + } + } + } + + if (isValidHost(host)) { + return host + } + + throw new InvalidParametersError('Could not determine request host name - a request must have a host header, be made to a DNS-based multiaddr or an http(s) URL') +} + +export function getCacheKey (resource: URL | Multiaddr[], init: RequestInit): string { + let prefix = '' + + if (Array.isArray(resource)) { + const peer = resource.map(ma => ma.getPeerId()) + .filter(Boolean) + .pop() + + if (peer != null) { + prefix = `${peer}-` + } } - return entries.find(([key]) => key.toLowerCase() === 'host')?.[1] ?? DEFAULT_HOST + return `${prefix}${getHost(resource, init)}` +} + +export async function prepareAndSendRequest (resource: URL | Multiaddr[], init: RequestInit, processors: RequestProcessor[], sendRequest: (resource: URL | Multiaddr[], init: FetchInit) => Promise): Promise { + for (const processor of processors) { + await processor.prepareRequest?.(resource, init) + } + + return sendRequest(resource, init) +} + +export async function processResponse (resource: URL | Multiaddr[], init: RequestInit, processors: RequestProcessor[], response: Response): Promise { + for (const proc of processors) { + await proc.processResponse?.(resource, init, response) + } + + return response +} + +export function stripHTTPPath (addresses: Multiaddr[]): { httpPath: string, addresses: Multiaddr[] } { + // strip http-path tuple but record the value if set + let httpPath = '/' + addresses = addresses.map(ma => { + return fromStringTuples( + ma.stringTuples().filter(t => { + if (t[0] === HTTP_PATH_CODEC && t[1] != null) { + httpPath = `/${t[1]}` + } + + return t[0] !== HTTP_PATH_CODEC + }) + ) + }) + + return { + httpPath, + addresses + } } diff --git a/src/websocket-handler.ts b/src/websocket-handler.ts index 949e71b..b0ec7df 100644 --- a/src/websocket-handler.ts +++ b/src/websocket-handler.ts @@ -1,4 +1,5 @@ import { WEBSOCKET_HANDLER } from './constants.js' +import { Response } from './fetch/response.js' import { getServerUpgradeHeaders } from './websocket/utils.js' import { RequestWebSocket } from './websocket/websocket.js' import type { HTTPRequestHandler, WebSocketHandler } from './index.js' diff --git a/src/websocket/utils.ts b/src/websocket/utils.ts index a81ffbd..b3cad7e 100644 --- a/src/websocket/utils.ts +++ b/src/websocket/utils.ts @@ -101,30 +101,29 @@ function getHeader (headers: Headers | Record { +export async function * performClientUpgrade (url: URL, protocols: string[] = [], headers: Headers): AsyncGenerator { const webSocketKey = base64pad.encode( crypto.getRandomValues(new Uint8Array(16)) ).substring(1) - const headers = [ - `GET ${url.pathname ?? '/'} HTTP/1.1`, - `Host: ${url.hostname}`, - 'Connection: upgrade', - 'Upgrade: websocket', - 'Pragma: no-cache', - 'Cache-Control: no-cache', - 'Sec-WebSocket-Version: 13', - `Sec-WebSocket-Key: ${webSocketKey}` - ] + headers.set('host', url.hostname) + headers.set('connection', 'upgrade') + headers.set('upgrade', 'websocket') + headers.set('pragma', 'no-cache') + headers.set('cache-control', 'no-cache') + headers.set('sec-websocket-version', '13') + headers.set('sec-websocket-key', webSocketKey) if (protocols.length > 0) { - headers.push(`Sec-WebSocket-Protocol: ${protocols?.join(', ')}`) + headers.set('sec-websocket-protocol', protocols.join(', ')) } - headers.push('', '') - - const req = uint8ArrayFromString(headers.join('\r\n')) - yield req + yield uint8ArrayFromString([ + `GET ${url.pathname ?? '/'} HTTP/1.1`, + ...[...headers.entries()].map(([key, value]) => `${key}: ${value}`), + '', + '' + ].join('\r\n')) } export async function getServerUpgradeHeaders (headers: Headers | Record): Promise { diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts index 268bf3f..3de15d4 100644 --- a/src/websocket/websocket.ts +++ b/src/websocket/websocket.ts @@ -3,14 +3,14 @@ import { isPromise } from '@libp2p/utils/is-promise' import { byteStream, type ByteStream } from 'it-byte-stream' import { Uint8ArrayList } from 'uint8arraylist' import { PROTOCOL } from '../constants.js' -import { getHost } from '../utils.js' +import { getHeaders } from '../utils.js' import { ErrorEvent } from './events.js' import { encodeMessage, decodeMessage, CLOSE_MESSAGES } from './message.js' import { performClientUpgrade, performServerUpgrade, readResponse, toBytes } from './utils.js' import type { CloseListener, ErrorListener, MessageListener, OpenListener, WebSocketEvents } from './index.js' import type { MESSAGE_TYPE } from './message.js' -import type { HeaderInfo } from '../index.js' -import type { Stream, AbortOptions } from '@libp2p/interface' +import type { HeaderInfo, WebSocketInit } from '../index.js' +import type { Stream } from '@libp2p/interface' import type { ConnectionManager } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' import type { IncomingMessage } from 'node:http' @@ -20,16 +20,9 @@ const DATA_MESSAGES: MESSAGE_TYPE[] = ['BINARY', 'TEXT', 'CONTINUATION'] const MAX_MESSAGE_SIZE = 10_485_760 const DEFAULT_HOST = 'example.com' -export interface WebSocketInit extends AbortOptions { +export interface AbstractWebSocketInit extends WebSocketInit { protocols?: string[] isClient?: boolean - - /** - * The maximum message size to be sent or received over the socket in bytes - * - * @default 10_485_760 - */ - maxMessageSize?: number } export abstract class AbstractWebSocket extends TypedEventEmitter { @@ -57,7 +50,7 @@ export abstract class AbstractWebSocket extends TypedEventEmitter - constructor (info: HeaderInfo, stream: Stream, init?: WebSocketInit) { + constructor (info: HeaderInfo, stream: Stream, init?: AbstractWebSocketInit) { super(new URL(`http://${info.headers.get('host') ?? DEFAULT_HOST}${info.url}`), { ...init, isClient: false @@ -338,8 +331,8 @@ export class RequestWebSocket extends AbstractWebSocket { private readonly writer: WritableStreamDefaultWriter private readonly writable: WritableStream - constructor (request: Request, writable: WritableStream, init?: WebSocketInit) { - super(new URL(`http://${getHost(request.headers)}${request.url}`), { + constructor (request: Request, writable: WritableStream, init: AbstractWebSocketInit = {}) { + super(new URL(request.url), { ...init, isClient: false }) @@ -406,7 +399,7 @@ export class RequestWebSocket extends AbstractWebSocket { export class WebSocket extends AbstractWebSocket { private bytes?: ByteStream - constructor (mas: Multiaddr[], url: URL, connectionManager: ConnectionManager, init: WebSocketInit = {}) { + constructor (mas: Multiaddr[], url: URL, connectionManager: ConnectionManager, init: AbstractWebSocketInit = {}) { super(url, { ...init, isClient: true @@ -418,7 +411,7 @@ export class WebSocket extends AbstractWebSocket { const stream = await connection.newStream(PROTOCOL, init) this.bytes = byteStream(stream) - for await (const buf of performClientUpgrade(url, init.protocols)) { + for await (const buf of performClientUpgrade(url, init.protocols, getHeaders(init))) { await this.bytes.write(buf) } diff --git a/src/well-known-handler.ts b/src/well-known-handler.ts index ca3cdfb..8da2b8a 100644 --- a/src/well-known-handler.ts +++ b/src/well-known-handler.ts @@ -1,3 +1,4 @@ +import { Response } from './fetch/response.js' import { webSocketHandler } from './websocket-handler.js' import type { HTTPRequestHandler } from './index.js' import type { HTTPRegistrar } from './registrar.js' diff --git a/test/cookies.spec.ts b/test/cookies.spec.ts new file mode 100644 index 0000000..66ef6c3 --- /dev/null +++ b/test/cookies.spec.ts @@ -0,0 +1,148 @@ +import { stop } from '@libp2p/interface' +import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' +import { expect } from 'aegir/chai' +import { createServer } from '../src/http/index.js' +import { nodeServer } from '../src/servers/node.js' +import { createHttp } from './fixtures/create-http.js' +import { getClient, getListener } from './fixtures/get-libp2p.js' +import type { HTTP } from '../src/index.js' +import type { Libp2p } from 'libp2p' + +interface Test { + name: string + startServer(): Promise + stopServer(): Promise +} + +let listener: Libp2p<{ http: HTTP }> + +const tests: Test[] = [{ + name: 'in-process server', + startServer: async () => { + const server = createHttp(createServer()) + listener = await getListener(nodeServer(server)) + + return listener.getMultiaddrs() + }, + stopServer: async () => { + await stop(listener) + } +}, { + name: 'js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_HTTP_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_HTTP_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'express/js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_EXPRESS_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'express/node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_EXPRESS_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'fastify/js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_FASTIFY_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'fastify/node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_FASTIFY_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}] + +for (const test of tests) { + describe(`cookies - ${test.name}`, () => { + let client: Libp2p<{ http: HTTP }> + let listenerMultiaddrs: Multiaddr[] + + beforeEach(async () => { + client = await getClient() + listenerMultiaddrs = await test.startServer() + }) + + afterEach(async () => { + await stop(client) + await test.stopServer() + }) + + it('should support cookies', async () => { + const setResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/set-cookies')), { + headers: { + host: 'test-with-cookies.com' + } + }) + expect(setResponse.status).to.equal(201) + expect(setResponse.headers.get('set-cookie')).to.not.be.ok() + + const getResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/get-cookies')), { + headers: { + host: 'test-with-cookies.com' + } + }) + expect(getResponse.status).to.equal(200) + await expect(getResponse.json()).to.eventually.deep.equal([ + 'cookie-1=value-1', + 'cookie-2=value-2' + ]) + }) + + it('should support ignoring cookies', async () => { + const setResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/set-cookies')), { + headers: { + host: 'test-without-cookies.com' + }, + ignoreCookies: true + }) + expect(setResponse.status).to.equal(201) + expect(setResponse.headers.get('set-cookie')).to.not.be.ok() + + const getResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/get-cookies')), { + headers: { + host: 'test-without-cookies.com' + }, + ignoreCookies: true + }) + expect(getResponse.status).to.equal(200) + await expect(getResponse.json()).to.eventually.deep.equal([]) + }) + }) +} diff --git a/test/fetch.spec.ts b/test/fetch.spec.ts index 9289057..71eee24 100644 --- a/test/fetch.spec.ts +++ b/test/fetch.spec.ts @@ -3,8 +3,8 @@ import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import { createServer } from '../src/http/index.js' import { nodeServer } from '../src/servers/node.js' +import { createHttp } from './fixtures/create-http.js' import { getClient, getListener } from './fixtures/get-libp2p.js' -import { getServer } from './fixtures/get-server.js' import type { HTTP } from '../src/index.js' import type { Libp2p } from 'libp2p' @@ -19,7 +19,7 @@ let listener: Libp2p<{ http: HTTP }> const tests: Test[] = [{ name: 'in-process server', startServer: async () => { - const server = getServer(createServer) + const server = createHttp(createServer()) listener = await getListener(nodeServer(server)) return listener.getMultiaddrs() diff --git a/test/fixtures/create-express.ts b/test/fixtures/create-express.ts index 3798e4b..ecd1469 100644 --- a/test/fixtures/create-express.ts +++ b/test/fixtures/create-express.ts @@ -1,3 +1,4 @@ +import cookieParser from 'cookie-parser' import express from 'express' import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' import type { Server } from 'node:http' @@ -8,6 +9,7 @@ import type { Server } from 'node:http' */ export function createExpress (server: Server, handler?: Libp2pOverHTTPHandler): Server { const app = express() + app.use(cookieParser()) app.get('/', (req, res) => { res.send('Hello World!') }) @@ -22,6 +24,15 @@ export function createExpress (server: Server, handler?: Libp2pOverHTTPHandler): res.destroy(err) }) }) + app.get('/set-cookies', (req, res) => { + res.appendHeader('set-cookie', `cookie-1=value-1; Domain=${req.headers.host}; Max-Age=3600`) + res.appendHeader('set-cookie', 'cookie-2=value-2') + res.writeHead(201) + res.end() + }) + app.get('/get-cookies', (req, res) => { + res.end(JSON.stringify(Object.entries(req.cookies).map(([key, value]) => `${key}=${value}`))) + }) server.on('request', (req, res) => { res.setHeader('Access-Control-Allow-Origin', '*') diff --git a/test/fixtures/create-fastify-http.ts b/test/fixtures/create-fastify-http.ts index d04af29..56144c1 100644 --- a/test/fixtures/create-fastify-http.ts +++ b/test/fixtures/create-fastify-http.ts @@ -1,3 +1,4 @@ +import cookies from '@fastify/cookie' import { fastify } from 'fastify' import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' import type { FastifyRequest } from 'fastify' @@ -21,6 +22,8 @@ export async function createFastifyHTTP (server: Server, handler?: Libp2pOverHTT } }) + await app.register(cookies) + // fastify only supports 'application/json' and 'text/plain' by default app.addContentTypeParser('*', async (req: FastifyRequest, payload: IncomingMessage) => { return payload @@ -43,6 +46,18 @@ export async function createFastifyHTTP (server: Server, handler?: Libp2pOverHTT reply.raw.destroy(err) }) }) + app.get('/set-cookies', async (req, res) => { + await res.setCookie('cookie-1', 'value-1', { + domain: req.headers.host, + maxAge: 3600 + }) + await res.setCookie('cookie-2', 'value-2') + res.statusCode = 201 + await res.send() + }) + app.get('/get-cookies', async (req, res) => { + await res.send(JSON.stringify(Object.entries(req.cookies).map(([key, value]) => `${key}=${value}`))) + }) await app.ready() diff --git a/test/fixtures/create-http.ts b/test/fixtures/create-http.ts index ef9522e..708aa48 100644 --- a/test/fixtures/create-http.ts +++ b/test/fixtures/create-http.ts @@ -9,6 +9,21 @@ export function createHttp (server: Server, handler?: Libp2pOverHTTPHandler): Se return } + if (req.url === '/set-cookies') { + res.appendHeader('set-cookie', `cookie-1=value-1; Domain=${req.headers.host}; Max-Age=3600`) + res.appendHeader('set-cookie', 'cookie-2=value-2') + res.writeHead(201) + res.end() + + return + } + + if (req.url === '/get-cookies') { + res.end(JSON.stringify(req.headers.cookie?.split(';').map(s => s.trim()) ?? [])) + + return + } + res.end('Hello World!') } diff --git a/test/fixtures/get-server.ts b/test/fixtures/get-server.ts deleted file mode 100644 index 8a5bf23..0000000 --- a/test/fixtures/get-server.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { createServer } from 'node:http' - -export function getServer (s: typeof createServer): ReturnType { - return s((req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Request-Method', '*') - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') - res.setHeader('Access-Control-Allow-Headers', '*') - - if (req.url === '/echo') { - req.on('data', buf => { - res.write(buf) - }) - req.on('end', () => { - res.end() - }) - req.on('error', err => { - res.destroy(err) - }) - - return - } - - res.end('Hello World!') - }) -} From 718286f9fe44022a620b9ba446bf36311c553936 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 9 Apr 2025 19:18:23 +0100 Subject: [PATCH 04/22] chore: cookies and middleware --- .gitignore | 2 + README.md | 3177 +------------------------- package.json | 2 +- src/constants.ts | 65 + src/cookies.ts | 20 +- src/fetch/response.ts | 26 +- src/http.browser.ts | 47 +- src/http/server-response.ts | 67 +- src/index.ts | 35 +- src/peer-id-auth.ts | 52 +- src/utils.ts | 23 +- src/websocket/index.ts | 6 +- src/websocket/server.ts | 3 +- src/websocket/utils.ts | 11 +- src/websocket/websocket.ts | 24 +- test/fixtures/create-fastify-http.ts | 6 +- test/peer-id-auth.spec.ts | 132 ++ 17 files changed, 359 insertions(+), 3339 deletions(-) create mode 100644 test/peer-id-auth.spec.ts diff --git a/.gitignore b/.gitignore index 7ad9e67..f115d26 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ node_modules package-lock.json yarn.lock .vscode +.tmp-compiled-docs +tsconfig-doc-check.aegir.json diff --git a/README.md b/README.md index 48e4caa..b6d358d 100644 --- a/README.md +++ b/README.md @@ -36,3186 +36,13 @@ frameworks like [Hono](https://hono.dev/). It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s -(based on the [ws](https://www.npmjs.com/package/ws) module API in the -absence of a native Node.js API to emulate) in browsers to truly realize the -power of the distributed web. +in browsers to truly realize the power of the distributed web. -Instead of the regular "host:port" addressing, it uses a libp2p PeerId and/or +In addition to URL-based addressing, it can use a libp2p PeerId and/or multiaddr(s) and lets libp2p take care of the routing, thus taking advantage of features like multi-routes, NAT transversal and stream multiplexing over a single connection. -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@libp2p/http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import { multiaddr } from '@multiformats/multiaddr' - -const client = await createLibp2p({ - // ...other options - services: { - http: http() - } -}) - -const peerId = peerIdFromString('12DKoo') -const ma = multiaddr(`/p2p/${peerId}/http`) -const response = await client.services.httpClient.fetch(ma, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@libp2p/http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@libp2p/http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import { multiaddr } from '@multiformats/multiaddr' - -const client = await createLibp2p({ - // ...other options - services: { - http: http() - } -}) - -const peerId = peerIdFromString('12DKoo') -const ma = multiaddr(`/p2p/${peerId}/http`) -const response = await client.services.httpClient.fetch(ma, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@libp2p/http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@libp2p/http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import { multiaddr } from '@multiformats/multiaddr' - -const client = await createLibp2p({ - // ...other options - services: { - http: http() - } -}) - -const peerId = peerIdFromString('12DKoo') -const ma = multiaddr(`/p2p/${peerId}/http`) -const response = await client.services.httpClient.fetch(ma, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@libp2p/http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@libp2p/http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@libp2p/http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server)) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { http } from '@libp2p/http' -import { nodeServer } from '@libp2p/http/servers/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: http({ - server: nodeServer(server)) - }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Servers - -You can create HTTP and WebSocket servers using the framework of your choice, -as long as it accepts a Node.js `http.Server` instance. - -## Example - Node HTTP server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@libp2p/libp2p-http' -import { nodeServer } from '@libp2p/libp2p-http/node' -import { createServer } from 'node:http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - http: httpServer({ server: nodeServer(server) }) - } -}) -``` - -## Example - Express server - -```ts -import express from 'express' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -// create an express app -const app = express() -app.get('/', (req, res) => { - res.send('Hello World!') -}) - -const server = createServer(app) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - Fastify server - -```ts -import { fastify } from 'fastify' -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' - -let server - -// create a fastify app -const app = fastify({ - serverFactory: (handler, opts) => { - server = createServer((req, res) => { - handler(req, res) - }) - - return server - } - }) -app.get('/', async (req, res) => { - await res.send('Hello World!') -}) -await app.ready() - -if (server == null) { - throw new Error('Server not created') - } - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - ws WebSocket server - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer } from '@ipshipyard/libp2p-http' -import { createServer } from 'node:http' -import { WebSocketServer } from 'ws' - -const wss = new WebSocketServer({ noServer: true }) -wss.on('connection', (ws) => { - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.on('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -# Clients - -You can use the built-in `.fetch` and `.connect` methods to make HTTP or -WebSocket requests respectively, or you can create a Node.js `http.Agent` for -use with the `node:http`, or a `Dispatcher` for use with `undici`. - -## Example - Using fetch to make a HTTP request - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const response = await client.services.httpClient.fetch(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -## Example - Using connect to create a WebSocket - -This example works in all JavaScript environments, Node.js and browsers too! - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') -const webSocket = await client.services.httpClient.connect(peerId, url, { - signal: AbortSignal.timeout(10_000) -}) - -webSocket.addEventListener('message', (evt) => { - console.info(response.data) - // -}) -``` - -## Example - Using a http.Agent to make a request with node:http - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import * as http from 'node:http' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const agent = client.services.httpClient.agent(peerId) - -const req = http.request({ host: 'example.com', agent }, (res) => { - let result = '' - - res.setEncoding('utf8') - res.on('data', (chunk) => { - result += chunk - }) - res.on('end', () => { - console.info(result) - // Hello world! - }) -}) - -req.end() -``` - -## Example - Using a Dispatcher to make a request with undici - -This example only works in Node.js-compatible environments. - -```ts -import { createLibp2p } from 'libp2p' -import { httpClient } from '@ipshipyard/libp2p-http' -import { peerIdFromString } from '@libp2p/peer-id' -import { fetch } from 'undici' - -const client = await createLibp2p({ - // ...other options - services: { - httpClient: httpClient() - } -}) - -const peerId = peerIdFromString('12DKoo') -const url = new URL('http://example.com') - -const dispatcher = client.services.httpClient.dispatcher(peerId) -const response = await fetch(url, { - dispatcher, - signal: AbortSignal.timeout(10_000) -}) - -console.info('Response:', response.status) -// Response: 200 - -console.info(await response.text()) -// Hello world! -``` - -# Browsers - -Making requests to servers is all good and well, but what if you could also -run a web or WebSocket server in a browser? - -## Example - A HTTP server running in a browser - -Once configured you can make requests to this server in the same was as the -fetch example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer } from '@ipshipyard/libp2p-http' - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - -## Example - A WebSocket server running in a browser - -Once configured you can make requests to this server in the same was as the -WebSocket example near the top of this README. - -```ts -import { createLibp2p } from 'libp2p' -import { httpServer, createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' - -const wss = createWebSocketServer() -wss.addEventListener('connection', (evt) => { - const ws = evt.webSocket - - ws.on('message', (data) => { - ws.send(data) - }) -}) - -const server = createServer((req, res) => { - req.end('Hello world!') -}) - -server.addListener('upgrade', (request, socket, head) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit('connection', ws, request) - }) -}) - -const listener = await createLibp2p({ - // ...other options - services: { - httpServer: httpServer({ server }) - } -}) -``` - # Install ```console diff --git a/package.json b/package.json index 159caf9..767b0f3 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ "release": "aegir release" }, "dependencies": { - "@achingbrain/http-parser-js": "^0.5.8", + "@achingbrain/http-parser-js": "^0.5.9", "@libp2p/crypto": "^5.0.6", "@libp2p/interface": "^2.2.0", "@libp2p/interface-internal": "^2.0.10", diff --git a/src/constants.ts b/src/constants.ts index 87257a1..18cc364 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -17,3 +17,68 @@ export const DNS_CODECS = [ DNSADDR_CODEC ] export const DEFAULT_COOKIE_EXPIRY_CHECK_INTERVAL = 60_000 +export const STATUS_CODES: Record = { + 100: 'Continue', // RFC 7231 6.2.1 + 101: 'Switching Protocols', // RFC 7231 6.2.2 + 102: 'Processing', // RFC 2518 10.1 (obsoleted by RFC 4918) + 103: 'Early Hints', // RFC 8297 2 + 200: 'OK', // RFC 7231 6.3.1 + 201: 'Created', // RFC 7231 6.3.2 + 202: 'Accepted', // RFC 7231 6.3.3 + 203: 'Non-Authoritative Information', // RFC 7231 6.3.4 + 204: 'No Content', // RFC 7231 6.3.5 + 205: 'Reset Content', // RFC 7231 6.3.6 + 206: 'Partial Content', // RFC 7233 4.1 + 207: 'Multi-Status', // RFC 4918 11.1 + 208: 'Already Reported', // RFC 5842 7.1 + 226: 'IM Used', // RFC 3229 10.4.1 + 300: 'Multiple Choices', // RFC 7231 6.4.1 + 301: 'Moved Permanently', // RFC 7231 6.4.2 + 302: 'Found', // RFC 7231 6.4.3 + 303: 'See Other', // RFC 7231 6.4.4 + 304: 'Not Modified', // RFC 7232 4.1 + 305: 'Use Proxy', // RFC 7231 6.4.5 + 307: 'Temporary Redirect', // RFC 7231 6.4.7 + 308: 'Permanent Redirect', // RFC 7238 3 + 400: 'Bad Request', // RFC 7231 6.5.1 + 401: 'Unauthorized', // RFC 7235 3.1 + 402: 'Payment Required', // RFC 7231 6.5.2 + 403: 'Forbidden', // RFC 7231 6.5.3 + 404: 'Not Found', // RFC 7231 6.5.4 + 405: 'Method Not Allowed', // RFC 7231 6.5.5 + 406: 'Not Acceptable', // RFC 7231 6.5.6 + 407: 'Proxy Authentication Required', // RFC 7235 3.2 + 408: 'Request Timeout', // RFC 7231 6.5.7 + 409: 'Conflict', // RFC 7231 6.5.8 + 410: 'Gone', // RFC 7231 6.5.9 + 411: 'Length Required', // RFC 7231 6.5.10 + 412: 'Precondition Failed', // RFC 7232 4.2 + 413: 'Payload Too Large', // RFC 7231 6.5.11 + 414: 'URI Too Long', // RFC 7231 6.5.12 + 415: 'Unsupported Media Type', // RFC 7231 6.5.13 + 416: 'Range Not Satisfiable', // RFC 7233 4.4 + 417: 'Expectation Failed', // RFC 7231 6.5.14 + 418: 'I\'m a Teapot', // RFC 7168 2.3.3 + 421: 'Misdirected Request', // RFC 7540 9.1.2 + 422: 'Unprocessable Entity', // RFC 4918 11.2 + 423: 'Locked', // RFC 4918 11.3 + 424: 'Failed Dependency', // RFC 4918 11.4 + 425: 'Too Early', // RFC 8470 5.2 + 426: 'Upgrade Required', // RFC 2817 and RFC 7231 6.5.15 + 428: 'Precondition Required', // RFC 6585 3 + 429: 'Too Many Requests', // RFC 6585 4 + 431: 'Request Header Fields Too Large', // RFC 6585 5 + 451: 'Unavailable For Legal Reasons', // RFC 7725 3 + 500: 'Internal Server Error', // RFC 7231 6.6.1 + 501: 'Not Implemented', // RFC 7231 6.6.2 + 502: 'Bad Gateway', // RFC 7231 6.6.3 + 503: 'Service Unavailable', // RFC 7231 6.6.4 + 504: 'Gateway Timeout', // RFC 7231 6.6.5 + 505: 'HTTP Version Not Supported', // RFC 7231 6.6.6 + 506: 'Variant Also Negotiates', // RFC 2295 8.1 + 507: 'Insufficient Storage', // RFC 4918 11.5 + 508: 'Loop Detected', // RFC 5842 7.2 + 509: 'Bandwidth Limit Exceeded', + 510: 'Not Extended', // RFC 2774 7 + 511: 'Network Authentication Required' // RFC 6585 6 +} diff --git a/src/cookies.ts b/src/cookies.ts index 7891703..ac35bad 100644 --- a/src/cookies.ts +++ b/src/cookies.ts @@ -1,7 +1,6 @@ import cookie from 'cookie' import { toURL } from './http.browser.js' -import { getHeaders } from './utils.js' -import type { FetchInit, RequestProcessor } from './index.js' +import type { RequestMiddleware, RequestOptions } from './index.js' import type { ComponentLogger, Logger } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -21,7 +20,7 @@ interface Cookie { path?: string } -export class Cookies implements RequestProcessor { +export class Cookies implements RequestMiddleware { private readonly log: Logger private readonly cookies: Map @@ -30,12 +29,12 @@ export class Cookies implements RequestProcessor { this.cookies = new Map() } - async prepareRequest (resource: URL | Multiaddr[], init: FetchInit): Promise { - if (init.ignoreCookies === true) { + async prepareRequest (resource: URL | Multiaddr[], opts: RequestOptions): Promise { + if (opts.ignoreCookies) { return } - const url = toURL(resource, init) + const url = toURL(resource, opts.headers) const cookies = (this.cookies.get(url.hostname) ?? []).filter(cookie => { if (cookie.expires != null && cookie.expires < Date.now()) { return false @@ -51,19 +50,18 @@ export class Cookies implements RequestProcessor { .join('; ') if (cookies.length > 0) { - const headers = getHeaders(init) - headers.set('cookie', cookies) + opts.headers.set('cookie', cookies) } } - async processResponse (resource: URL | Multiaddr[], init: FetchInit, response: Response): Promise { - if (init.ignoreCookies === true) { + async processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): Promise { + if (opts.ignoreCookies) { removeSetCookie(response) return } - const url = toURL(resource, init) + const url = toURL(resource, opts.headers) for (const value of response.headers.getSetCookie()) { const cookies = [ diff --git a/src/fetch/response.ts b/src/fetch/response.ts index 9b9c933..64e512e 100644 --- a/src/fetch/response.ts +++ b/src/fetch/response.ts @@ -1,15 +1,31 @@ +import { STATUS_CODES } from '../constants.js' + /** - * Extends the native Response class to preserve the passed headers - the fetch - * spec restricts access to certain headers that we need access to - - * `set-cookie`, `Access-Control-*`, etc, and the native Response implementation - * in browsers removes them + * Extends the native Response class to be more flexible. + * + * - response headers - the fetch spec restricts access to certain headers that + * we need access to `set-cookie`, `Access-Control-*`, etc, and the native + * Response implementations remove them + * + * - status codes - we need to represent all possible HTTP status codes, not + * just those allowed by the fetch spec */ export class Response extends globalThis.Response { + public readonly status: number + public readonly statusText: string public readonly headers: Headers - constructor (body: BodyInit | null, init?: ResponseInit) { + constructor (body: BodyInit | null, init: ResponseInit = {}) { + const status = init.status ?? 200 + + if (status < 200 || status > 599) { + init.status = 200 + } + super(body, init) + this.status = status + this.statusText = STATUS_CODES[status] this.headers = new Headers(init?.headers) } } diff --git a/src/http.browser.ts b/src/http.browser.ts index 8165296..bc5c053 100644 --- a/src/http.browser.ts +++ b/src/http.browser.ts @@ -3,9 +3,9 @@ import { PROTOCOL, WELL_KNOWN_PROTOCOLS } from './constants.js' import { Cookies } from './cookies.js' import { fetch } from './fetch/index.js' import { HTTPRegistrar } from './registrar.js' -import { getHost, prepareAndSendRequest, processResponse, stripHTTPPath, toMultiaddrs, toResource } from './utils.js' +import { getHeaders, getHost, prepareAndSendRequest, processResponse, stripHTTPPath, toMultiaddrs, toResource } from './utils.js' import { WebSocket as WebSocketClass } from './websocket/websocket.js' -import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, HTTPRequestHandler, ProtocolMap, RequestHandlerOptions, FetchInit, RequestProcessor } from './index.js' +import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, HTTPRequestHandler, ProtocolMap, RequestHandlerOptions, FetchInit, RequestMiddleware, RequestOptions } from './index.js' import type { ComponentLogger, Logger, PeerId, PrivateKey, Startable } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -21,13 +21,13 @@ export class HTTP implements HTTPInterface, Startable { private readonly log: Logger protected readonly components: HTTPComponents private readonly httpRegistrar: HTTPRegistrar - private readonly processors: RequestProcessor[] + private readonly middleware: RequestMiddleware[] constructor (components: HTTPComponents, init: HTTPInit = {}) { this.components = components this.log = components.logger.forComponent('libp2p:http') this.httpRegistrar = new HTTPRegistrar(components, init) - this.processors = [ + this.middleware = [ new Cookies(components, init) ] } @@ -41,14 +41,14 @@ export class HTTP implements HTTPInterface, Startable { async start (): Promise { await start( this.httpRegistrar, - ...this.processors + ...this.middleware ) } async stop (): Promise { await stop( this.httpRegistrar, - ...this.processors + ...this.middleware ) } @@ -70,24 +70,41 @@ export class HTTP implements HTTPInterface, Startable { return socket } + const opts: RequestOptions = { + ...init, + headers: getHeaders(init), + method: 'GET', + signal: init.signal ?? undefined, + middleware: init.middleware?.map(fn => fn(this.components)) ?? this.middleware, + ignoreCookies: init.ignoreCookies ?? false + } + // strip http-path tuple but record the value if set const { addresses, httpPath } = stripHTTPPath(url) - return new WebSocketClass(addresses, new URL(`http://${getHost(url, init)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, { - ...init, - protocols, - isClient: true + return new WebSocketClass(addresses, new URL(`http://${getHost(url, opts.headers)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, { + ...opts, + protocols }) } async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: FetchInit = {}): Promise { const url = toResource(resource) - const response = await prepareAndSendRequest(url, init, init.processors ?? this.processors, async () => { + const opts: RequestOptions = { + ...init, + headers: getHeaders(init), + method: 'GET', + signal: init.signal ?? undefined, + middleware: init.middleware?.map(fn => fn(this.components)) ?? this.middleware, + ignoreCookies: init.ignoreCookies ?? false + } + + const response = await prepareAndSendRequest(url, opts, async () => { return this.sendRequest(url, init) }) - return processResponse(url, init, init.processors ?? this.processors, response) + return processResponse(url, opts, response) } async getSupportedProtocols (peer: PeerId | Multiaddr | Multiaddr[]): Promise { @@ -145,7 +162,7 @@ export class HTTP implements HTTPInterface, Startable { return globalThis.fetch(resource, init) } - const host = getHost(resource, init) + const host = getHost(resource, getHeaders(init)) // strip http-path tuple but record the value if set const { addresses, httpPath } = stripHTTPPath(resource) @@ -164,12 +181,12 @@ export class HTTP implements HTTPInterface, Startable { } } -export function toURL (resource: URL | Multiaddr[], init: FetchInit): URL { +export function toURL (resource: URL | Multiaddr[], headers: Headers): URL { if (resource instanceof URL) { return resource } - const host = getHost(resource, init) + const host = getHost(resource, headers) const { httpPath } = stripHTTPPath(resource) return new URL(`http://${host}${httpPath}`) diff --git a/src/http/server-response.ts b/src/http/server-response.ts index 8d9fe8e..782c1e8 100644 --- a/src/http/server-response.ts +++ b/src/http/server-response.ts @@ -1,76 +1,11 @@ import { Writable } from 'node:stream' import { InvalidParametersError } from '@libp2p/interface' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' +import { STATUS_CODES } from '../constants.js' import type { IncomingMessage } from './incoming-message.js' import type { OutgoingHttpHeader, OutgoingHttpHeaders } from 'node:http' import type { Socket } from 'node:net' -const STATUS_CODES: Record = { - 100: 'Continue', // RFC 7231 6.2.1 - 101: 'Switching Protocols', // RFC 7231 6.2.2 - 102: 'Processing', // RFC 2518 10.1 (obsoleted by RFC 4918) - 103: 'Early Hints', // RFC 8297 2 - 200: 'OK', // RFC 7231 6.3.1 - 201: 'Created', // RFC 7231 6.3.2 - 202: 'Accepted', // RFC 7231 6.3.3 - 203: 'Non-Authoritative Information', // RFC 7231 6.3.4 - 204: 'No Content', // RFC 7231 6.3.5 - 205: 'Reset Content', // RFC 7231 6.3.6 - 206: 'Partial Content', // RFC 7233 4.1 - 207: 'Multi-Status', // RFC 4918 11.1 - 208: 'Already Reported', // RFC 5842 7.1 - 226: 'IM Used', // RFC 3229 10.4.1 - 300: 'Multiple Choices', // RFC 7231 6.4.1 - 301: 'Moved Permanently', // RFC 7231 6.4.2 - 302: 'Found', // RFC 7231 6.4.3 - 303: 'See Other', // RFC 7231 6.4.4 - 304: 'Not Modified', // RFC 7232 4.1 - 305: 'Use Proxy', // RFC 7231 6.4.5 - 307: 'Temporary Redirect', // RFC 7231 6.4.7 - 308: 'Permanent Redirect', // RFC 7238 3 - 400: 'Bad Request', // RFC 7231 6.5.1 - 401: 'Unauthorized', // RFC 7235 3.1 - 402: 'Payment Required', // RFC 7231 6.5.2 - 403: 'Forbidden', // RFC 7231 6.5.3 - 404: 'Not Found', // RFC 7231 6.5.4 - 405: 'Method Not Allowed', // RFC 7231 6.5.5 - 406: 'Not Acceptable', // RFC 7231 6.5.6 - 407: 'Proxy Authentication Required', // RFC 7235 3.2 - 408: 'Request Timeout', // RFC 7231 6.5.7 - 409: 'Conflict', // RFC 7231 6.5.8 - 410: 'Gone', // RFC 7231 6.5.9 - 411: 'Length Required', // RFC 7231 6.5.10 - 412: 'Precondition Failed', // RFC 7232 4.2 - 413: 'Payload Too Large', // RFC 7231 6.5.11 - 414: 'URI Too Long', // RFC 7231 6.5.12 - 415: 'Unsupported Media Type', // RFC 7231 6.5.13 - 416: 'Range Not Satisfiable', // RFC 7233 4.4 - 417: 'Expectation Failed', // RFC 7231 6.5.14 - 418: 'I\'m a Teapot', // RFC 7168 2.3.3 - 421: 'Misdirected Request', // RFC 7540 9.1.2 - 422: 'Unprocessable Entity', // RFC 4918 11.2 - 423: 'Locked', // RFC 4918 11.3 - 424: 'Failed Dependency', // RFC 4918 11.4 - 425: 'Too Early', // RFC 8470 5.2 - 426: 'Upgrade Required', // RFC 2817 and RFC 7231 6.5.15 - 428: 'Precondition Required', // RFC 6585 3 - 429: 'Too Many Requests', // RFC 6585 4 - 431: 'Request Header Fields Too Large', // RFC 6585 5 - 451: 'Unavailable For Legal Reasons', // RFC 7725 3 - 500: 'Internal Server Error', // RFC 7231 6.6.1 - 501: 'Not Implemented', // RFC 7231 6.6.2 - 502: 'Bad Gateway', // RFC 7231 6.6.3 - 503: 'Service Unavailable', // RFC 7231 6.6.4 - 504: 'Gateway Timeout', // RFC 7231 6.6.5 - 505: 'HTTP Version Not Supported', // RFC 7231 6.6.6 - 506: 'Variant Also Negotiates', // RFC 2295 8.1 - 507: 'Insufficient Storage', // RFC 4918 11.5 - 508: 'Loop Detected', // RFC 5842 7.2 - 509: 'Bandwidth Limit Exceeded', - 510: 'Not Extended', // RFC 2774 7 - 511: 'Network Authentication Required' // RFC 6585 6 -} - export class ServerResponse extends Writable { public req: Request public chunkedEncoding: boolean diff --git a/src/index.ts b/src/index.ts index 737c8d2..2291016 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,11 +13,9 @@ * * It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s * and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s - * (based on the [ws](https://www.npmjs.com/package/ws) module API in the - * absence of a native Node.js API to emulate) in browsers to truly realize the - * power of the distributed web. + * in browsers to truly realize the power of the distributed web. * - * Instead of the regular "host:port" addressing, it uses a libp2p PeerId and/or + * In addition to URL-based addressing, it can use a libp2p PeerId and/or * multiaddr(s) and lets libp2p take care of the routing, thus taking advantage * of features like multi-routes, NAT transversal and stream multiplexing over a * single connection. @@ -371,7 +369,7 @@ export interface WebSocketInit extends AbortOptions { * A list of request processors that can augment requests - if specified will * override any processors passed to the `http` service */ - processors?: RequestProcessor[] + middleware?: Array<(components: any) => RequestMiddleware> /** * If true, cookies will not be used for this request @@ -386,7 +384,7 @@ export interface FetchInit extends RequestInit { * A list of request processors that can augment requests - if specified will * override any processors passed to the `http` service */ - processors?: RequestProcessor[] + middleware?: Array<(components: any) => RequestMiddleware> /** * If true, cookies will not be used for this request @@ -558,14 +556,28 @@ export interface Endpoint { inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise } +export interface RequestOptions extends AbortOptions { + method: string + headers: Headers + middleware: RequestMiddleware[] + ignoreCookies: boolean +} + /** * Request/response middleware that allows augmenting the request/response with * additional fields or headers. */ -export interface RequestProcessor { - prepareRequest?(resource: URL | Multiaddr[], init: FetchInit): void | Promise +export interface RequestMiddleware { + /** + * Called before a request is made + */ + prepareRequest?(resource: URL | Multiaddr[], opts: RequestOptions): void | Promise - processResponse?(resource: URL | Multiaddr[], init: FetchInit, response: Response): void | Promise + /** + * Called after a request is made but before the body has been read - the + * processor may do any necessary housekeeping based on the server response + */ + processResponse?(resource: URL | Multiaddr[], opts: RequestOptions, response: Response): void | Promise } /** @@ -589,9 +601,10 @@ export interface HTTPInit { authTokenTTL?: number /** - * A list of request processors that can augment requests + * A list of request processors that can augment requests. Middleware passed + * here will be invoked on every request. */ - processors?: RequestProcessor[] + middleware?: Array<(components: any) => RequestMiddleware> /** * How often to evict stale cookies from the cache in ms. diff --git a/src/peer-id-auth.ts b/src/peer-id-auth.ts index d24ba7e..8c62af9 100644 --- a/src/peer-id-auth.ts +++ b/src/peer-id-auth.ts @@ -5,8 +5,8 @@ import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } fr import { parseHeader, sign, verify } from './auth/common.js' import { InvalidPeerError, InvalidSignatureError, MissingAuthHeaderError } from './auth/errors.js' import { DEFAULT_AUTH_TOKEN_TTL, PEER_ID_AUTH_SCHEME } from './constants.js' -import { getCacheKey, getHeaders, getHost } from './utils.js' -import type { FetchInit, HTTP, RequestProcessor } from './index.js' +import { getCacheKey, getHost } from './utils.js' +import type { HTTP, RequestMiddleware, RequestOptions } from './index.js' import type { AbortOptions, ComponentLogger, Logger, PeerId, PrivateKey } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -27,7 +27,7 @@ interface PeerIdAuthInit { ttl?: number } -class PeerIdAuth implements RequestProcessor { +class PeerIdAuth implements RequestMiddleware { private readonly components: PeerIdAuthComponents private readonly log: Logger private readonly tokens: Map @@ -42,19 +42,24 @@ class PeerIdAuth implements RequestProcessor { this.verifyPeer = init.verifyPeer ?? (() => true) } - async prepareRequest (resource: URL | Multiaddr[], init: FetchInit): Promise { - const headers = getHeaders(init) + async prepareRequest (resource: URL | Multiaddr[], opts: RequestOptions): Promise { + const existingAuthHeader = opts.headers.get('authorization') + + if (existingAuthHeader != null) { + if (existingAuthHeader.includes('challenge-server')) { + // we are already authenticating this request + return + } - if (headers.get('authorization') != null) { throw new InvalidParametersError('Will not overwrite existing Authorization header') } - const token = await this.getOrCreateAuthToken(resource, init) - headers.set('Authorization', token.bearer) + const token = await this.getOrCreateAuthToken(resource, opts) + opts.headers.set('Authorization', token.bearer) } - async getOrCreateAuthToken (resource: URL | Multiaddr[], init: FetchInit): Promise { - const key = getCacheKey(resource, init) + async getOrCreateAuthToken (resource: URL | Multiaddr[], opts: RequestOptions): Promise { + const key = getCacheKey(resource, opts.headers) let token = this.tokens.get(key) // check token expiry @@ -65,15 +70,14 @@ class PeerIdAuth implements RequestProcessor { // create new token if (token == null) { - token = await this.createAuthToken(resource, init) + token = await this.createAuthToken(resource, opts) } return token } - async createAuthToken (resource: URL | Multiaddr[], init: FetchInit): Promise { - const hostname = getHost(resource, init) - const headers = getHeaders(init) + async createAuthToken (resource: URL | Multiaddr[], opts: RequestOptions): Promise { + const hostname = getHost(resource, opts.headers) // Client initiated handshake (server initiated is not implemented yet) const marshalledClientPubKey = publicKeyToProtobuf(this.components.privateKey.publicKey) @@ -81,7 +85,7 @@ class PeerIdAuth implements RequestProcessor { const challengeServer = generateChallenge() // copy existing headers - const challengeHeaders = new Headers(headers) + const challengeHeaders = new Headers(opts.headers) challengeHeaders.set('authorization', encodeAuthParams({ 'challenge-server': challengeServer, 'public-key': publicKeyStr @@ -90,15 +94,17 @@ class PeerIdAuth implements RequestProcessor { const resp = await this.components.http.fetch(resource, { method: 'OPTIONS', headers: challengeHeaders, - signal: init.signal, - processors: init.processors?.filter(proc => proc !== this) ?? undefined + signal: opts.signal, + middleware: opts.middleware.map(m => () => m) }) // verify the server's challenge const authHeader = resp.headers.get('www-authenticate') + if (authHeader == null) { throw new MissingAuthHeaderError('No auth header') } + const authFields = parseHeader(authHeader) const serverPubKeyBytes = uint8ArrayFromString(authFields['public-key'], 'base64urlpad') const serverPubKey = publicKeyFromProtobuf(serverPubKeyBytes) @@ -115,7 +121,7 @@ class PeerIdAuth implements RequestProcessor { const serverPublicKey = publicKeyFromProtobuf(serverPubKeyBytes) const serverID = peerIdFromPublicKey(serverPublicKey) - if (!await this.verifyPeer(serverID, { signal: init.signal ?? undefined })) { + if (!await this.verifyPeer(serverID, { signal: opts.signal })) { throw new InvalidPeerError('Id check failed') } @@ -135,17 +141,17 @@ class PeerIdAuth implements RequestProcessor { bearer: authenticateSelfHeaders } - const key = getCacheKey(resource, init) + const key = getCacheKey(resource, opts.headers) this.tokens.set(key, authToken) return authToken } - processResponse (resource: URL | Multiaddr[], init: FetchInit, response: Response): void { - const serverAuthHeader = response.headers.get('Authentication-Info') + processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): void { + const serverAuthHeader = response.headers.get('authentication-info') if (serverAuthHeader != null) { - const key = getCacheKey(resource, init) + const key = getCacheKey(resource, opts.headers) const token = this.tokens.get(key) if (token != null) { @@ -156,7 +162,7 @@ class PeerIdAuth implements RequestProcessor { } } -export function peerIdAuth (init: PeerIdAuthInit = {}): (components: PeerIdAuthComponents) => RequestProcessor { +export function peerIdAuth (init: PeerIdAuthInit = {}): (components: PeerIdAuthComponents) => RequestMiddleware { return (components) => { return new PeerIdAuth(components, init) } diff --git a/src/utils.ts b/src/utils.ts index 6a54da2..8d7f72e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -8,7 +8,7 @@ import itToBrowserReadableStream from 'it-to-browser-readablestream' import { base36 } from 'multiformats/bases/base36' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { DNS_CODECS, HTTP_CODEC, HTTP_PATH_CODEC } from './constants.js' -import type { FetchInit, HeaderInfo, RequestProcessor } from './index.js' +import type { HeaderInfo, RequestOptions } from './index.js' import type { PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Readable } from 'node:stream' @@ -285,7 +285,7 @@ function isValidHost (host?: string): host is string { return host != null && host !== '' } -export function getHost (addresses: URL | Multiaddr[], init: RequestInit): string { +export function getHost (addresses: URL | Multiaddr[], headers: Headers): string { let host: string | undefined if (addresses instanceof URL) { @@ -293,7 +293,6 @@ export function getHost (addresses: URL | Multiaddr[], init: RequestInit): strin } if (!isValidHost(host)) { - const headers = getHeaders(init) host = headers.get('host') ?? undefined } @@ -331,7 +330,7 @@ export function getHost (addresses: URL | Multiaddr[], init: RequestInit): strin throw new InvalidParametersError('Could not determine request host name - a request must have a host header, be made to a DNS-based multiaddr or an http(s) URL') } -export function getCacheKey (resource: URL | Multiaddr[], init: RequestInit): string { +export function getCacheKey (resource: URL | Multiaddr[], headers: Headers): string { let prefix = '' if (Array.isArray(resource)) { @@ -344,20 +343,20 @@ export function getCacheKey (resource: URL | Multiaddr[], init: RequestInit): st } } - return `${prefix}${getHost(resource, init)}` + return `${prefix}${getHost(resource, headers)}` } -export async function prepareAndSendRequest (resource: URL | Multiaddr[], init: RequestInit, processors: RequestProcessor[], sendRequest: (resource: URL | Multiaddr[], init: FetchInit) => Promise): Promise { - for (const processor of processors) { - await processor.prepareRequest?.(resource, init) +export async function prepareAndSendRequest (resource: URL | Multiaddr[], opts: RequestOptions, sendRequest: () => Promise): Promise { + for (const middleware of opts.middleware) { + await middleware.prepareRequest?.(resource, opts) } - return sendRequest(resource, init) + return sendRequest() } -export async function processResponse (resource: URL | Multiaddr[], init: RequestInit, processors: RequestProcessor[], response: Response): Promise { - for (const proc of processors) { - await proc.processResponse?.(resource, init, response) +export async function processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): Promise { + for (const middleware of opts.middleware) { + await middleware.processResponse?.(resource, opts, response) } return response diff --git a/src/websocket/index.ts b/src/websocket/index.ts index 16a5b41..1b01780 100644 --- a/src/websocket/index.ts +++ b/src/websocket/index.ts @@ -75,7 +75,7 @@ export interface WebSocketServer extends TypedEventTarget * @example * * ```ts - * import { createServer, createWebSocketServer } from '@ipshipyard/libp2p-http' + * import { createServer, createWebSocketServer } from '@libp2p/http' * * const wss = createWebSocketServer() * wss.addEventListener('connection', (evt) => { @@ -91,9 +91,7 @@ export interface WebSocketServer extends TypedEventTarget * }) * * server.addListener('upgrade', (request, socket, head) => { - * wss.handleUpgrade(request, socket, head, (ws) => { - * wss.emit('connection', ws, request) - * }) + * wss.handleUpgrade(request, socket, head) * }) * `` */ diff --git a/src/websocket/server.ts b/src/websocket/server.ts index 0d511b0..6c4cb11 100644 --- a/src/websocket/server.ts +++ b/src/websocket/server.ts @@ -2,7 +2,8 @@ import { TypedEventEmitter } from '@libp2p/interface' import { raceEvent } from 'race-event' import { INTERNAL_SERVER_ERROR } from '../utils.js' import { ServerWebSocket } from './websocket.js' -import { ConnectionEvent, type WebSocketServerEvents } from './index.js' +import { ConnectionEvent } from './index.js' +import type { WebSocketServerEvents } from './index.js' import type { IncomingMessage } from '../http/incoming-message.js' import type { Duplex } from 'node:stream' diff --git a/src/websocket/utils.ts b/src/websocket/utils.ts index b3cad7e..753cac7 100644 --- a/src/websocket/utils.ts +++ b/src/websocket/utils.ts @@ -3,6 +3,7 @@ import { InvalidParametersError, ProtocolError } from '@libp2p/interface' import { base64pad } from 'multiformats/bases/base64' import { sha1 } from 'multiformats/hashes/sha1' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { Response } from '../fetch/response.js' import { BAD_REQUEST, toUint8Array, writeHeaders } from '../utils.js' import { StreamWebSocket } from './websocket.js' import type { HeaderInfo } from '../index.js' @@ -35,12 +36,6 @@ export class CodeError extends Error { } } -export interface Response { - status: number - statusText: string - headers: Headers -} - export async function readResponse (bytes: ByteStream, options: AbortOptions): Promise { return new Promise((resolve, reject) => { let readHeaders = false @@ -55,11 +50,11 @@ export async function readResponse (bytes: ByteStream, options: AbortOptions): P headers.push([info.headers[i], info.headers[i + 1]]) } - resolve({ + resolve(new Response(null, { status: info.statusCode, statusText: info.statusMessage, headers: new Headers(headers) - }) + })) } Promise.resolve() diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts index 3de15d4..d8dd2a6 100644 --- a/src/websocket/websocket.ts +++ b/src/websocket/websocket.ts @@ -9,8 +9,8 @@ import { encodeMessage, decodeMessage, CLOSE_MESSAGES } from './message.js' import { performClientUpgrade, performServerUpgrade, readResponse, toBytes } from './utils.js' import type { CloseListener, ErrorListener, MessageListener, OpenListener, WebSocketEvents } from './index.js' import type { MESSAGE_TYPE } from './message.js' -import type { HeaderInfo, WebSocketInit } from '../index.js' -import type { Stream } from '@libp2p/interface' +import type { HeaderInfo, RequestMiddleware, RequestOptions } from '../index.js' +import type { AbortOptions, Stream } from '@libp2p/interface' import type { ConnectionManager } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' import type { IncomingMessage } from 'node:http' @@ -20,9 +20,12 @@ const DATA_MESSAGES: MESSAGE_TYPE[] = ['BINARY', 'TEXT', 'CONTINUATION'] const MAX_MESSAGE_SIZE = 10_485_760 const DEFAULT_HOST = 'example.com' -export interface AbstractWebSocketInit extends WebSocketInit { +export interface AbstractWebSocketInit extends AbortOptions { protocols?: string[] isClient?: boolean + maxMessageSize?: number + headers?: HeadersInit + ignoreCookies?: boolean } export abstract class AbstractWebSocket extends TypedEventEmitter { @@ -396,10 +399,15 @@ export class RequestWebSocket extends AbstractWebSocket { } } +export interface WebSocketInit extends RequestOptions { + middleware: RequestMiddleware[] + protocols?: string[] +} + export class WebSocket extends AbstractWebSocket { private bytes?: ByteStream - constructor (mas: Multiaddr[], url: URL, connectionManager: ConnectionManager, init: AbstractWebSocketInit = {}) { + constructor (mas: Multiaddr[], url: URL, connectionManager: ConnectionManager, init: WebSocketInit) { super(url, { ...init, isClient: true @@ -411,6 +419,10 @@ export class WebSocket extends AbstractWebSocket { const stream = await connection.newStream(PROTOCOL, init) this.bytes = byteStream(stream) + for (const middleware of init.middleware) { + await middleware.prepareRequest?.(mas, init) + } + for await (const buf of performClientUpgrade(url, init.protocols, getHeaders(init))) { await this.bytes.write(buf) } @@ -421,6 +433,10 @@ export class WebSocket extends AbstractWebSocket { throw new Error('Invalid WebSocket handshake') } + for (const middleware of init.middleware) { + await middleware.processResponse?.(mas, init, res) + } + // if a protocol was selected by the server, expose it this.protocol = res.headers.get('Sec-WebSocket-Protocol') ?? '' diff --git a/test/fixtures/create-fastify-http.ts b/test/fixtures/create-fastify-http.ts index 56144c1..b2b42e3 100644 --- a/test/fixtures/create-fastify-http.ts +++ b/test/fixtures/create-fastify-http.ts @@ -47,13 +47,13 @@ export async function createFastifyHTTP (server: Server, handler?: Libp2pOverHTT }) }) app.get('/set-cookies', async (req, res) => { + res.statusCode = 201 await res.setCookie('cookie-1', 'value-1', { domain: req.headers.host, maxAge: 3600 }) - await res.setCookie('cookie-2', 'value-2') - res.statusCode = 201 - await res.send() + .setCookie('cookie-2', 'value-2') + .send() }) app.get('/get-cookies', async (req, res) => { await res.send(JSON.stringify(Object.entries(req.cookies).map(([key, value]) => `${key}=${value}`))) diff --git a/test/peer-id-auth.spec.ts b/test/peer-id-auth.spec.ts new file mode 100644 index 0000000..6ee3896 --- /dev/null +++ b/test/peer-id-auth.spec.ts @@ -0,0 +1,132 @@ +import { stop } from '@libp2p/interface' +import { expect } from 'aegir/chai' +import { createServer } from '../src/http/index.js' +import { peerIdAuth } from '../src/peer-id-auth.js' +import { nodeServer } from '../src/servers/node.js' +import { createHttp } from './fixtures/create-http.js' +import { getClient, getListener } from './fixtures/get-libp2p.js' +import type { HTTP } from '../src/index.js' +import type { Multiaddr } from '@multiformats/multiaddr' +import type { Libp2p } from 'libp2p' + +interface Test { + name: string + startServer(): Promise + stopServer(): Promise +} + +let listener: Libp2p<{ http: HTTP }> + +const tests: Test[] = [{ + name: 'in-process server', + startServer: async () => { + const server = createHttp(createServer()) + listener = await getListener(nodeServer(server)) + + return listener.getMultiaddrs() + }, + stopServer: async () => { + await stop(listener) + } +}/*, { + name: 'js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_HTTP_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_HTTP_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'express/js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_EXPRESS_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'express/node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_EXPRESS_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'fastify/js', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_JS_FASTIFY_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +}, { + name: 'fastify/node:http', + startServer: async () => { + return [ + multiaddr(process.env.LIBP2P_NODE_FASTIFY_MULTIADDR ?? '') + ] + }, + stopServer: async () => { + + } +} */] + +for (const test of tests) { + describe.skip(`peer id auth - ${test.name}`, () => { + let client: Libp2p<{ http: HTTP }> + let listenerMultiaddrs: Multiaddr[] + + beforeEach(async () => { + client = await getClient() + listenerMultiaddrs = await test.startServer() + }) + + afterEach(async () => { + await stop(client) + await test.stopServer() + }) + + it('should support peer id auth', async () => { + const setResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/set-cookies')), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(setResponse.status).to.equal(201) + expect(setResponse.headers.get('set-cookie')).to.not.be.ok() + + const getResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/get-cookies')), { + headers: { + host: 'test-with-cookies.com' + } + }) + expect(getResponse.status).to.equal(200) + await expect(getResponse.json()).to.eventually.deep.equal([ + 'cookie-1=value-1', + 'cookie-2=value-2' + ]) + }) + }) +} From d5a365c5953ea9f64db9b5e6d04e07bb2f6a12b4 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 23 Apr 2025 18:23:41 +0100 Subject: [PATCH 05/22] chore: auth working --- .aegir.js | 47 +- README.md | 18 +- package.json | 2 + src/auth/common.ts | 2 + src/constants.ts | 1 - src/fetch.ts | 4 +- src/fetch/read-response.ts | 12 +- src/fetch/request.ts | 31 + src/http.browser.ts | 81 +-- src/index.ts | 99 +-- src/{ => middleware}/cookies.ts | 8 +- src/{ => middleware}/peer-id-auth.ts | 56 +- src/ping/index.ts | 15 +- src/ping/ping.ts | 43 +- src/registrar.ts | 126 ++-- src/routes/index.ts | 86 +++ src/routes/peer-id-auth.ts | 578 ++++++++++++++++++ src/routes/websocket.ts | 82 +++ src/routes/well-known.ts | 28 + src/servers/node.ts | 76 ++- src/utils.ts | 98 ++- src/websocket-handler.ts | 68 --- src/websocket/events.ts | 22 + src/websocket/websocket.ts | 34 +- src/well-known-handler.ts | 22 - test/cookies.spec.ts | 4 +- test/fetch.spec.ts | 4 +- test/fixtures/create-express.ts | 14 +- test/fixtures/create-fastify-http.ts | 14 +- test/fixtures/create-fastify-websocket.ts | 16 +- test/fixtures/create-http.ts | 13 +- test/fixtures/create-websocket-server.ts | 12 +- test/fixtures/create-wss.ts | 12 +- test/fixtures/get-libp2p-over-http-handler.ts | 73 --- test/fixtures/get-libp2p.ts | 107 +++- test/fixtures/to-websocket.ts | 8 +- test/peer-id-auth.spec.ts | 164 ++++- test/ping.spec.ts | 163 ++--- test/websockets.spec.ts | 36 +- 39 files changed, 1706 insertions(+), 573 deletions(-) create mode 100644 src/fetch/request.ts rename src/{ => middleware}/cookies.ts (93%) rename src/{ => middleware}/peer-id-auth.ts (82%) create mode 100644 src/routes/index.ts create mode 100644 src/routes/peer-id-auth.ts create mode 100644 src/routes/websocket.ts create mode 100644 src/routes/well-known.ts delete mode 100644 src/websocket-handler.ts delete mode 100644 src/well-known-handler.ts delete mode 100644 test/fixtures/get-libp2p-over-http-handler.ts diff --git a/.aegir.js b/.aegir.js index cfd5ccc..0f5505c 100644 --- a/.aegir.js +++ b/.aegir.js @@ -38,38 +38,45 @@ export default { test: { before: async () => { const { createServer } = await import('./dist/src/http/index.js') - const { nodeServer } = await import('./dist/src/servers/node.js') - const { getListener } = await import('./dist/test/fixtures/get-libp2p.js') + const { nodeServer, canHandle } = await import('./dist/src/servers/node.js') + const { getHTTPOverLibp2pHandler } = await import('./dist/test/fixtures/get-libp2p.js') const { createHttp } = await import('./dist/test/fixtures/create-http.js') const { createFastifyHTTP } = await import('./dist/test/fixtures/create-fastify-http.js') const { createExpress } = await import('./dist/test/fixtures/create-express.js') const { createWss } = await import('./dist/test/fixtures/create-wss.js') const { createFastifyWebSocket } = await import('./dist/test/fixtures/create-fastify-websocket.js') - const { getLibp2pOverHttpHandler } = await import('./dist/test/fixtures/get-libp2p-over-http-handler.js') + const { getLibp2pOverHttpHandler } = await import('./dist/test/fixtures/get-libp2p.js') // --- http-over-libp2p - const jsHttpListener = await getListener(nodeServer(createHttp(createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const nodeHttpListener = await getListener(nodeServer(createHttp(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const jsExpressListener = await getListener(nodeServer(createExpress(createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const nodeHttpExpressListener = await getListener(nodeServer(createExpress(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const jsFastifyListener = await getListener(nodeServer(await createFastifyHTTP(createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const nodeHttpFastifyListener = await getListener(nodeServer(await createFastifyHTTP(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + // these are libp2p nodes that we pass an HTTP server to - eg. in the + // tests we open a libp2p stream to these nodes and send an HTTP request, + // the node hands the request off to the HTTP server for processing + const jsHttpListener = await getHTTPOverLibp2pHandler(nodeServer(createHttp(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpListener = await getHTTPOverLibp2pHandler(nodeServer(createHttp(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const jsExpressListener = await getHTTPOverLibp2pHandler(nodeServer(createExpress(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpExpressListener = await getHTTPOverLibp2pHandler(nodeServer(createExpress(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const jsFastifyListener = await getHTTPOverLibp2pHandler(nodeServer(await createFastifyHTTP(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpFastifyListener = await getHTTPOverLibp2pHandler(nodeServer(await createFastifyHTTP(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') // --- ws-over-libp2p - const jsWssListener = await getListener(nodeServer(createWss(createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const nodeHttpWssListener = await getListener(nodeServer(createWss(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const jsFastifyWsListener = await getListener(nodeServer(await createFastifyWebSocket(createServer())), '/ip4/0.0.0.0/tcp/0/ws') - const nodeHttpFastifyWsListener = await getListener(nodeServer(await createFastifyWebSocket(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + // as above but with WebSocket servers instead of HTTP + const jsWssListener = await getHTTPOverLibp2pHandler(nodeServer(createWss(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpWssListener = await getHTTPOverLibp2pHandler(nodeServer(createWss(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const jsFastifyWsListener = await getHTTPOverLibp2pHandler(nodeServer(await createFastifyWebSocket(createServer())), '/ip4/0.0.0.0/tcp/0/ws') + const nodeHttpFastifyWsListener = await getHTTPOverLibp2pHandler(nodeServer(await createFastifyWebSocket(http.createServer())), '/ip4/0.0.0.0/tcp/0/ws') // --- libp2p-over-http + // these are HTTP servers that accept HTTP requests and can hand them off + // to libp2p for processing const libp2pOverHttpHandler = await getLibp2pOverHttpHandler() - const express = createExpress(http.createServer(), libp2pOverHttpHandler.handler) - const nodeHttp = createHttp(http.createServer(), libp2pOverHttpHandler.handler) - const fastify = await createFastifyHTTP(http.createServer(), libp2pOverHttpHandler.handler) + const express = createExpress(http.createServer(), canHandle(libp2pOverHttpHandler)) + const nodeHttp = createHttp(http.createServer(), canHandle(libp2pOverHttpHandler)) + const fastify = await createFastifyHTTP(http.createServer(), canHandle(libp2pOverHttpHandler)) // --- libp2p-over-ws - const wss = createWss(http.createServer(), libp2pOverHttpHandler.handler) - const fastifyWs = await createFastifyWebSocket(http.createServer(), libp2pOverHttpHandler.handler) + // as above but with WebSocket servers instead of HTTP + const wss = createWss(http.createServer(), canHandle(libp2pOverHttpHandler)) + const fastifyWs = await createFastifyWebSocket(http.createServer(), canHandle(libp2pOverHttpHandler)) return { // http-over-libp2p @@ -87,7 +94,7 @@ export default { nodeHttpFastifyWsListener, // libp2p-over-http - libp2pOverHttpHandler: libp2pOverHttpHandler.libp2p, + libp2pOverHttpHandler, nodeHttp: stoppableServer(nodeHttp), express: stoppableServer(express), fastify: stoppableServer(fastify), @@ -112,7 +119,7 @@ export default { LIBP2P_NODE_FASTIFY_WS_MULTIADDR: nodeHttpFastifyWsListener.getMultiaddrs()[0], // libp2p-over-http - HTTP_PEER_ID: `${libp2pOverHttpHandler.libp2p.peerId}`, + HTTP_PEER_ID: `${libp2pOverHttpHandler.peerId}`, HTTP_NODE_HTTP_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(nodeHttp)}/http`, HTTP_EXPRESS_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(express)}/http`, HTTP_FASTIFY_MULTIADDR: `/ip4/127.0.0.1/tcp/${await startHTTPServer(fastify)}/http`, diff --git a/README.md b/README.md index b6d358d..261d0d1 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -# @libp2p/http-fetch +# @libp2p/http [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) -[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http-fetch.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http-fetch) -[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http-fetch/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http-fetch/actions/workflows/js-test-and-release.yml?query=branch%3Amain) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) > Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP @@ -46,27 +46,27 @@ single connection. # Install ```console -$ npm i @libp2p/http-fetch +$ npm i @libp2p/http ``` ## Browser ` + ``` # API Docs -- +- # License Licensed under either of -- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http-fetch/LICENSE-APACHE) / ) -- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http-fetch/LICENSE-MIT) / ) +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) # Contribution diff --git a/package.json b/package.json index 767b0f3..6307660 100644 --- a/package.json +++ b/package.json @@ -208,6 +208,8 @@ "fastify": "^5.2.2", "it-pair": "^2.0.6", "libp2p": "^2.2.1", + "p-event": "^6.0.1", + "sinon": "^20.0.0", "wherearewe": "^2.0.1", "ws": "^8.18.1" }, diff --git a/src/auth/common.ts b/src/auth/common.ts index 1396b33..a2637ee 100644 --- a/src/auth/common.ts +++ b/src/auth/common.ts @@ -68,9 +68,11 @@ export function parseHeader (headerVal: string): Record { const rest = headerVal.substring(PeerIDAuthScheme.length).trim() const params: Record = {} const regex = /(\w[^=]+)="([^"]+)"/g + let match while ((match = regex.exec(rest)) !== null) { params[match[1]] = match[2] } + return params } diff --git a/src/constants.ts b/src/constants.ts index 18cc364..5db034d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,4 @@ export const PROTOCOL = '/http/1.1' -export const WELL_KNOWN_PROTOCOLS = '/.well-known/libp2p/protocols' export const WEBSOCKET_HANDLER = Symbol.for('@libp2p/http/websocket-handler') export const PEER_ID_AUTH_SCHEME = 'libp2p-PeerID' export const HTTP_PEER_ID_AUTH_PROTO = '/http-peer-id-auth/1.0.0' diff --git a/src/fetch.ts b/src/fetch.ts index 040b6a0..3204c3e 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -71,7 +71,9 @@ export function fetchViaDuplex (s: Duplex): Fetch { /** * A function that can be used to handle HTTP requests */ -export interface HTTPHandler { (req: Request): Promise } +export interface HTTPHandler { + (req: Request): Promise +} /** * diff --git a/src/fetch/read-response.ts b/src/fetch/read-response.ts index 9bdd1cf..f3f406e 100644 --- a/src/fetch/read-response.ts +++ b/src/fetch/read-response.ts @@ -4,6 +4,8 @@ import type { SendRequestInit } from './index.js' import type { Stream } from '@libp2p/interface' import type { ByteStream } from 'it-byte-stream' +const nullBodyStatus = [101, 204, 205, 304] + export async function readResponse (bytes: ByteStream, resource: URL, init: SendRequestInit): Promise { return new Promise((resolve, reject) => { const body = new TransformStream() @@ -21,7 +23,15 @@ export async function readResponse (bytes: ByteStream, resource: URL, in headers.append(info.headers[i], info.headers[i + 1]) } - const response = new Response(body.readable, { + let responseBody: BodyInit | null = body.readable + + if (nullBodyStatus.includes(info.statusCode)) { + body.writable.close().catch(() => {}) + body.readable.cancel().catch(() => {}) + responseBody = null + } + + const response = new Response(responseBody, { status: info.statusCode, statusText: info.statusMessage, headers diff --git a/src/fetch/request.ts b/src/fetch/request.ts new file mode 100644 index 0000000..f921eca --- /dev/null +++ b/src/fetch/request.ts @@ -0,0 +1,31 @@ +import { getHeaders, isWebSocketUpgrade } from '../utils.js' + +/** + * Extends the native Request class to be more flexible. + * + * - body - normally GET requests cannot have a body, but if the request is for + * a WebSocket upgrade, we need the body to turn into the socket + * + * - headers - the global browser request removes certain headers like + * Authorization and Sec-WebSocket-Protocol but we need to preserve them + */ +export class Request extends globalThis.Request { + public readonly method: string + public readonly headers: Headers + + constructor (input: RequestInfo | URL, init: RequestInit = {}) { + const headers = getHeaders(init) + const method = init.method ?? 'GET' + + if (isWebSocketUpgrade(method, headers)) { + // temporarily override the method name since undici does not allow GET + // requests with bodies + init.method = 'UPGRADE' + } + + super(input, init) + + this.method = method + this.headers = headers + } +} diff --git a/src/http.browser.ts b/src/http.browser.ts index bc5c053..266c672 100644 --- a/src/http.browser.ts +++ b/src/http.browser.ts @@ -1,11 +1,13 @@ import { UnsupportedOperationError, serviceCapabilities, start, stop } from '@libp2p/interface' -import { PROTOCOL, WELL_KNOWN_PROTOCOLS } from './constants.js' -import { Cookies } from './cookies.js' +import { PROTOCOL } from './constants.js' import { fetch } from './fetch/index.js' +import { Cookies } from './middleware/cookies.js' import { HTTPRegistrar } from './registrar.js' -import { getHeaders, getHost, prepareAndSendRequest, processResponse, stripHTTPPath, toMultiaddrs, toResource } from './utils.js' +import { getHeaders, getHost, prepareAndConnect, prepareAndSendRequest, processResponse, stripHTTPPath, toMultiaddrs, toResource } from './utils.js' import { WebSocket as WebSocketClass } from './websocket/websocket.js' -import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, HTTPRequestHandler, ProtocolMap, RequestHandlerOptions, FetchInit, RequestMiddleware, RequestOptions } from './index.js' +import { WELL_KNOWN_PROTOCOLS_PATH } from './index.js' +import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, ProtocolMap, FetchInit, RequestOptions } from './index.js' +import type { HTTPRoute } from './routes/index.js' import type { ComponentLogger, Logger, PeerId, PrivateKey, Startable } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -21,15 +23,13 @@ export class HTTP implements HTTPInterface, Startable { private readonly log: Logger protected readonly components: HTTPComponents private readonly httpRegistrar: HTTPRegistrar - private readonly middleware: RequestMiddleware[] + private readonly cookies: Cookies constructor (components: HTTPComponents, init: HTTPInit = {}) { this.components = components this.log = components.logger.forComponent('libp2p:http') this.httpRegistrar = new HTTPRegistrar(components, init) - this.middleware = [ - new Cookies(components, init) - ] + this.cookies = new Cookies(components, init) } readonly [Symbol.toStringTag] = '@libp2p/http' @@ -40,15 +40,13 @@ export class HTTP implements HTTPInterface, Startable { async start (): Promise { await start( - this.httpRegistrar, - ...this.middleware + this.httpRegistrar ) } async stop (): Promise { await stop( - this.httpRegistrar, - ...this.middleware + this.httpRegistrar ) } @@ -60,43 +58,52 @@ export class HTTP implements HTTPInterface, Startable { throw new UnsupportedOperationError('This method is not supported in browsers') } - connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init: WebSocketInit = {}): globalThis.WebSocket { + async connect (resource: string | URL | Multiaddr | Multiaddr[], init: WebSocketInit = {}): Promise { const url = toResource(resource) - - if (url instanceof URL) { - const socket = new globalThis.WebSocket(url, protocols) - socket.binaryType = 'arraybuffer' - - return socket - } - + const headers = getHeaders(init) const opts: RequestOptions = { ...init, - headers: getHeaders(init), + headers, method: 'GET', - signal: init.signal ?? undefined, - middleware: init.middleware?.map(fn => fn(this.components)) ?? this.middleware, - ignoreCookies: init.ignoreCookies ?? false + middleware: init.middleware?.map(fn => fn(this.components)) ?? [], + // WebSocket requests are not subject to cross-origin checks so do not use + // cookies as it introduces a security vulnerability + ignoreCookies: true } - // strip http-path tuple but record the value if set - const { addresses, httpPath } = stripHTTPPath(url) + headers.set('connection', 'upgrade') + headers.set('upgrade', 'websocket') + + return prepareAndConnect(url, opts, async () => { + if (url instanceof URL) { + const socket = new globalThis.WebSocket(url, init.protocols) + socket.binaryType = 'arraybuffer' + + return socket + } + + // strip http-path tuple but record the value if set + const { addresses, httpPath } = stripHTTPPath(url) - return new WebSocketClass(addresses, new URL(`http://${getHost(url, opts.headers)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, { - ...opts, - protocols + return new WebSocketClass( + addresses, + new URL(`http://${getHost(url, opts.headers)}${decodeURIComponent(httpPath)}`), + this.components.connectionManager, + opts + ) }) } async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: FetchInit = {}): Promise { const url = toResource(resource) - const opts: RequestOptions = { ...init, headers: getHeaders(init), method: 'GET', - signal: init.signal ?? undefined, - middleware: init.middleware?.map(fn => fn(this.components)) ?? this.middleware, + middleware: [ + this.cookies, + ...init.middleware?.map(fn => fn(this.components)) ?? [] + ], ignoreCookies: init.ignoreCookies ?? false } @@ -108,7 +115,7 @@ export class HTTP implements HTTPInterface, Startable { } async getSupportedProtocols (peer: PeerId | Multiaddr | Multiaddr[]): Promise { - const addresses = toMultiaddrs(peer, `/http-path/${encodeURIComponent(WELL_KNOWN_PROTOCOLS.substring(1))}`) + const addresses = toMultiaddrs(peer, `/http-path/${encodeURIComponent(WELL_KNOWN_PROTOCOLS_PATH.substring(1))}`) const resp = await this.fetch(addresses, { method: 'GET', headers: { @@ -145,8 +152,8 @@ export class HTTP implements HTTPInterface, Startable { this.httpRegistrar.onWebSocket(ws) } - handle (protocol: string, handler: HTTPRequestHandler, options?: RequestHandlerOptions): void { - this.httpRegistrar.handle(protocol, handler, options) + handle (protocol: string, handler: HTTPRoute): void { + this.httpRegistrar.handle(protocol, handler) } unhandle (protocol: string): void { @@ -159,9 +166,11 @@ export class HTTP implements HTTPInterface, Startable { private async sendRequest (resource: Multiaddr[] | URL, init: FetchInit): Promise { if (resource instanceof URL) { + this.log('making request with global fetch') return globalThis.fetch(resource, init) } + this.log('making request with libp2p fetch') const host = getHost(resource, getHeaders(init)) // strip http-path tuple but record the value if set diff --git a/src/index.ts b/src/index.ts index 2291016..012b702 100644 --- a/src/index.ts +++ b/src/index.ts @@ -344,32 +344,25 @@ import { HTTP as HTTPClass } from './http.js' import type { HTTPComponents } from './http.js' +import type { HTTPRoute } from './routes/index.js' import type { AbortOptions, Connection, PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Agent, AgentOptions, IncomingMessage } from 'node:http' import type { Uint8ArrayList } from 'uint8arraylist' import type { Dispatcher, Agent as UnidiciAgent } from 'undici' -export { WELL_KNOWN_PROTOCOLS } from './constants.js' - -export interface WebSocketInit extends AbortOptions { - /** - * The maximum message size to be sent or received over the socket in bytes - * - * @default 10_485_760 - */ - maxMessageSize?: number - - /** - * Headers to send with the initial upgrade request - */ - headers?: HeadersInit +export { WELL_KNOWN_PROTOCOLS_PATH } from './routes/well-known.js' +/** + * Options used to control Fetch request and the initial WebSocket upgrade + * request + */ +export interface HTTPRequestOptions extends AbortOptions { /** * A list of request processors that can augment requests - if specified will * override any processors passed to the `http` service */ - middleware?: Array<(components: any) => RequestMiddleware> + middleware?: Array<(components: any) => ClientMiddleware> /** * If true, cookies will not be used for this request @@ -377,30 +370,43 @@ export interface WebSocketInit extends AbortOptions { * @default false */ ignoreCookies?: boolean -} -export interface FetchInit extends RequestInit { /** - * A list of request processors that can augment requests - if specified will - * override any processors passed to the `http` service + * The maximum number of bytes that will be parsed as response headers + * + * @default 81_920 */ - middleware?: Array<(components: any) => RequestMiddleware> + maxHeaderSize?: number /** - * If true, cookies will not be used for this request + * If true, verify the server's peer id using PeerId Authentication * * @default false */ - ignoreCookies?: boolean + authenticateServer?: boolean +} +export interface WebSocketInit extends HTTPRequestOptions { /** - * The maximum number of bytes that will be parsed as response headers + * The maximum message size to be sent or received over the socket in bytes * - * @default 81_920 + * @default 10_485_760 */ - maxHeaderSize?: number + maxMessageSize?: number + + /** + * Headers to send with the initial upgrade request + */ + headers?: HeadersInit + + /** + * Protocols to send with the upgrade request + */ + protocols?: string[] } +export type FetchInit = HTTPRequestOptions & RequestInit + export interface HTTPRequestHandler { (req: Request): Promise } @@ -419,22 +425,29 @@ export type ProtocolMap = Record export interface RequestHandlerOptions { /** - * If true, all requests to this handler will be authenticated using peer id - * auth before they are passed to the handler. + * Specify a path to serve the protocol from. If omitted the protocol name + * will be used. * - * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + * Paths can be looked up from the protocol map using `getProtocolMap()` or by + * making a GET request to `/.well-known/libp2p/protocols`. + */ + path?: string + + /** + * A list of HTTP verbs this handler will respond to. If the handler is found + * but the request method is not present a 405 will be returned. * - * @default false + * @default ['GET'] */ - authenticate?: boolean + methods?: string[] /** - * Specify a path to serve the protocol from. If omitted a random one will be - * generated which can be looked up from the protocol map using - * `getProtocolMap()` or by making a GET request to - * `/.well-known/libp2p/protocols`. + * By default all handlers support CORS headers, pass `false` here to disallow + * access to fetch requests. + * + * @default true */ - path?: string + cors?: boolean } /** @@ -462,7 +475,7 @@ export interface HTTP { * URLs can start with the `multiaddr:` scheme if the global URL class in the * runtime environment supports it. */ - connect (resource: string | URL | Multiaddr | Multiaddr[], protocols?: string[], init?: WebSocketInit): WebSocket + connect (resource: string | URL | Multiaddr | Multiaddr[], init?: WebSocketInit): Promise /** * Get a libp2p-enabled Agent for use with node's `http` module. This method @@ -498,7 +511,7 @@ export interface HTTP { /** * Register a listener for a HTTP protocol */ - handle (protocol: string, handler: HTTPRequestHandler, options?: RequestHandlerOptions): void + handle (protocol: string, handler: HTTPRoute): void /** * Remove a listener for a HTTP protocol @@ -559,15 +572,15 @@ export interface Endpoint { export interface RequestOptions extends AbortOptions { method: string headers: Headers - middleware: RequestMiddleware[] + middleware: ClientMiddleware[] ignoreCookies: boolean } /** - * Request/response middleware that allows augmenting the request/response with - * additional fields or headers. + * Middleware that allows augmenting the client request/response with additional + * fields or headers. */ -export interface RequestMiddleware { +export interface ClientMiddleware { /** * Called before a request is made */ @@ -602,9 +615,9 @@ export interface HTTPInit { /** * A list of request processors that can augment requests. Middleware passed - * here will be invoked on every request. + * here will be invoked on every outgoing request. */ - middleware?: Array<(components: any) => RequestMiddleware> + middleware?: Array<(components: any) => ClientMiddleware> /** * How often to evict stale cookies from the cache in ms. diff --git a/src/cookies.ts b/src/middleware/cookies.ts similarity index 93% rename from src/cookies.ts rename to src/middleware/cookies.ts index ac35bad..090552c 100644 --- a/src/cookies.ts +++ b/src/middleware/cookies.ts @@ -1,6 +1,6 @@ import cookie from 'cookie' -import { toURL } from './http.browser.js' -import type { RequestMiddleware, RequestOptions } from './index.js' +import { toURL } from '../http.browser.js' +import type { ClientMiddleware, RequestOptions } from '../index.js' import type { ComponentLogger, Logger } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -8,7 +8,7 @@ interface CookiesComponents { logger: ComponentLogger } -interface CookiesInit { +export interface CookiesInit { cookieExpiryCheckInterval?: number } @@ -20,7 +20,7 @@ interface Cookie { path?: string } -export class Cookies implements RequestMiddleware { +export class Cookies implements ClientMiddleware { private readonly log: Logger private readonly cookies: Map diff --git a/src/peer-id-auth.ts b/src/middleware/peer-id-auth.ts similarity index 82% rename from src/peer-id-auth.ts rename to src/middleware/peer-id-auth.ts index 8c62af9..e39858c 100644 --- a/src/peer-id-auth.ts +++ b/src/middleware/peer-id-auth.ts @@ -2,11 +2,12 @@ import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' import { InvalidParametersError } from '@libp2p/interface' import { peerIdFromPublicKey } from '@libp2p/peer-id' import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' -import { parseHeader, sign, verify } from './auth/common.js' -import { InvalidPeerError, InvalidSignatureError, MissingAuthHeaderError } from './auth/errors.js' -import { DEFAULT_AUTH_TOKEN_TTL, PEER_ID_AUTH_SCHEME } from './constants.js' -import { getCacheKey, getHost } from './utils.js' -import type { HTTP, RequestMiddleware, RequestOptions } from './index.js' +import { parseHeader, sign, verify } from '../auth/common.js' +import { InvalidPeerError, InvalidSignatureError, MissingAuthHeaderError } from '../auth/errors.js' +import { DEFAULT_AUTH_TOKEN_TTL, PEER_ID_AUTH_SCHEME } from '../constants.js' +import { SEC_WEBSOCKET_PROTOCOL_PREFIX } from '../routes/peer-id-auth.js' +import { getCacheKey, getHost, isWebSocketInit } from '../utils.js' +import type { HTTP, ClientMiddleware, RequestOptions } from '../index.js' import type { AbortOptions, ComponentLogger, Logger, PeerId, PrivateKey } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -22,19 +23,19 @@ interface PeerIdAuthComponents { http: HTTP } -interface PeerIdAuthInit { +export interface PeerIdAuthInit { verifyPeer?(peerId: PeerId): boolean | Promise ttl?: number } -class PeerIdAuth implements RequestMiddleware { +export class PeerIdAuth implements ClientMiddleware { private readonly components: PeerIdAuthComponents private readonly log: Logger private readonly tokens: Map private readonly tokenTTL: number private readonly verifyPeer: (peerId: PeerId, options?: AbortOptions) => boolean | Promise - constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit = {}) { + constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit) { this.components = components this.log = components.logger.forComponent('libp2p:http:peer-id-auth') this.tokens = new Map() @@ -43,19 +44,20 @@ class PeerIdAuth implements RequestMiddleware { } async prepareRequest (resource: URL | Multiaddr[], opts: RequestOptions): Promise { - const existingAuthHeader = opts.headers.get('authorization') + const token = await this.getOrCreateAuthToken(resource, opts) - if (existingAuthHeader != null) { - if (existingAuthHeader.includes('challenge-server')) { - // we are already authenticating this request - return + if (isWebSocketInit(opts)) { + opts.protocols = [ + ...(opts.protocols ?? []), + `${SEC_WEBSOCKET_PROTOCOL_PREFIX}${btoa(token.bearer)}` + ] + } else { + if (opts.headers.get('authorization') != null) { + throw new InvalidParametersError('Will not overwrite existing Authorization header') } - throw new InvalidParametersError('Will not overwrite existing Authorization header') + opts.headers.set('Authorization', token.bearer) } - - const token = await this.getOrCreateAuthToken(resource, opts) - opts.headers.set('Authorization', token.bearer) } async getOrCreateAuthToken (resource: URL | Multiaddr[], opts: RequestOptions): Promise { @@ -86,6 +88,8 @@ class PeerIdAuth implements RequestMiddleware { // copy existing headers const challengeHeaders = new Headers(opts.headers) + challengeHeaders.delete('connection') + challengeHeaders.delete('upgrade') challengeHeaders.set('authorization', encodeAuthParams({ 'challenge-server': challengeServer, 'public-key': publicKeyStr @@ -95,14 +99,16 @@ class PeerIdAuth implements RequestMiddleware { method: 'OPTIONS', headers: challengeHeaders, signal: opts.signal, - middleware: opts.middleware.map(m => () => m) + middleware: opts.middleware + .filter(m => m !== this) + .map(m => () => m) }) // verify the server's challenge const authHeader = resp.headers.get('www-authenticate') if (authHeader == null) { - throw new MissingAuthHeaderError('No auth header') + throw new MissingAuthHeaderError('No www-authenticate header in response') } const authFields = parseHeader(authHeader) @@ -162,12 +168,6 @@ class PeerIdAuth implements RequestMiddleware { } } -export function peerIdAuth (init: PeerIdAuthInit = {}): (components: PeerIdAuthComponents) => RequestMiddleware { - return (components) => { - return new PeerIdAuth(components, init) - } -} - function generateChallenge (): string { const randomBytes = new Uint8Array(32) crypto.getRandomValues(randomBytes) @@ -181,3 +181,9 @@ function encodeAuthParams (params: Record): string { return `${PEER_ID_AUTH_SCHEME} ${encodedParams}` } + +export function peerIdAuth (init: PeerIdAuthInit = {}): (component: any) => ClientMiddleware { + return (components) => { + return new PeerIdAuth(components, init) + } +} diff --git a/src/ping/index.ts b/src/ping/index.ts index 0a23ffa..13c0c94 100644 --- a/src/ping/index.ts +++ b/src/ping/index.ts @@ -1,7 +1,7 @@ // http-ping implementation import { PingHTTPService as PingHTTPServiceClass } from './ping.js' -import type { HTTP } from '../index.js' -import type { AbortOptions, ComponentLogger, PeerId } from '@libp2p/interface' +import type { FetchInit, WebSocketInit, HTTP } from '../index.js' +import type { ComponentLogger, PeerId } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' export const HTTP_PING_PROTOCOL = '/http-ping/1' @@ -11,15 +11,18 @@ export interface PingHTTPComponents { logger: ComponentLogger } -export interface PingOptions extends AbortOptions { +export interface PingHTTPOptions extends FetchInit { +} + +export interface PingWebSocketOptions extends WebSocketInit { /** - * If true, make a request over a WebSocket instead of HTTP + * Make a request over a WebSocket instead of HTTP */ - webSocket?: true + webSocket: true } export interface PingHTTP { - ping (peer: PeerId | Multiaddr | Multiaddr[], options?: PingOptions): Promise + ping (peer: PeerId | Multiaddr | Multiaddr[], options?: PingHTTPOptions | PingWebSocketOptions): Promise } export function pingHTTP (): (components: PingHTTPComponents) => PingHTTP { diff --git a/src/ping/ping.ts b/src/ping/ping.ts index e7a08c0..59c7225 100644 --- a/src/ping/ping.ts +++ b/src/ping/ping.ts @@ -4,12 +4,12 @@ import { raceEvent } from 'race-event' import { raceSignal } from 'race-signal' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' import { Response } from '../fetch/response.js' +import { authenticatedWebSocketRoute } from '../routes/peer-id-auth.js' import { toMultiaddrs } from '../utils.js' -import { webSocketHandler } from '../websocket-handler.js' import { HTTP_PING_PROTOCOL } from './index.js' -import type { PingHTTPComponents, PingHTTP as PingHTTPInterface, PingOptions } from './index.js' +import type { PingHTTPComponents, PingHTTP as PingHTTPInterface, PingHTTPOptions, PingWebSocketOptions } from './index.js' import type { Logger, PeerId, Startable } from '@libp2p/interface' -import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr' +import type { Multiaddr } from '@multiformats/multiaddr' const PING_SIZE = 32 @@ -32,7 +32,10 @@ export class PingHTTPService implements PingHTTPInterface, Startable { ] start (): void { - this.components.http.handle(HTTP_PING_PROTOCOL, webSocketHandler(this.onWebSocket, { + this.components.http.handle(HTTP_PING_PROTOCOL, authenticatedWebSocketRoute({ + requireAuth: false, + method: ['GET', 'POST'], + handler: this.onWebSocket, fallback: this.onHTTPRequest })) } @@ -42,7 +45,10 @@ export class PingHTTPService implements PingHTTPInterface, Startable { } async onHTTPRequest (req: Request): Promise { + this.log('incoming HTTP ping request') + if (req.body == null) { + this.log.error('body was null') return new Response(null, { status: 400 }) } @@ -50,6 +56,7 @@ export class PingHTTPService implements PingHTTPInterface, Startable { const buf = new Uint8Array(ab, 0, ab.byteLength) if (buf.byteLength !== PING_SIZE) { + this.log.error('ping data length was incorrect - expected %d got %d', PING_SIZE, buf.byteLength) return new Response(null, { status: 400 }) } @@ -62,10 +69,13 @@ export class PingHTTPService implements PingHTTPInterface, Startable { } onWebSocket (ws: WebSocket): void { + this.log('incoming WebSocket ping request') + ws.addEventListener('message', (evt) => { const buf = new Uint8Array(evt.data, 0, evt.data.byteLength) if (buf.length !== PING_SIZE) { + this.log.error('ping data length was incorrect - expected %d got %d', PING_SIZE, buf.byteLength) ws.close(400) return } @@ -75,8 +85,11 @@ export class PingHTTPService implements PingHTTPInterface, Startable { }) } - async ping (peer: PeerId | Multiaddr | Multiaddr[], options: PingOptions = {}): Promise { - const pingEndpoint = await this.components.http.getProtocolPath(peer, HTTP_PING_PROTOCOL, options) + async ping (peer: PeerId | Multiaddr | Multiaddr[], options: PingHTTPOptions | PingWebSocketOptions = {}): Promise { + const pingEndpoint = await this.components.http.getProtocolPath(peer, HTTP_PING_PROTOCOL, { + ...options, + signal: options.signal ?? undefined + }) const dialTarget = toMultiaddrs(peer) .map(ma => ma.encapsulate(`/http-path/${encodeURIComponent(pingEndpoint.substring(1))}`)) @@ -85,8 +98,8 @@ export class PingHTTPService implements PingHTTPInterface, Startable { // fill buffer with random data crypto.getRandomValues(buf) - this.log('ping %o', peer) - const output = await raceSignal(options.webSocket === true ? this.webSocketPing(dialTarget, buf, options) : this.httpPing(dialTarget, buf, options), options?.signal) + this.log('ping %s', peer) + const output = await raceSignal(isPingWebSocketOptions(options) ? this.webSocketPing(dialTarget, buf, options) : this.httpPing(dialTarget, buf, options), options?.signal ?? undefined) const respBuf = new Uint8Array(output, 0, output.byteLength) if (respBuf.length !== PING_SIZE) { @@ -100,7 +113,7 @@ export class PingHTTPService implements PingHTTPInterface, Startable { return Date.now() - start } - async httpPing (dialTarget: Multiaddr[], buf: Uint8Array, options: AbortOptions): Promise { + async httpPing (dialTarget: Multiaddr[], buf: Uint8Array, options: PingHTTPOptions): Promise { const res = await this.components.http.fetch(dialTarget, { ...options, method: 'POST', @@ -114,9 +127,9 @@ export class PingHTTPService implements PingHTTPInterface, Startable { return res.arrayBuffer() } - async webSocketPing (dialTarget: Multiaddr[], buf: Uint8Array, options: AbortOptions): Promise { + async webSocketPing (dialTarget: Multiaddr[], buf: Uint8Array, options: PingWebSocketOptions): Promise { this.log('opening websocket connection to %a', dialTarget) - const socket = this.components.http.connect(dialTarget, [], options) + const socket = await this.components.http.connect(dialTarget, options) if (socket.readyState !== WebSocket.OPEN) { await raceEvent(socket, 'open', options.signal) @@ -132,6 +145,10 @@ export class PingHTTPService implements PingHTTPInterface, Startable { this.log('ping to %a errored - %e', dialTarget, evt.error ?? evt) reject(new Error('An error occurred')) }) + socket.addEventListener('close', () => { + this.log('ping to %a closed prematurely - %e', dialTarget) + reject(new Error('The WebSocket was closed before the pong was received')) + }) }) this.log('send ping message to %a', dialTarget) @@ -140,3 +157,7 @@ export class PingHTTPService implements PingHTTPInterface, Startable { return p } } + +function isPingWebSocketOptions (obj: any): obj is PingWebSocketOptions { + return obj?.webSocket === true +} diff --git a/src/registrar.ts b/src/registrar.ts index 4e7c612..39a1b1e 100644 --- a/src/registrar.ts +++ b/src/registrar.ts @@ -2,11 +2,14 @@ import { HTTPParser } from '@achingbrain/http-parser-js' import { InvalidParametersError } from '@libp2p/interface' import { queuelessPushable } from 'it-queueless-pushable' import { Uint8ArrayList } from 'uint8arraylist' -import { PROTOCOL, WEBSOCKET_HANDLER, WELL_KNOWN_PROTOCOLS } from './constants.js' +import { PROTOCOL, WEBSOCKET_HANDLER } from './constants.js' import { Response } from './fetch/response.js' -import { NOT_FOUND_RESPONSE, responseToStream, streamToRequest } from './utils.js' -import { wellKnownHandler } from './well-known-handler.js' -import type { Endpoint, HTTPRequestHandler, HeaderInfo, ProtocolMap, RequestHandlerOptions, WebSocketHandler } from './index.js' +import { initializeRoute } from './routes/index.js' +import { wellKnownRoute } from './routes/well-known.js' +import { NOT_FOUND_RESPONSE, normalizeMethod, normalizeUrl, responseToStream, streamToRequest } from './utils.js' +import { CLOSE_MESSAGES } from './websocket/message.js' +import type { Endpoint, HTTPRequestHandler, HeaderInfo, ProtocolMap, WebSocketHandler } from './index.js' +import type { HTTPRoute, HandlerRoute } from './routes/index.js' import type { ComponentLogger, IncomingStreamData, Logger, Stream } from '@libp2p/interface' import type { Registrar } from '@libp2p/interface-internal' @@ -21,9 +24,7 @@ export interface HTTPRegistrarInit { interface ProtocolHandler { protocol: string - path: string - handler: HTTPRequestHandler - authenticated?: boolean + route: Required> } export class HTTPRegistrar { @@ -31,7 +32,6 @@ export class HTTPRegistrar { private readonly components: HTTPRegistrarComponents private protocols: ProtocolHandler[] private readonly endpoint?: Endpoint - private readonly wellKnownHandler: ProtocolHandler constructor (components: HTTPRegistrarComponents, init: HTTPRegistrarInit = {}) { this.components = components @@ -39,11 +39,7 @@ export class HTTPRegistrar { this.protocols = [] this.onStream = this.onStream.bind(this) this.endpoint = init.server - this.wellKnownHandler = { - protocol: '', - path: WELL_KNOWN_PROTOCOLS, - handler: wellKnownHandler(this) - } + this.handle('', wellKnownRoute(this)) } async start (): Promise { @@ -67,6 +63,7 @@ export class HTTPRegistrar { const res = await this.onRequest(streamToRequest(info, stream)) await responseToStream(res, stream) await stream.close() + return } @@ -86,34 +83,58 @@ export class HTTPRegistrar { } canHandle (req: { url?: string }): boolean { - if (req.url === WELL_KNOWN_PROTOCOLS || this.protocols.find(p => p.path === req.url) != null) { - this.log('can handle %s', req.url) + const url = normalizeUrl(req).pathname + + if (this.protocols.find(p => p.route.path === url) != null) { + this.log.trace('can handle %s', url) return true } - this.log('cannot handle %s', req.url) + this.log.trace('cannot handle %s', url) return false } async onRequest (request: Request): Promise { - const result = this.findHandler(request.url) + this.log('incoming request %s %s', request.method, request.url) + + const handler = this.findHandler(request.url) - if (result?.handler != null) { - return result.handler(request) + if (handler == null) { + return new Response(null, { + status: 404 + }) } - return new Response(null, { - status: 404, - statusText: 'Not Found' - }) + let response: Response + + // support OPTIONS method where endpoint does not + if (!handler.route.method.includes(request.method)) { + if (request.method === 'OPTIONS') { + response = new Response(null, { + status: 204 + }) + } else { + response = new Response(null, { + status: 405 + }) + } + } else { + response = await handler.route.handler(request) + } + + addHeaders(response, request, handler) + + this.log('%s %s %d %s', request.method, request.url, response.status, response.statusText) + + return response } onWebSocket (ws: WebSocket): void { - const result = this.findHandler(ws.url) + const handler = this.findHandler(ws.url) - if (result != null) { + if (handler != null) { // @ts-expect-error hidden field - const wsHandler: WebSocketHandler = result.handler[WEBSOCKET_HANDLER] + const wsHandler: WebSocketHandler = handler.route[WEBSOCKET_HANDLER] if (wsHandler != null) { wsHandler(ws) @@ -121,19 +142,15 @@ export class HTTPRegistrar { } } - ws.close(404, 'Not Found') + ws.close(CLOSE_MESSAGES.NORMAL_CLOSURE) } private findHandler (url: string): ProtocolHandler | undefined { const pathname = url.startsWith('/') ? url : new URL(url).pathname - if (pathname === WELL_KNOWN_PROTOCOLS) { - return this.wellKnownHandler - } - this.log('search for handler on path %s', pathname) - const handler = this.protocols.find(p => p.path === pathname) + const handler = this.protocols.find(p => p.route.path === pathname) if (handler != null) { this.log('found handler for HTTP protocol %s on path %s', handler.protocol, url) @@ -142,27 +159,30 @@ export class HTTPRegistrar { return handler } - handle (protocol: string, handler: HTTPRequestHandler, options: RequestHandlerOptions = {}): void { - let path = options.path ?? crypto.randomUUID() + handle (protocol: string, route: HTTPRoute): void { + route.path = route.path ?? protocol if (this.protocols.find(p => p.protocol === protocol) != null) { throw new InvalidParametersError(`HTTP protocol handler for ${protocol} already registered`) } - if (path === '' || !path.startsWith('/')) { - path = `/${path}` + if (route.path === '' || !route.path.startsWith('/')) { + route.path = `/${route.path}` } + route.cors = route.cors ?? true + route.method = normalizeMethod(route.method) + route = initializeRoute(route, this.components) + // add handler this.protocols.push({ protocol, - path, - handler, - authenticated: options.authenticate + // @ts-expect-error optional fields are filled out above + route }) // sort by path length desc so the most specific handler is invoked first - this.protocols.sort(({ path: a }, { path: b }) => b.length - a.length) + this.protocols.sort(({ route: { path: a } }, { route: { path: b } }) => b.length - a.length) } unhandle (protocol: string): void { @@ -174,7 +194,7 @@ export class HTTPRegistrar { for (const p of this.protocols) { output[p.protocol] = { - path: p.path + path: p.route.path } } @@ -235,3 +255,27 @@ async function readHeaders (stream: Stream): Promise { }) }) } + +function addHeaders (response: Response, request: Request, handler: ProtocolHandler): void { + const allow = [...new Set(['OPTIONS', ...handler.route.method])].join(', ') + + if (handler.route.cors) { + if (request.headers.get('Access-Control-Request-Method') != null) { + response.headers.set('access-control-allow-methods', allow) + } + + if (request.headers.get('Access-Control-Request-Headers') != null) { + response.headers.set('access-control-allow-headers', request.headers.get('Access-Control-Request-Headers') ?? '') + } + + if (request.headers.get('Origin') != null) { + response.headers.set('access-control-allow-origin', request.headers.get('Origin') ?? '') + // https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Access-Control-Allow-Origin#cors_and_caching + response.headers.set('vary', 'Origin') + } + } + + if (request.method === 'OPTIONS') { + response.headers.set('allow', allow) + } +} diff --git a/src/routes/index.ts b/src/routes/index.ts new file mode 100644 index 0000000..9fc16e6 --- /dev/null +++ b/src/routes/index.ts @@ -0,0 +1,86 @@ +import type { WEBSOCKET_HANDLER } from '../constants.js' +import type { HTTPRequestHandler, WebSocketHandler } from '../index.js' + +/** + * Options used to define a HTTP route that can handle requests + */ +export interface RouteOptions { + /** + * Specify a path to serve the protocol from. If omitted the protocol name + * will be used. + * + * Paths can be looked up from the protocol map using `getProtocolMap()` or by + * making a GET request to `/.well-known/libp2p/protocols`. + */ + path?: string + + /** + * A list of HTTP verbs this handler will respond to. If the handler is found + * but the request method is not present a 405 will be returned. + * + * @default ['GET'] + */ + method?: string | string[] + + /** + * By default all handlers support CORS headers, pass `false` here to disallow + * access to fetch requests. + * + * @default true + */ + cors?: boolean +} + +/** + * A simple route that defines a handler function + */ +export interface HandlerRoute extends RouteOptions { + handler: H +} + +/** + * A route that requires initialization before use + */ +export interface ServiceRoute extends RouteOptions { + init(components: any): H +} + +/** + * A WebSocket route can make it's handler available for invocation with a + * pre-upgraded WebSocket object + */ +export interface WebSocketRoute { + [WEBSOCKET_HANDLER]?: WebSocketHandler +} + +/** + * A union of the various route types + */ +export type HTTPRoute = (HandlerRoute | ServiceRoute) & WebSocketRoute + +/** + * Returns true if the passed route requires initialization + */ +export function isInitializable , S extends ServiceRoute> (obj: H | S): obj is S { + // @ts-expect-error init is not a property of H + return typeof obj.init === 'function' +} + +/** + * Initializes a `ServiceRoute` and converts it to a `HandlerRoute`. + * + * If the passed route has an `init` method, it invokes it and sets the + * `handler` field on the endpoint with the return value, then deletes the + * `init` property, otherwise it returns the endpoint unaltered. + */ +export function initializeRoute (serviceOrHandler: HTTPRoute, components: any): HandlerRoute { + if (isInitializable(serviceOrHandler)) { + const route: any = serviceOrHandler + route.handler = serviceOrHandler.init(components) + delete route.init + + return route + } + + return serviceOrHandler +} diff --git a/src/routes/peer-id-auth.ts b/src/routes/peer-id-auth.ts new file mode 100644 index 0000000..f20390c --- /dev/null +++ b/src/routes/peer-id-auth.ts @@ -0,0 +1,578 @@ +import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' +import { peerIdFromPublicKey, peerIdFromString } from '@libp2p/peer-id' +import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' +import { encodeAuthParams, parseHeader, sign, verify } from '../auth/common.js' +import { DEFAULT_AUTH_TOKEN_TTL, WEBSOCKET_HANDLER } from '../constants.js' +import { normalizeMethod } from '../utils.js' +import { webSocketRoute } from './websocket.js' +import { initializeRoute } from './index.js' +import type { HTTPRoute, HandlerRoute } from './index.js' +import type { ComponentLogger, Logger, PeerId, PrivateKey, PublicKey } from '@libp2p/interface' + +export const PeerIDAuthScheme = 'libp2p-PeerID' +export const HTTPPeerIDAuthProto = '/http-peer-id-auth/1.0.0' + +interface PeerIdAuthComponents { + privateKey: PrivateKey + logger: ComponentLogger +} + +interface OpaqueUnwrapped { + challengeClient: string + clientPublicKey?: string + hostname: string + creationTime: number +} + +interface AuthenticationResult { + status: number + headers?: Headers + peer?: PeerId | undefined +} + +interface PeerIdAuthInit { + tokenTTL?: number + verifyHostname?(hostname: string): boolean | Promise +} + +export class PeerIdAuth { + private readonly components: PeerIdAuthComponents + public readonly log: Logger + private readonly tokenTTL: number + private readonly verifyHostname: (hostname: string) => boolean | Promise + + constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit) { + this.components = components + this.log = components.logger.forComponent('libp2p:http:server-peer-id-auth') + this.tokenTTL = init.tokenTTL ?? DEFAULT_AUTH_TOKEN_TTL + + this.verifyHostname = init.verifyHostname ?? (() => true) + } + + /* eslint-disable-next-line complexity */ + public async authenticateRequest (hostname: string, authHeader?: string | null): Promise { + if (!(await this.verifyHostname(hostname))) { + this.log.error('hostname verification failed') + return { status: 400 } + } + + if (authHeader == null || authHeader === '') { + return this.returnChallenge(hostname, null, {}) + } + + const authFields = parseHeader(authHeader) + if (authFields.bearer !== undefined && authFields.bearer !== '') { + const peer = await this.unwrapBearerToken(hostname, authFields.bearer) + return { status: 200, peer } + } + + let opaqueState: OpaqueUnwrapped | undefined + if (authFields.opaque !== undefined) { + try { + const opaque = await this.unwrapOpaque(authFields.opaque) + if (opaque.hostname !== hostname) { + this.log.error('invalid hostname') + return { status: 400 } + } + if (Date.now() - opaque.creationTime > this.tokenTTL) { + this.log.error('token expired') + return { status: 400 } + } + + opaqueState = opaque + } catch (e) { + this.log.error('invalid opaque') + return { status: 400 } + } + } + + let clientPublicKey: PublicKey | null = null + if (opaqueState?.clientPublicKey !== undefined) { + clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(opaqueState.clientPublicKey, 'base64urlpad')) + } else if (authFields['public-key'] !== undefined) { + clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(authFields['public-key'], 'base64urlpad')) + } + + const returnParams: Record = {} + let clientPeerId: PeerId | undefined + if (authFields.sig !== undefined) { + // Verify signature + if (clientPublicKey === null) { + this.log.error('missing public-key') + return { status: 400 } + } + if (opaqueState?.challengeClient === null) { + this.log.error('missing challenge-client') + return { status: 400 } + } + + const valid = await verify(clientPublicKey, PeerIDAuthScheme, [ + ['challenge-client', opaqueState?.challengeClient ?? ''], + ['hostname', hostname], + ['server-public-key', publicKeyToProtobuf(this.components.privateKey.publicKey)] + ], uint8ArrayFromString(authFields.sig, 'base64urlpad')) + if (!valid) { + this.log.error('invalid signature') + return { status: 400 } + } + + // Return a bearer token + clientPeerId = peerIdFromPublicKey(clientPublicKey) + returnParams.bearer = this.genBearerToken(clientPeerId, hostname) + } + + if (authFields['challenge-server'] !== undefined) { + if (clientPublicKey === null) { + this.log.error('missing public-key') + return { status: 400 } + } + + // Sign and return challenge + const sig = await sign(this.components.privateKey, PeerIDAuthScheme, [ + ['hostname', hostname], + ['client-public-key', publicKeyToProtobuf(clientPublicKey)], + ['challenge-server', authFields['challenge-server']] + ]) + returnParams['public-key'] = uint8ArrayToString(publicKeyToProtobuf(this.components.privateKey.publicKey), 'base64urlpad') + returnParams.sig = uint8ArrayToString(sig, 'base64urlpad') + } + + if (returnParams.bearer !== undefined) { + return { + status: 200, + peer: clientPeerId, + headers: new Headers({ + 'Authentication-info': encodeAuthParams(returnParams) + }) + } + } + + // Not authenticated + return this.returnChallenge(hostname, clientPublicKey, returnParams) + } + + private async returnChallenge (hostname: string, clientPublicKey: PublicKey | null, returnParams: Record): Promise { + const challenge = this.generateChallenge() + returnParams['challenge-client'] = challenge + + returnParams.opaque = this.genOpaque({ + challengeClient: challenge, + clientPublicKey: clientPublicKey !== null ? uint8ArrayToString(publicKeyToProtobuf(clientPublicKey), 'base64urlpad') : undefined, + hostname, + creationTime: Date.now() + }) + + return { + status: 401, + headers: new Headers({ + 'www-authenticate': encodeAuthParams(returnParams), + 'access-control-expose-headers': 'www-authenticate' + }) + } + } + + private genBearerToken (clientPeerId: PeerId, hostname: string): string { + return this.signBox(this.components.privateKey, { + peer: clientPeerId.toString(), + h: hostname, + t: Date.now() + }) + } + + private async unwrapBearerToken (expectedHostname: string, token: string): Promise { + if (token.length < PeerIDAuthScheme.length + 1) { + throw new Error('Invalid bearer token') + } + const bearer = parseHeader(token).bearer + const unwrapped = await this.verifyBox(this.components.privateKey.publicKey, bearer) as any + if (typeof unwrapped.peer !== 'string' || typeof unwrapped.h !== 'string' || typeof unwrapped.t !== 'number') { + throw new Error('Invalid bearer token') + } + if (unwrapped.h !== expectedHostname) { + throw new Error('Invalid hostname') + } + if (Date.now() - unwrapped.t > this.tokenTTL) { + throw new Error('Token expired') + } + return peerIdFromString(unwrapped.peer) + } + + private genOpaque (unwrapped: OpaqueUnwrapped): string { + return this.signBox(this.components.privateKey, unwrapped) + } + + private async unwrapOpaque (opaque: string): Promise { + const unwrapped = await this.verifyBox(this.components.privateKey.publicKey, opaque) as any + if (typeof unwrapped.challengeClient !== 'string' || typeof unwrapped.hostname !== 'string' || typeof unwrapped.creationTime !== 'number') { + throw new Error('Invalid opaque') + } + return unwrapped + } + + private signBox (key: PrivateKey, data: unknown): string { + const dataSerialized = JSON.stringify(data) + const dataBytes = uint8ArrayFromString(dataSerialized) + const sig = key.sign(dataBytes) + const jsonStr = JSON.stringify({ + val: uint8ArrayToString(dataBytes, 'base64urlpad'), + sig: uint8ArrayToString(sig, 'base64urlpad') + }) + return uint8ArrayToString(uint8ArrayFromString(jsonStr), 'base64urlpad') + } + + private async verifyBox (key: PublicKey, data: string): Promise { + const { sig, val } = JSON.parse(uint8ArrayToString(uint8ArrayFromString(data, 'base64urlpad'))) + const valBytes = uint8ArrayFromString(val, 'base64urlpad') + const sigValid = await key.verify(valBytes, uint8ArrayFromString(sig, 'base64urlpad')) + if (!sigValid) { + throw new Error('Invalid signature') + } + const valStr = uint8ArrayToString(valBytes) + return JSON.parse(valStr) + } + + private generateChallenge (): string { + const randomBytes = new Uint8Array(32) + crypto.getRandomValues(randomBytes) + return uint8ArrayToString(randomBytes, 'base64urlpad') + } +} + +export interface AuthenticationOptions { + /** + * How long in ms an auth token for a server will be valid for, defaults to + * one hour + * + * @default 360_000 + */ + tokenTTL?: number + + /** + * An optional function that can be used to verify that the hostname of the + * incoming request is valid and supported + */ + verifyHostname?(hostname: string): boolean | Promise +} + +export interface OptionalAuthenticationOptions extends AuthenticationOptions { + /** + * If true the request will be rejected if the client does not supply an + * `Authorization` header, pass `false` here to attempt to verify the client + * but allow the request to proceed if it fails + * + * @default true + */ + requireAuth: false +} + +export interface AuthenticatedWebSocketOptions extends AuthenticationOptions { + /** + * If the request was not a WebSocket request, invoke this method + */ + fallback?: AuthenticatedHTTPRequestHandler + + /** + * The maximum message size to be sent or received over the socket in bytes + * + * @default 10_485_760 + */ + maxMessageSize?: number +} + +export interface OptionallyAuthenticatedWebSocketOptions extends OptionalAuthenticationOptions { + /** + * If the request was not a WebSocket request, invoke this method + */ + fallback?: OptionallyAuthenticatedHTTPRequestHandler + + /** + * The maximum message size to be sent or received over the socket in bytes + * + * @default 10_485_760 + */ + maxMessageSize?: number +} + +/** + * An HTTP handler that accepts the PeerId of the client as an argument + */ +export interface AuthenticatedHTTPRequestHandler { + (req: Request, peerId: PeerId): Promise +} + +/** + * An HTTP handler that accepts the PeerId of the client as an argument, if they + * provided a valid Authorization header + */ +export interface OptionallyAuthenticatedHTTPRequestHandler { + (req: Request, peerId?: PeerId): Promise +} + +/** + * An WebSocket handler that accepts the PeerId of the client as an argument + */ +export interface AuthenticatedWebSocketHandler { + (socket: WebSocket, peerId: PeerId): void +} + +/** + * An WebSocket handler that accepts the PeerId of the client as an argument, if + * they provided a valid Authorization header + */ +export interface OptionallyAuthenticatedWebSocketHandler { + (socket: WebSocket, peerId?: PeerId): void +} + +function isOptionalAuth (obj: any): obj is OptionallyAuthenticatedHandler { + return obj.requireAuth === false +} + +async function authenticate (req: Request, authResult: AuthenticationResult, handlerMethods: string[], next: AuthenticatedHandler): Promise +async function authenticate (req: Request, authResult: AuthenticationResult, handlerMethods: string[], next: OptionallyAuthenticatedHandler): Promise +async function authenticate (req: Request, authResult: AuthenticationResult, handlerMethods: string[], next: AuthenticatedHandler | OptionallyAuthenticatedHandler): Promise { + const authIsOptional = isOptionalAuth(next) + + if (!authIsOptional && authResult.peer == null) { + return new Response(undefined, { + status: authResult.status, + headers: authResult.headers + }) + } + + if (!handlerMethods.includes(req.method)) { + // handle auth requests + let res: Response + + if (req.method === 'OPTIONS') { + // support OPTIONS if the handler doesn't + res = new Response(undefined, { + status: 204, + headers: authResult.headers + }) + } else { + // unsupported method + res = new Response(undefined, { + status: 405 + }) + } + + // add auth headers to response + if (authResult.headers !== undefined) { + for (const [key, value] of authResult.headers) { + res.headers.set(key, value) + } + } + + return res + } + + // @ts-expect-error cannot derive handler type + return next.handler(req, authResult.peer) +} + +type OptionallyAuthenticatedHandler = HandlerRoute & OptionalAuthenticationOptions +type AuthenticatedHandler = HandlerRoute & AuthenticationOptions + +type OptionallyAuthenticatedEndpoint = HTTPRoute & OptionalAuthenticationOptions +type AuthenticatedEndpoint = HTTPRoute & AuthenticationOptions + +/** + * Attempt to authenticate the client before request processing to discover + * their PeerID. + * + * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + */ +export function authenticatedRoute (handler: OptionallyAuthenticatedEndpoint): HTTPRoute +export function authenticatedRoute (handler: AuthenticatedEndpoint): HTTPRoute +export function authenticatedRoute (handler: OptionallyAuthenticatedEndpoint | AuthenticatedEndpoint): HTTPRoute { + const handlerMethods: string[] = normalizeMethod(handler.method) + + return { + path: handler.path, + method: ['OPTIONS', ...handlerMethods], + cors: handler.cors, + init: (components: PeerIdAuthComponents) => { + const auth = new PeerIdAuth(components, handler) + const next = initializeRoute(handler, components) + + return async (req: Request): Promise => { + const authResult = await auth.authenticateRequest(readHostname(req), req.headers.get('Authorization')) + + return authenticate(req, authResult, handlerMethods, next) + } + } + } +} + +type OptionallyAuthenticatedWebSocketEndpoint = HTTPRoute & OptionallyAuthenticatedWebSocketOptions +type AuthenticatedWebSocketEndpoint = HTTPRoute & AuthenticatedWebSocketOptions + +/** + * Attempt to authenticate the client before request processing to discover + * their PeerID. + * + * The authorization token should be passed as a protocol prefixed with + * `authorization=`. + * + * To allow use of actual protocol field, multiple values should be + * comma-delimited, e.g. `authorization=foo,actual,useful,protocols` + * + * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + */ +export function authenticatedWebSocketRoute (handler: OptionallyAuthenticatedWebSocketEndpoint): HTTPRoute +export function authenticatedWebSocketRoute (handler: AuthenticatedWebSocketEndpoint): HTTPRoute +export function authenticatedWebSocketRoute (handler: OptionallyAuthenticatedWebSocketEndpoint | AuthenticatedWebSocketEndpoint): HTTPRoute { + const handlerMethods: string[] = normalizeMethod(handler.method) + + const output: HTTPRoute = { + path: handler.path, + method: ['OPTIONS', ...handlerMethods], + cors: handler.cors, + init: (components: PeerIdAuthComponents) => { + const auth = new PeerIdAuth(components, handler) + const next: any = initializeRoute(handler, components) + + // allow invoking the handler with a pre-upgraded socket + output[WEBSOCKET_HANDLER] = (ws) => { + // need to read the authorization header from the websocket protocol + + // TODO: we should have a way of doing this before the websocket upgrade + // has been negotiated + auth.authenticateRequest(readHostname(ws), readProtocol(ws)) + .then(authResult => { + next.handler(ws, authResult.peer) + }) + .catch(() => { + ws.close() + }) + } + + return async (req: Request): Promise => { + const authResult = await auth.authenticateRequest(readHostname(req), readAuthorization(req) ?? readSecWebSocketProtocol(req)) + + return authenticate(req, authResult, handlerMethods, { + ...next, + handler: async (req, peerId) => { + const wsRoute = initializeRoute(webSocketRoute({ + ...next, + handler: (ws) => { + next.handler(ws, peerId) + }, + fallback: next.fallback == null + ? undefined + : async (req: Request): Promise => { + return authenticate(req, authResult, handlerMethods, { + ...next, + handler: async (res, peerId) => { + if (next.fallback == null) { + // should not get here because we have already + // null-guarded on `handler.fallback` + return new Response(undefined, { + status: 500 + }) + } + + return next.fallback(res, peerId) + } + }) + } + }), components) + + return wsRoute.handler(req) + } + }) + } + } + } + + return output +} + +function readHostname (req: { url: string }): string { + const url = new URL(req.url) + let hostname = url.hostname + + if (url.port === '' || url.port === undefined) { + return hostname + } + + if (url.protocol === 'http:' && url.port !== '80') { + hostname += ':' + url.port + } + + if (url.protocol === 'https:' && url.port !== '443') { + hostname += ':' + url.port + } + + if (hostname === '') { + throw new Error('No hostname') + } + + return hostname +} + +function readAuthorization (req: Request): string | undefined { + const authorization = req.headers.get('Authorization') + + if (authorization == null) { + return + } + + return authorization +} + +export const SEC_WEBSOCKET_PROTOCOL_PREFIX = 'authorization=' + +function readSecWebSocketProtocol (req: Request): string | undefined { + const protocol = req.headers.get('Sec-WebSocket-Protocol') + + if (protocol == null) { + return + } + + const protos = protocol.split(',') + + const authorization = protos + .filter(p => p.startsWith(SEC_WEBSOCKET_PROTOCOL_PREFIX)) + .pop() + + // remove authorization field from protocol if present + if (authorization != null) { + req.headers.set('Sec-WebSocket-Protocol', protos + .filter(p => !p.startsWith(SEC_WEBSOCKET_PROTOCOL_PREFIX)) + .join(',')) + } + + if (authorization == null) { + return + } + + return atob(authorization.substring(SEC_WEBSOCKET_PROTOCOL_PREFIX.length)) +} + +function readProtocol (ws: { protocol?: string }): string | undefined { + const protocol = ws.protocol + + if (protocol == null) { + return + } + + const protos = protocol.split(',') + + const authorization = protos + .filter(p => p.startsWith(SEC_WEBSOCKET_PROTOCOL_PREFIX)) + .pop() + + // remove authorization field from protocol if present + if (authorization != null) { + ws.protocol = protos + .filter(p => !p.startsWith(SEC_WEBSOCKET_PROTOCOL_PREFIX)) + .join(',') + } + + if (authorization == null) { + return + } + + return atob(authorization.substring(SEC_WEBSOCKET_PROTOCOL_PREFIX.length)) +} diff --git a/src/routes/websocket.ts b/src/routes/websocket.ts new file mode 100644 index 0000000..05e744d --- /dev/null +++ b/src/routes/websocket.ts @@ -0,0 +1,82 @@ +import { InvalidParametersError } from '@libp2p/interface' +import { WEBSOCKET_HANDLER } from '../constants.js' +import { Response } from '../fetch/response.js' +import { isWebSocketUpgrade, normalizeMethod } from '../utils.js' +import { getServerUpgradeHeaders } from '../websocket/utils.js' +import { RequestWebSocket } from '../websocket/websocket.js' +import { initializeRoute } from './index.js' +import type { HTTPRequestHandler, WebSocketHandler } from '../index.js' +import type { HTTPRoute, RouteOptions } from './index.js' + +export interface WebSocketRouteOptions extends RouteOptions { + /** + * If the request does not have a `Connection: upgrade` header, pass a + * fallback here to handle the request normally, otherwise the request + * will be rejected with a 400 error. + */ + fallback?: HTTPRequestHandler + + /** + * The maximum message size to be sent or received over the socket in bytes + * + * @default 10_485_760 + */ + maxMessageSize?: number +} + +export type WebSocketRoute = HTTPRoute & WebSocketRouteOptions + +/** + * Negotiate a connection upgrade to the WebSocket protocol and call the passed + * handler + */ +export function webSocketRoute (route: WebSocketRoute): HTTPRoute { + const method = normalizeMethod(route.method, ['GET']) + + if (route.fallback == null && method.filter(method => method !== 'GET').length > 0) { + throw new InvalidParametersError('WebSocket handlers only support the GET HTTP method') + } + + const output: HTTPRoute = { + ...route, + init: (components) => { + const next = initializeRoute(route, components) + + // allow invoking the handler with a pre-upgraded socket + output[WEBSOCKET_HANDLER] = next.handler + + return async (req: Request): Promise => { + // check upgrade has been requested + if (!isWebSocketUpgrade(req.method, req.headers)) { + if (route?.fallback != null) { + return route.fallback(req) + } + + return new Response(null, { + status: 400 + }) + } + + const transform = new TransformStream() + + try { + const res = new Response(transform.readable, { + status: 101, + headers: await getServerUpgradeHeaders(req.headers) + }) + + const ws = new RequestWebSocket(req, transform.writable, route) + next.handler(ws) + + return res + } catch (err) { + return new Response(null, { + status: 500 + }) + } + } + } + } + + return output +} diff --git a/src/routes/well-known.ts b/src/routes/well-known.ts new file mode 100644 index 0000000..9ee30e5 --- /dev/null +++ b/src/routes/well-known.ts @@ -0,0 +1,28 @@ +import { Response } from '../fetch/response.js' +import { webSocketRoute } from './websocket.js' +import type { HTTPRegistrar } from '../registrar.js' +import type { HTTPRoute } from './index.js' + +export const WELL_KNOWN_PROTOCOLS_PATH = '/.well-known/libp2p/protocols' + +export function wellKnownRoute (registrar: HTTPRegistrar): HTTPRoute { + return webSocketRoute({ + path: WELL_KNOWN_PROTOCOLS_PATH, + method: ['GET'], + cors: true, + handler: ws => { + const map = JSON.stringify(registrar.getProtocolMap()) + ws.send(map) + ws.close() + }, + fallback: async (req) => { + const map = JSON.stringify(registrar.getProtocolMap()) + return new Response(map, { + headers: { + 'Content-Type': 'application/json', + 'Content-Length': `${map.length}` + } + }) + } + }) +} diff --git a/src/servers/node.ts b/src/servers/node.ts index c412f1a..6bb11d3 100644 --- a/src/servers/node.ts +++ b/src/servers/node.ts @@ -1,7 +1,7 @@ import { streamToSocket } from '../stream-to-socket.js' import { readableToReadableStream } from '../utils.js' -import type { Endpoint, HeaderInfo } from '../index.js' -import type { Stream, Connection } from '@libp2p/interface' +import type { Endpoint, HTTP, HeaderInfo } from '../index.js' +import type { Stream, Connection, Libp2p } from '@libp2p/interface' import type { ServerResponse, IncomingMessage } from 'node:http' import type { Socket } from 'node:net' @@ -36,7 +36,7 @@ export function nodeServer (server: ConnectionHandler): Endpoint { return new NodeServer({ server }) } -export function incomingMessageToRequest (req: IncomingMessage): Request { +function incomingMessageToRequest (req: IncomingMessage): Request { const headers = incomingHttpHeadersToHeaders(req.headers) const init: RequestInit = { method: req.method, @@ -74,15 +74,14 @@ function incomingHttpHeadersToHeaders (input: IncomingMessage['headers']): Heade return headers } -export function writeResponse (res: Response, ser: ServerResponse): void { - const headers: Record = {} +function writeResponse (res: Response, ser: ServerResponse): void { + ser.statusCode = res.status + ser.statusMessage = res.statusText res.headers.forEach((val, key) => { - headers[key] = val + ser.setHeader(key, val) }) - ser.writeHead(res.status, res.statusText, headers) - if (res.body == null) { ser.end() } else { @@ -108,3 +107,64 @@ export function writeResponse (res: Response, ser: ServerResponse): void { }) } } + +export interface DidHandle { + (...args: any[]): boolean +} + +/** + * Helper function to ascertain whether the passed libp2p node handled the + * incoming HTTP or WebSocket request. + * + * @example Delegating handling of HTTP requests + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { canHandle } from '@libp2p/http/servers' + * import createServer from 'node:http' + * + * const libp2p = await createLibp2p({ + * // ...options + * }) + * + * const handled = canHandle(libp2p) + * + * createServer((req, res) => { + * if (handled(req, res)) { + * // libp2p handled the request, nothing else to do + * return + * } + * + * // handle request normally - pass off to express/fastify/etc or return 404 + * }) + * ``` + */ +export function canHandle (libp2p: Libp2p<{ http: HTTP }>): DidHandle { + return (...args: any[]): boolean => { + if (args.length === 1) { + const ws: WebSocket = args[0] + + if (libp2p.services.http.canHandle(ws)) { + libp2p.services.http.onWebSocket(ws) + return true + } + } else if (args.length === 2) { + const req: IncomingMessage = args[0] + const res: ServerResponse = args[1] + + if (libp2p.services.http.canHandle(req)) { + libp2p.services.http.onRequest(incomingMessageToRequest(req)) + .then(result => { + writeResponse(result, res) + }) + .catch(err => { + res.writeHead(500, err.toString()) + res.end() + }) + return true + } + } + + return false + } +} diff --git a/src/utils.ts b/src/utils.ts index 8d7f72e..a9f1a2d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -8,7 +8,8 @@ import itToBrowserReadableStream from 'it-to-browser-readablestream' import { base36 } from 'multiformats/bases/base36' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { DNS_CODECS, HTTP_CODEC, HTTP_PATH_CODEC } from './constants.js' -import type { HeaderInfo, RequestOptions } from './index.js' +import { Request } from './fetch/request.js' +import type { HeaderInfo, RequestOptions, WebSocketInit } from './index.js' import type { PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Readable } from 'node:stream' @@ -29,17 +30,13 @@ export function toUint8Array (obj: DataView | ArrayBuffer | Uint8Array): Uint8Ar return new Uint8Array(obj, 0, obj.byteLength) } -export function streamToRequest (info: HeaderInfo, stream: Stream): Request { +export function streamToRequest (info: HeaderInfo, stream: Stream): globalThis.Request { const init: RequestInit = { method: info.method, headers: info.headers } - if (info.upgrade) { - init.method = 'UPGRADE' - } - - if (init.method !== 'GET' && init.method !== 'HEAD') { + if ((init.method !== 'GET' || info.upgrade) && init.method !== 'HEAD') { let source: AsyncGenerator = stream.source if (!info.upgrade) { @@ -51,7 +48,7 @@ export function streamToRequest (info: HeaderInfo, stream: Stream): Request { init.duplex = 'half' } - return new Request(`http://${info.headers.get('host') ?? 'host'}${info.url}`, init) + return new Request(normalizeUrl(info).toString(), init) } export async function responseToStream (res: Response, stream: Stream): Promise { @@ -287,9 +284,13 @@ function isValidHost (host?: string): host is string { export function getHost (addresses: URL | Multiaddr[], headers: Headers): string { let host: string | undefined + let port = 80 + let protocol = 'http:' if (addresses instanceof URL) { host = addresses.hostname + port = parseInt(addresses.port, 10) + protocol = addresses.protocol } if (!isValidHost(host)) { @@ -314,6 +315,12 @@ export function getHost (addresses: URL | Multiaddr[], headers: Headers): string for (const address of addresses) { const peerStr = address.getPeerId() + // try to extract port from multiaddr if it is available + try { + const options = address.toOptions() + port = options.port + } catch {} + if (peerStr != null) { const peerId = peerIdFromString(peerStr) // host has to be case-insensitive @@ -324,6 +331,15 @@ export function getHost (addresses: URL | Multiaddr[], headers: Headers): string } if (isValidHost(host)) { + // add port if not standard + if (protocol === 'http:' && port !== 80) { + host = `${host}:${port}` + } + + if (protocol === 'https:' && port !== 443) { + host = `${host}:${port}` + } + return host } @@ -354,6 +370,14 @@ export async function prepareAndSendRequest (resource: URL | Multiaddr[], opts: return sendRequest() } +export async function prepareAndConnect (resource: URL | Multiaddr[], opts: RequestOptions, connect: () => Promise): Promise { + for (const middleware of opts.middleware) { + await middleware.prepareRequest?.(resource, opts) + } + + return connect() +} + export async function processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): Promise { for (const middleware of opts.middleware) { await middleware.processResponse?.(resource, opts, response) @@ -382,3 +406,61 @@ export function stripHTTPPath (addresses: Multiaddr[]): { httpPath: string, addr addresses } } + +export function normalizeMethod (method?: string | string[], defaultMethod = ['GET']): string[] { + if (method == null) { + return defaultMethod + } + + if (typeof method === 'string') { + method = [method] + } + + return method.map(m => m.toUpperCase()) +} + +/** + * Returns a fully qualified URL representing the resource that is being + * requested + */ +export function normalizeUrl (req: { url?: string, headers?: Headers | { host?: string } }): URL { + const url = req.url ?? '/' + + if (url.startsWith('http')) { + return new URL(url) + } + + const host = getHostFromReq(req) + + return new URL(`http://${host}${url}`) +} + +function getHostFromReq (req: any): string { + let host = req.headers?.host + + if (host == null) { + host = req.headers?.Host + } + + if (host == null && typeof req.headers.get === 'function') { + host = req.headers.get('host') + } + + if (host == null) { + throw new InvalidParametersError('Could not read host') + } + + return host +} + +export function isWebSocketUpgrade (method: string, headers: Headers): boolean { + return method === 'GET' && headers.get('connection')?.toLowerCase() === 'upgrade' && headers.get('upgrade')?.toLowerCase() === 'websocket' +} + +export function isWebSocketInit (opts?: any): opts is WebSocketInit { + if (opts == null) { + return false + } + + return isWebSocketUpgrade(opts.method, opts.headers) +} diff --git a/src/websocket-handler.ts b/src/websocket-handler.ts deleted file mode 100644 index b0ec7df..0000000 --- a/src/websocket-handler.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { WEBSOCKET_HANDLER } from './constants.js' -import { Response } from './fetch/response.js' -import { getServerUpgradeHeaders } from './websocket/utils.js' -import { RequestWebSocket } from './websocket/websocket.js' -import type { HTTPRequestHandler, WebSocketHandler } from './index.js' - -export interface WebSocketHandlerOptions { - /** - * If the request does not have a `Connection: upgrade` header, pass a - * fallback here to handle the request normally, otherwise the request - * will be rejected with a 400 error. - */ - fallback?: HTTPRequestHandler - - /** - * The maximum message size to be sent or received over the socket in bytes - * - * @default 10_485_760 - */ - maxMessageSize?: number -} - -/** - * Negotiate a connection upgrade to the WebSocket protocol and call the passed - * handler - */ -export function webSocketHandler (handler: WebSocketHandler, options?: WebSocketHandlerOptions): HTTPRequestHandler { - const fn = async (req: Request): Promise => { - // check upgrade has been requested - if (req.headers.get('connection') !== 'upgrade' && req.headers.get('upgrade') !== 'websocket') { - if (options?.fallback != null) { - return options.fallback(req) - } - - return new Response(null, { - status: 400, - statusText: 'Bad Request' - }) - } - - const transform = new TransformStream() - - try { - const res = { - status: 101, - statusText: 'Switching Protocols', - headers: await getServerUpgradeHeaders(req.headers), - body: transform.readable - } - - const ws = new RequestWebSocket(req, transform.writable, options) - handler(ws) - - // @ts-expect-error the Undici Response class requires statuses to be - // 200-500 so we can't use it, just return an object with the correct - // properties instead - return res - } catch { - return new Response(null, { - status: 400, - statusText: 'Bad Request' - }) - } - } - fn[WEBSOCKET_HANDLER] = handler - - return fn -} diff --git a/src/websocket/events.ts b/src/websocket/events.ts index 4803f83..d317689 100644 --- a/src/websocket/events.ts +++ b/src/websocket/events.ts @@ -11,3 +11,25 @@ export class ErrorEvent extends Event { this.message = err.message } } + +export interface CloseEventInit extends EventInit { + code?: number + reason?: string + wasClean?: boolean +} + +/** + * Can remove once node.js 24 becomes LTS + */ +export class CloseEvent extends Event { + public readonly code: number + public readonly reason: string + public readonly wasClean: boolean + + constructor (type: string, eventInitDict?: CloseEventInit) { + super(type) + this.code = eventInitDict?.code ?? 0 + this.reason = eventInitDict?.reason ?? '' + this.wasClean = eventInitDict?.wasClean ?? true + } +} diff --git a/src/websocket/websocket.ts b/src/websocket/websocket.ts index d8dd2a6..329a2a2 100644 --- a/src/websocket/websocket.ts +++ b/src/websocket/websocket.ts @@ -4,12 +4,12 @@ import { byteStream, type ByteStream } from 'it-byte-stream' import { Uint8ArrayList } from 'uint8arraylist' import { PROTOCOL } from '../constants.js' import { getHeaders } from '../utils.js' -import { ErrorEvent } from './events.js' +import { CloseEvent, ErrorEvent } from './events.js' import { encodeMessage, decodeMessage, CLOSE_MESSAGES } from './message.js' import { performClientUpgrade, performServerUpgrade, readResponse, toBytes } from './utils.js' import type { CloseListener, ErrorListener, MessageListener, OpenListener, WebSocketEvents } from './index.js' import type { MESSAGE_TYPE } from './message.js' -import type { HeaderInfo, RequestMiddleware, RequestOptions } from '../index.js' +import type { HeaderInfo, ClientMiddleware, RequestOptions } from '../index.js' import type { AbortOptions, Stream } from '@libp2p/interface' import type { ConnectionManager } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -29,7 +29,7 @@ export interface AbstractWebSocketInit extends AbortOptions { } export abstract class AbstractWebSocket extends TypedEventEmitter { - public readonly binaryType = 'arraybuffer' + public readonly binaryType: 'arraybuffer' | 'blob' = 'arraybuffer' public bufferedAmount = 0 public extensions = '' public protocol: string = '' @@ -170,8 +170,24 @@ export abstract class AbstractWebSocket extends TypedEventEmitter { - this.readyState = this.OPEN this.dispatchEvent(new Event('open')) while (true) { @@ -400,7 +416,7 @@ export class RequestWebSocket extends AbstractWebSocket { } export interface WebSocketInit extends RequestOptions { - middleware: RequestMiddleware[] + middleware: ClientMiddleware[] protocols?: string[] } @@ -419,10 +435,6 @@ export class WebSocket extends AbstractWebSocket { const stream = await connection.newStream(PROTOCOL, init) this.bytes = byteStream(stream) - for (const middleware of init.middleware) { - await middleware.prepareRequest?.(mas, init) - } - for await (const buf of performClientUpgrade(url, init.protocols, getHeaders(init))) { await this.bytes.write(buf) } @@ -430,7 +442,7 @@ export class WebSocket extends AbstractWebSocket { const res = await readResponse(this.bytes, {}) if (res.status !== 101) { - throw new Error('Invalid WebSocket handshake') + throw new Error('Invalid WebSocket handshake - response status ' + res.status) } for (const middleware of init.middleware) { diff --git a/src/well-known-handler.ts b/src/well-known-handler.ts deleted file mode 100644 index 8da2b8a..0000000 --- a/src/well-known-handler.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Response } from './fetch/response.js' -import { webSocketHandler } from './websocket-handler.js' -import type { HTTPRequestHandler } from './index.js' -import type { HTTPRegistrar } from './registrar.js' - -export function wellKnownHandler (registrar: HTTPRegistrar): HTTPRequestHandler { - return webSocketHandler(ws => { - const map = JSON.stringify(registrar.getProtocolMap()) - ws.send(map) - ws.close() - }, { - fallback: async (req) => { - const map = JSON.stringify(registrar.getProtocolMap()) - return new Response(map, { - headers: { - 'Content-Type': 'application/json', - 'Content-Length': `${map.length}` - } - }) - } - }) -} diff --git a/test/cookies.spec.ts b/test/cookies.spec.ts index 66ef6c3..aa575d0 100644 --- a/test/cookies.spec.ts +++ b/test/cookies.spec.ts @@ -4,7 +4,7 @@ import { expect } from 'aegir/chai' import { createServer } from '../src/http/index.js' import { nodeServer } from '../src/servers/node.js' import { createHttp } from './fixtures/create-http.js' -import { getClient, getListener } from './fixtures/get-libp2p.js' +import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' import type { HTTP } from '../src/index.js' import type { Libp2p } from 'libp2p' @@ -20,7 +20,7 @@ const tests: Test[] = [{ name: 'in-process server', startServer: async () => { const server = createHttp(createServer()) - listener = await getListener(nodeServer(server)) + listener = await getHTTPOverLibp2pHandler(nodeServer(server)) return listener.getMultiaddrs() }, diff --git a/test/fetch.spec.ts b/test/fetch.spec.ts index 71eee24..0ebeae7 100644 --- a/test/fetch.spec.ts +++ b/test/fetch.spec.ts @@ -4,7 +4,7 @@ import { expect } from 'aegir/chai' import { createServer } from '../src/http/index.js' import { nodeServer } from '../src/servers/node.js' import { createHttp } from './fixtures/create-http.js' -import { getClient, getListener } from './fixtures/get-libp2p.js' +import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' import type { HTTP } from '../src/index.js' import type { Libp2p } from 'libp2p' @@ -20,7 +20,7 @@ const tests: Test[] = [{ name: 'in-process server', startServer: async () => { const server = createHttp(createServer()) - listener = await getListener(nodeServer(server)) + listener = await getHTTPOverLibp2pHandler(nodeServer(server)) return listener.getMultiaddrs() }, diff --git a/test/fixtures/create-express.ts b/test/fixtures/create-express.ts index ecd1469..2ce54bc 100644 --- a/test/fixtures/create-express.ts +++ b/test/fixtures/create-express.ts @@ -1,13 +1,13 @@ import cookieParser from 'cookie-parser' import express from 'express' -import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { DidHandle } from '../../src/servers/node.js' import type { Server } from 'node:http' /** * Creates an Express server that optionally delegates request handling to a * Libp2p Over HTTP handler */ -export function createExpress (server: Server, handler?: Libp2pOverHTTPHandler): Server { +export function createExpress (server: Server, handler?: DidHandle): Server { const app = express() app.use(cookieParser()) app.get('/', (req, res) => { @@ -35,12 +35,12 @@ export function createExpress (server: Server, handler?: Libp2pOverHTTPHandler): }) server.on('request', (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Request-Method', '*') - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') - res.setHeader('Access-Control-Allow-Headers', '*') - if (handler?.(req, res) !== true) { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + app(req, res) } }) diff --git a/test/fixtures/create-fastify-http.ts b/test/fixtures/create-fastify-http.ts index b2b42e3..3c258d8 100644 --- a/test/fixtures/create-fastify-http.ts +++ b/test/fixtures/create-fastify-http.ts @@ -1,19 +1,19 @@ import cookies from '@fastify/cookie' import { fastify } from 'fastify' -import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { DidHandle } from '../../src/servers/node.js' import type { FastifyRequest } from 'fastify' import type { Server, IncomingMessage } from 'node:http' -export async function createFastifyHTTP (server: Server, handler?: Libp2pOverHTTPHandler): Promise { +export async function createFastifyHTTP (server: Server, handler?: DidHandle): Promise { const app = fastify({ serverFactory: (app, opts) => { server.addListener('request', (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Request-Method', '*') - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') - res.setHeader('Access-Control-Allow-Headers', '*') - if (handler?.(req, res) !== true) { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + app(req, res) } }) diff --git a/test/fixtures/create-fastify-websocket.ts b/test/fixtures/create-fastify-websocket.ts index a70b043..a8547c1 100644 --- a/test/fixtures/create-fastify-websocket.ts +++ b/test/fixtures/create-fastify-websocket.ts @@ -1,19 +1,19 @@ import fastifyWebSocket from '@fastify/websocket' import { fastify } from 'fastify' import { toWebSocket } from './to-websocket.js' -import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { DidHandle } from '../../src/servers/node.js' import type { Server } from 'node:http' -export async function createFastifyWebSocket (server: Server, handler?: Libp2pOverHTTPHandler): Promise { +export async function createFastifyWebSocket (server: Server, handler?: DidHandle): Promise { const app = fastify({ serverFactory: (app, opts) => { server.addListener('request', (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Request-Method', '*') - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') - res.setHeader('Access-Control-Allow-Headers', '*') - if (handler?.(req, res) !== true) { + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') + res.setHeader('Access-Control-Allow-Headers', '*') + app(req, res) } }) @@ -29,7 +29,7 @@ export async function createFastifyWebSocket (server: Server, handler?: Libp2pOv }) }) fastify.get('/*', { websocket: true }, (socket, req) => { - if (handler?.(toWebSocket(socket, req)) === true) { + if (handler?.(toWebSocket(socket, req.raw)) === true) { return } diff --git a/test/fixtures/create-http.ts b/test/fixtures/create-http.ts index 708aa48..d5ba4ea 100644 --- a/test/fixtures/create-http.ts +++ b/test/fixtures/create-http.ts @@ -1,7 +1,7 @@ -import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { DidHandle } from '../../src/servers/node.js' import type { Server, RequestListener } from 'node:http' -export function createHttp (server: Server, handler?: Libp2pOverHTTPHandler): Server { +export function createHttp (server: Server, handler?: DidHandle): Server { const app: RequestListener = (req, res) => { if (req.url === '/echo') { req.pipe(res) @@ -28,12 +28,11 @@ export function createHttp (server: Server, handler?: Libp2pOverHTTPHandler): Se } server.on('request', (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Request-Method', '*') - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') - res.setHeader('Access-Control-Allow-Headers', '*') - if (handler?.(req, res) !== true) { + res.setHeader('Access-Control-Allow-Origin', req.headers.origin ?? '*') + res.setHeader('Access-Control-Allow-Methods', ['OPTIONS', req.headers['access-control-request-method'] ?? '']) + res.setHeader('Access-Control-Allow-Headers', req.headers['access-control-request-headers'] ?? '*') + app(req, res) } }) diff --git a/test/fixtures/create-websocket-server.ts b/test/fixtures/create-websocket-server.ts index 86ff713..e0d9bd3 100644 --- a/test/fixtures/create-websocket-server.ts +++ b/test/fixtures/create-websocket-server.ts @@ -1,8 +1,8 @@ import { createWebSocketServer as createWss } from '../../src/websocket/index.js' -import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { DidHandle } from '../../src/servers/node.js' import type { Server } from 'node:http' -export function createWebSocketServer (server: Server, handler?: Libp2pOverHTTPHandler): Server { +export function createWebSocketServer (server: Server, handler?: DidHandle): Server { const wss = createWss() wss.addEventListener('connection', (evt) => { const ws = evt.webSocket @@ -22,15 +22,15 @@ export function createWebSocketServer (server: Server, handler?: Libp2pOverHTTPH }) server.on('request', (req, res) => { + if (handler?.(req, res) === true) { + return + } + res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Request-Method', '*') res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') res.setHeader('Access-Control-Allow-Headers', '*') - if (handler?.(req, res) === true) { - return - } - res.writeHead(400) res.end() }) diff --git a/test/fixtures/create-wss.ts b/test/fixtures/create-wss.ts index c667b83..6708cd7 100644 --- a/test/fixtures/create-wss.ts +++ b/test/fixtures/create-wss.ts @@ -1,9 +1,9 @@ import { WebSocketServer } from 'ws' import { toWebSocket } from './to-websocket.js' -import type { Libp2pOverHTTPHandler } from './get-libp2p-over-http-handler.js' +import type { DidHandle } from '../../src/servers/node.js' import type { Server } from 'node:http' -export function createWss (server: Server, handler?: Libp2pOverHTTPHandler): Server { +export function createWss (server: Server, handler?: DidHandle): Server { const wss = new WebSocketServer({ noServer: true }) wss.on('connection', (ws, req) => { if (handler?.(toWebSocket(ws, req)) === true) { @@ -21,15 +21,15 @@ export function createWss (server: Server, handler?: Libp2pOverHTTPHandler): Ser }) server.on('request', (req, res) => { + if (handler?.(req, res) === true) { + return + } + res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Request-Method', '*') res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') res.setHeader('Access-Control-Allow-Headers', '*') - if (handler?.(req, res) === true) { - return - } - res.writeHead(400) res.end() }) diff --git a/test/fixtures/get-libp2p-over-http-handler.ts b/test/fixtures/get-libp2p-over-http-handler.ts deleted file mode 100644 index 37cbd84..0000000 --- a/test/fixtures/get-libp2p-over-http-handler.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { createLibp2p } from 'libp2p' -import { http } from '../../src/index.js' -import { pingHTTP, type PingHTTP } from '../../src/ping/index.js' -import { incomingMessageToRequest, writeResponse } from '../../src/servers/node.js' -import type { HTTP } from '../../src/index.js' -import type { Libp2p } from '@libp2p/interface' -import type { IncomingMessage, ServerResponse } from 'node:http' - -export interface Libp2pOverHTTPHandler { - /** - * Returns `true` if the libp2p HTTP service will handle this WebSocket (e.g. - * it is for protocol map published at the `/.well-known` location or there is - * a protocol handler registered for this path). - */ - (ws: WebSocket): boolean - - /** - * Returns `true` if the libp2p HTTP service will handle this request (e.g. it - * is for protocol map published at the `/.well-known` location or there is a - * protocol handler registered for this path). - */ - (req: IncomingMessage, res: ServerResponse): boolean -} - -export interface Libp2pOverHttpHandlerResults { - handler: Libp2pOverHTTPHandler - libp2p: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> -} - -export async function getLibp2pOverHttpHandler (): Promise { - const libp2p = await createLibp2p({ - services: { - http: http(), - pingHTTP: pingHTTP() - }, - connectionManager: { - inboundConnectionThreshold: Infinity - } - }) - - const handler = (...args: any[]): boolean => { - if (args.length === 1) { - const ws: WebSocket = args[0] - - if (libp2p.services.http.canHandle(ws)) { - libp2p.services.http.onWebSocket(ws) - return true - } - } else if (args.length === 2) { - const req: IncomingMessage = args[0] - const res: ServerResponse = args[1] - - if (libp2p.services.http.canHandle(req)) { - libp2p.services.http.onRequest(incomingMessageToRequest(req)) - .then(result => { - writeResponse(result, res) - }) - .catch(err => { - res.writeHead(500, err.toString()) - res.end() - }) - return true - } - } - - return false - } - - return { - libp2p, - handler - } -} diff --git a/test/fixtures/get-libp2p.ts b/test/fixtures/get-libp2p.ts index 880842b..4b8852f 100644 --- a/test/fixtures/get-libp2p.ts +++ b/test/fixtures/get-libp2p.ts @@ -5,12 +5,86 @@ import { ping } from '@libp2p/ping' import { webSockets } from '@libp2p/websockets' import { createLibp2p } from 'libp2p' import { http } from '../../src/index.js' -import { pingHTTP } from '../../src/ping/index.js' +import { pingHTTP, type PingHTTP } from '../../src/ping/index.js' +import { authenticatedRoute, authenticatedWebSocketRoute } from '../../src/routes/peer-id-auth.js' import type { Endpoint, HTTP } from '../../src/index.js' import type { Libp2p } from '@libp2p/interface' -export async function getListener (server: Endpoint, listen: string = '/memory/address-1'): Promise> { - return createLibp2p({ +function addEndpoints (libp2p: Libp2p<{ http: HTTP }>): void { + libp2p.services.http.handle('/libp2p/http/echo', { + method: 'POST', + handler: async (req) => { + if (req.body == null) { + return new Response(undefined, { + status: 400 + }) + } + + const body = new TransformStream() + const res = new Response(body.readable) + + req.body?.pipeTo(body.writable) + .catch(err => { + body.writable.abort(err) + .catch(() => {}) + }) + + return res + } + }) + + libp2p.services.http.handle('/libp2p/http/peer-id', authenticatedRoute({ + method: 'GET', + handler: async (req, peerId) => { + return new Response(peerId.toString(), { + status: 200 + }) + } + })) + + libp2p.services.http.handle('/libp2p/http/optional-peer-id', authenticatedRoute({ + method: 'GET', + requireAuth: false, + handler: async (req, peerId) => { + return new Response(peerId?.toString() ?? 'no-peer-id', { + status: 200 + }) + } + })) + + libp2p.services.http.handle('/libp2p/http/ws-peer-id', authenticatedWebSocketRoute({ + method: 'GET', + handler: (ws, peerId) => { + ws.send(peerId.toString()) + ws.close() + }, + fallback: async (req, peerId) => { + return new Response(peerId.toString(), { + status: 200 + }) + } + })) + + libp2p.services.http.handle('/libp2p/http/ws-optional-peer-id', authenticatedWebSocketRoute({ + method: 'GET', + requireAuth: false, + handler: (ws, peerId) => { + ws.send(peerId?.toString() ?? 'no-peer-id') + ws.close() + }, + fallback: async (req, peerId) => { + return new Response(peerId?.toString() ?? 'no-peer-id', { + status: 200 + }) + } + })) +} + +/** + * A node that listens for incoming HTTP over libp2p requests + */ +export async function getHTTPOverLibp2pHandler (server: Endpoint, listen: string = '/memory/address-1'): Promise> { + const libp2p = await createLibp2p({ addresses: { listen: [ listen @@ -35,8 +109,15 @@ export async function getListener (server: Endpoint, listen: string = '/memory/a inboundConnectionThreshold: Infinity } }) + + addEndpoints(libp2p) + + return libp2p } +/** + * A client node that makes HTTP over libp2p requests + */ export async function getClient (): Promise> { return createLibp2p({ transports: [ @@ -56,3 +137,23 @@ export async function getClient (): Promise> { } }) } + +/** + * A node that does not listen on any addresses but processes incoming libp2p + * over HTTP requests + */ +export async function getLibp2pOverHttpHandler (): Promise< Libp2p<{ http: HTTP, pingHTTP: PingHTTP }>> { + const libp2p = await createLibp2p({ + services: { + http: http(), + pingHTTP: pingHTTP() + }, + connectionManager: { + inboundConnectionThreshold: Infinity + } + }) + + addEndpoints(libp2p) + + return libp2p +} diff --git a/test/fixtures/to-websocket.ts b/test/fixtures/to-websocket.ts index f23efa5..5dc6b3e 100644 --- a/test/fixtures/to-websocket.ts +++ b/test/fixtures/to-websocket.ts @@ -1,8 +1,12 @@ +import { normalizeUrl } from '../../src/utils.js' +import type { IncomingMessage } from '../../src/http/incoming-message.js' import type { WebSocket as WSSWebSocket } from 'ws' -export function toWebSocket (ws: WSSWebSocket, req: { url?: string }): WebSocket { +export function toWebSocket (ws: WSSWebSocket, req: IncomingMessage): WebSocket { + const url = normalizeUrl(req) + Object.defineProperty(ws, 'url', { - value: req.url, + value: url.toString(), writable: false }) diff --git a/test/peer-id-auth.spec.ts b/test/peer-id-auth.spec.ts index 6ee3896..136450f 100644 --- a/test/peer-id-auth.spec.ts +++ b/test/peer-id-auth.spec.ts @@ -1,10 +1,13 @@ import { stop } from '@libp2p/interface' +import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' +import pDefer from 'p-defer' +import { pEvent } from 'p-event' import { createServer } from '../src/http/index.js' -import { peerIdAuth } from '../src/peer-id-auth.js' +import { peerIdAuth } from '../src/middleware/peer-id-auth.js' import { nodeServer } from '../src/servers/node.js' import { createHttp } from './fixtures/create-http.js' -import { getClient, getListener } from './fixtures/get-libp2p.js' +import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' import type { HTTP } from '../src/index.js' import type { Multiaddr } from '@multiformats/multiaddr' import type { Libp2p } from 'libp2p' @@ -21,14 +24,14 @@ const tests: Test[] = [{ name: 'in-process server', startServer: async () => { const server = createHttp(createServer()) - listener = await getListener(nodeServer(server)) + listener = await getHTTPOverLibp2pHandler(nodeServer(server)) return listener.getMultiaddrs() }, stopServer: async () => { await stop(listener) } -}/*, { +}, { name: 'js', startServer: async () => { return [ @@ -88,10 +91,10 @@ const tests: Test[] = [{ stopServer: async () => { } -} */] +}] for (const test of tests) { - describe.skip(`peer id auth - ${test.name}`, () => { + describe(`peer id auth - ${test.name}`, () => { let client: Libp2p<{ http: HTTP }> let listenerMultiaddrs: Multiaddr[] @@ -106,7 +109,72 @@ for (const test of tests) { }) it('should support peer id auth', async () => { - const setResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/set-cookies')), { + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/peer-id')}`)), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(client.peerId.toString()) + }) + + it('should support optional peer id auth', async () => { + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/optional-peer-id')}`)), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(client.peerId.toString()) + }) + + it('should support optional peer id auth without auth', async () => { + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/optional-peer-id')}`)), { + headers: { + host: 'test-with-auth.com' + } + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal('no-peer-id') + }) + + it('should support WebSocket peer id auth', async () => { + const deferred = pDefer() + const socket = await client.services.http.connect(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/ws-peer-id')}`)), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + + if (socket.readyState !== WebSocket.OPEN) { + await pEvent(socket, 'open') + } + + socket.addEventListener('error', (evt: any) => { + deferred.reject(evt.error) + }) + socket.addEventListener('close', () => { + deferred.reject(new Error('Socket closed before message received')) + }) + socket.addEventListener('message', (evt) => { + deferred.resolve(new TextDecoder().decode(evt.data)) + }) + + await expect(deferred.promise).to.eventually.equal(client.peerId.toString()) + }) + + it('should support WebSocket optional peer id auth', async () => { + const deferred = pDefer() + const socket = await client.services.http.connect(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/ws-optional-peer-id')}`)), { headers: { host: 'test-with-auth.com' }, @@ -114,19 +182,83 @@ for (const test of tests) { peerIdAuth() ] }) - expect(setResponse.status).to.equal(201) - expect(setResponse.headers.get('set-cookie')).to.not.be.ok() - const getResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/get-cookies')), { + if (socket.readyState !== WebSocket.OPEN) { + await pEvent(socket, 'open') + } + + socket.addEventListener('error', (evt: any) => { + deferred.reject(evt.error) + }) + socket.addEventListener('close', () => { + deferred.reject(new Error('Socket closed before message received')) + }) + socket.addEventListener('message', (evt) => { + deferred.resolve(new TextDecoder().decode(evt.data)) + }) + + await expect(deferred.promise).to.eventually.equal(client.peerId.toString()) + }) + + it('should support WebSocket optional peer id auth without auth', async () => { + const deferred = pDefer() + const socket = await client.services.http.connect(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/ws-optional-peer-id')}`)), { + headers: { + host: 'test-with-auth.com' + } + }) + + if (socket.readyState !== WebSocket.OPEN) { + await pEvent(socket, 'open') + } + + socket.addEventListener('error', (evt: any) => { + deferred.reject(evt.error) + }) + socket.addEventListener('close', () => { + deferred.reject(new Error('Socket closed before message received')) + }) + socket.addEventListener('message', (evt) => { + deferred.resolve(new TextDecoder().decode(evt.data)) + }) + + await expect(deferred.promise).to.eventually.equal('no-peer-id') + }) + + it('should fall back to HTTP on WebSocket route with peer id auth', async () => { + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/ws-peer-id')}`)), { headers: { - host: 'test-with-cookies.com' + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(client.peerId.toString()) + }) + + it('should fall back to HTTP on WebSocket route with optional peer id auth', async () => { + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/ws-optional-peer-id')}`)), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(client.peerId.toString()) + }) + + it('should fall back to HTTP on WebSocket route with optional peer id auth without auth', async () => { + const response = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/ws-optional-peer-id')}`)), { + headers: { + host: 'test-with-auth.com' } }) - expect(getResponse.status).to.equal(200) - await expect(getResponse.json()).to.eventually.deep.equal([ - 'cookie-1=value-1', - 'cookie-2=value-2' - ]) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal('no-peer-id') }) }) } diff --git a/test/ping.spec.ts b/test/ping.spec.ts index 5842838..495b050 100644 --- a/test/ping.spec.ts +++ b/test/ping.spec.ts @@ -3,98 +3,19 @@ import { noise } from '@chainsafe/libp2p-noise' import { yamux } from '@chainsafe/libp2p-yamux' import { generateKeyPair } from '@libp2p/crypto/keys' -import { NotFoundError, peerRoutingSymbol, stop } from '@libp2p/interface' -import { memory } from '@libp2p/memory' +import { stop } from '@libp2p/interface' import { peerIdFromPrivateKey } from '@libp2p/peer-id' import { webSockets } from '@libp2p/websockets' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import { createLibp2p } from 'libp2p' +import sinon from 'sinon' import { http } from '../src/index.js' +import { peerIdAuth } from '../src/middleware/peer-id-auth.js' import { pingHTTP } from '../src/ping/index.js' import type { HTTP } from '../src/index.js' import type { PingHTTP } from '../src/ping/index.js' -import type { Libp2p, PeerId, PeerInfo } from '@libp2p/interface' - -describe('pingHTTP', () => { - let client: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> - let listener: Libp2p<{ http: HTTP, pingHTTP: PingHTTP }> - - beforeEach(async () => { - listener = await createLibp2p({ - addresses: { - listen: [ - '/memory/address-1' - ] - }, - transports: [ - memory() - ], - streamMuxers: [ - yamux() - ], - connectionEncrypters: [ - noise() - ], - services: { - http: http(), - pingHTTP: pingHTTP() - } - }) - - client = await createLibp2p({ - transports: [ - memory() - ], - streamMuxers: [ - yamux() - ], - connectionEncrypters: [ - noise() - ], - services: { - http: http(), - pingHTTP: pingHTTP() - }, - peerRouters: [ - () => { - const routing: any = { - async findPeer (peerId: PeerId): Promise { - if (peerId.equals(listener.peerId)) { - return { - id: listener.peerId, - multiaddrs: listener.getMultiaddrs() - } - } - - throw new NotFoundError() - }, - async * getClosestPeers () {} - } - routing[peerRoutingSymbol] = routing - - return routing - } - ] - }) - }) - - afterEach(async () => { - await stop(client, listener) - }) - - it('should perform ping with multiaddr', async () => { - await expect(client.services.pingHTTP.ping(listener.getMultiaddrs()[0])).to.eventually.be.a('number') - }) - - it('should perform ping with multiaddrs', async () => { - await expect(client.services.pingHTTP.ping(listener.getMultiaddrs())).to.eventually.be.a('number') - }) - - it('should perform ping with a peer id', async () => { - await expect(client.services.pingHTTP.ping(listener.peerId)).to.eventually.be.a('number') - }) -}) +import type { Libp2p } from '@libp2p/interface' const LIBP2P_SERVERS = [{ name: 'node:http', @@ -145,14 +66,6 @@ describe('ping - HTTP over libp2p', () => { it(`should perform ping with ${test.name} server`, async () => { await expect(client.services.pingHTTP.ping(multiaddr(test.address))).to.eventually.be.a('number') }) - - it('should perform ping with multiaddrs', async () => { - await expect(client.services.pingHTTP.ping(multiaddr(test.address))).to.eventually.be.a('number') - }) - - it('should perform ping with a peer id', async () => { - await expect(client.services.pingHTTP.ping(multiaddr(test.address))).to.eventually.be.a('number') - }) }) }) @@ -192,20 +105,40 @@ describe('ping - libp2p over HTTP', () => { it(`should perform ping with a HTTP address with a peer id of a ${test.name} server`, async () => { const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${process.env.HTTP_PEER_ID}`) + const verifyPeer = sinon.stub().callsFake((peerId) => { + return peerId.equals(httpAddr.getPeerId()) + }) - await expect(client.services.pingHTTP.ping(httpAddr)).to.eventually.be.a('number') + await expect(client.services.pingHTTP.ping(httpAddr, { + middleware: [ + peerIdAuth({ + verifyPeer + }) + ] + })).to.eventually.be.a('number') + + expect(verifyPeer).to.have.property('called', true) }) - it.skip(`should reject when performing ping with a HTTP address with the wrong peer id of a ${test.name} server`, async () => { - // TODO: detect PeerID in HTTP multiaddr and apply peer id auth - // https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + it(`should reject when performing ping with a HTTP address with the wrong peer id of a ${test.name} server`, async () => { const privateKey = await generateKeyPair('Ed25519') const peerId = peerIdFromPrivateKey(privateKey) const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${peerId}`) + const verifyPeer = sinon.stub().callsFake((peerId) => { + return peerId.equals(httpAddr.getPeerId()) + }) + + await expect(client.services.pingHTTP.ping(httpAddr, { + middleware: [ + peerIdAuth({ + verifyPeer + }) + ] + })).to.eventually.be.rejected + .with.property('name', 'InvalidPeerError') - await expect(client.services.pingHTTP.ping(httpAddr)).to.eventually.be.rejected - .with.property('name', 'InvalidPeerIdError') + expect(verifyPeer).to.have.property('called', true) }) }) }) @@ -235,7 +168,7 @@ describe('ping - libp2p over WebSockets', () => { }) WS_SERVERS.forEach(test => { - it(`should perform ping with the HTTP address of a ${test.name} server`, async () => { + it(`should perform ping with the WebSocket address of a ${test.name} server`, async () => { const httpAddr = multiaddr(test.address) await expect(client.services.pingHTTP.ping(httpAddr, { @@ -243,26 +176,44 @@ describe('ping - libp2p over WebSockets', () => { })).to.eventually.be.a('number') }) - it(`should perform ping with a HTTP address with a peer id of a ${test.name} server`, async () => { + it(`should perform ping with a WebSocket address with a peer id of a ${test.name} server`, async () => { const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${process.env.HTTP_PEER_ID}`) + const verifyPeer = sinon.stub().callsFake((peerId) => { + return peerId.equals(httpAddr.getPeerId()) + }) await expect(client.services.pingHTTP.ping(httpAddr, { - webSocket: true + webSocket: true, + middleware: [ + peerIdAuth({ + verifyPeer + }) + ] })).to.eventually.be.a('number') + + expect(verifyPeer).to.have.property('called', true) }) - it.skip(`should reject when performing ping with a HTTP address with the wrong peer id of a ${test.name} server`, async () => { - // TODO: detect PeerID in HTTP multiaddr and apply peer id auth - // https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md + it(`should reject when performing ping with a WebSocket address with the wrong peer id of a ${test.name} server`, async () => { const privateKey = await generateKeyPair('Ed25519') const peerId = peerIdFromPrivateKey(privateKey) const httpAddr = multiaddr(test.address).encapsulate(`/p2p/${peerId}`) + const verifyPeer = sinon.stub().callsFake((peerId) => { + return peerId.equals(httpAddr.getPeerId()) + }) await expect(client.services.pingHTTP.ping(httpAddr, { - webSocket: true + webSocket: true, + middleware: [ + peerIdAuth({ + verifyPeer + }) + ] })).to.eventually.be.rejected - .with.property('name', 'InvalidPeerIdError') + .with.property('name', 'InvalidPeerError') + + expect(verifyPeer).to.have.property('called', true) }) }) }) @@ -307,7 +258,7 @@ describe('ping - WebSockets over libp2p', () => { }) LIBP2P_WS_SERVERS.forEach(test => { - it(`should perform ping with the HTTP address of a ${test.name} server`, async () => { + it(`should perform ping with the WebSocket address of a ${test.name} server`, async () => { const httpAddr = multiaddr(test.address) await expect(client.services.pingHTTP.ping(httpAddr, { diff --git a/test/websockets.spec.ts b/test/websockets.spec.ts index a573886..2ea8361 100644 --- a/test/websockets.spec.ts +++ b/test/websockets.spec.ts @@ -1,11 +1,11 @@ import { stop } from '@libp2p/interface' import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import pDefer from 'p-defer' import { createServer } from '../src/http/index.js' import { nodeServer } from '../src/servers/node.js' import { createWebSocketServer } from './fixtures/create-websocket-server.js' -import { getClient, getListener } from './fixtures/get-libp2p.js' +import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' import type { HTTP } from '../src/index.js' import type { Libp2p } from 'libp2p' @@ -22,7 +22,7 @@ const LIBP2P_SERVERS: Test[] = [{ startServer: async () => { const server = createWebSocketServer(createServer()) - listener = await getListener(nodeServer(server)) + listener = await getHTTPOverLibp2pHandler(nodeServer(server)) return listener.getMultiaddrs()[0] }, stopServer: async () => { @@ -77,23 +77,28 @@ for (const test of LIBP2P_SERVERS) { await test.stopServer() }) - it('should make an WebSocket request to echo', (cb) => { + it('should make an WebSocket request to echo', async () => { + const deferred = pDefer() const message = 'This should be echoed' - const socket = client.services.http.connect(address.encapsulate('/http-path/echo'), [], { + const socket = await client.services.http.connect(address.encapsulate('/http-path/echo'), { headers: { host: 'example.com' } }) socket.addEventListener('error', (evt: any) => { - cb(evt.error) + deferred.reject(evt.error) + }) + socket.addEventListener('close', () => { + deferred.reject(new Error('Socket closed before message received')) }) socket.addEventListener('message', (evt) => { - expect(evt.data).to.equalBytes(uint8ArrayFromString(message)) - cb() + deferred.resolve(evt.data) }) socket.addEventListener('open', () => { socket.send(message) }) + + expect(new TextDecoder().decode(await deferred.promise)).to.equal(message) }) }) } @@ -133,23 +138,28 @@ for (const test of HTTP_SERVERS) { await test.stopServer() }) - it('should make an WebSocket request to echo', (cb) => { + it('should make an WebSocket request to echo', async () => { + const deferred = pDefer() const message = 'This should be echoed' - socket = client.services.http.connect(address.encapsulate('/http-path/echo'), [], { + socket = await client.services.http.connect(address.encapsulate('/http-path/echo'), { headers: { host: 'example.com' } }) socket.addEventListener('error', (evt: any) => { - cb(evt.error) + deferred.reject(evt.error) + }) + socket.addEventListener('close', () => { + deferred.reject(new Error('Socket closed before message received')) }) socket.addEventListener('message', (evt) => { - expect(new Uint8Array(evt.data)).to.equalBytes(uint8ArrayFromString(message)) - cb() + deferred.resolve(evt.data) }) socket.addEventListener('open', () => { socket.send(message) }) + + expect(new TextDecoder().decode(await deferred.promise)).to.equal(message) }) }) } From 5ab1c701cb017508e13b1a22006dbfda77b30e68 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 24 Apr 2025 11:04:32 +0100 Subject: [PATCH 06/22] chore: fix firefox webworkers --- src/fetch/request.ts | 25 +++++++++++++++++++------ src/fetch/response.ts | 23 ++++++++++++++++------- src/fetch/send-request.ts | 38 ++------------------------------------ src/fetch/utils.ts | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 49 deletions(-) create mode 100644 src/fetch/utils.ts diff --git a/src/fetch/request.ts b/src/fetch/request.ts index f921eca..bbbb079 100644 --- a/src/fetch/request.ts +++ b/src/fetch/request.ts @@ -6,16 +6,17 @@ import { getHeaders, isWebSocketUpgrade } from '../utils.js' * - body - normally GET requests cannot have a body, but if the request is for * a WebSocket upgrade, we need the body to turn into the socket * + * Also firefox Web Workers remove the request body though weirdly the main + * thread doesn't. + * * - headers - the global browser request removes certain headers like * Authorization and Sec-WebSocket-Protocol but we need to preserve them */ export class Request extends globalThis.Request { - public readonly method: string - public readonly headers: Headers - constructor (input: RequestInfo | URL, init: RequestInit = {}) { - const headers = getHeaders(init) const method = init.method ?? 'GET' + const headers = getHeaders(init) + const body = init.body if (isWebSocketUpgrade(method, headers)) { // temporarily override the method name since undici does not allow GET @@ -25,7 +26,19 @@ export class Request extends globalThis.Request { super(input, init) - this.method = method - this.headers = headers + Object.defineProperties(this, { + body: { + value: body, + writable: false + }, + method: { + value: method, + writable: false + }, + headers: { + value: headers, + writable: false + } + }) } } diff --git a/src/fetch/response.ts b/src/fetch/response.ts index 64e512e..f170c62 100644 --- a/src/fetch/response.ts +++ b/src/fetch/response.ts @@ -1,4 +1,5 @@ import { STATUS_CODES } from '../constants.js' +import { getHeaders } from '../utils.js' /** * Extends the native Response class to be more flexible. @@ -11,11 +12,8 @@ import { STATUS_CODES } from '../constants.js' * just those allowed by the fetch spec */ export class Response extends globalThis.Response { - public readonly status: number - public readonly statusText: string - public readonly headers: Headers - constructor (body: BodyInit | null, init: ResponseInit = {}) { + const headers = getHeaders(init) const status = init.status ?? 200 if (status < 200 || status > 599) { @@ -24,8 +22,19 @@ export class Response extends globalThis.Response { super(body, init) - this.status = status - this.statusText = STATUS_CODES[status] - this.headers = new Headers(init?.headers) + Object.defineProperties(this, { + status: { + value: status, + writable: false + }, + statusText: { + value: STATUS_CODES[status], + writable: false + }, + headers: { + value: headers, + writable: false + } + }) } } diff --git a/src/fetch/send-request.ts b/src/fetch/send-request.ts index 13b079f..46b4bdf 100644 --- a/src/fetch/send-request.ts +++ b/src/fetch/send-request.ts @@ -1,10 +1,6 @@ import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' import { writeHeaders } from '../utils.js' -import { blobBody } from './body/blob.js' -import { bytesBody } from './body/bytes.js' -import { formDataBody } from './body/form-data.js' -import { readableStreamBody } from './body/readable-stream.js' -import { stringBody } from './body/string.js' +import { normalizeContent } from './utils.js' import type { SendRequestInit } from './index.js' import type { Stream } from '@libp2p/interface' import type { ByteStream } from 'it-byte-stream' @@ -19,11 +15,7 @@ export async function sendRequest (bytes: ByteStream, url: URL, init: Se headers.set('user-agent', 'libp2p/fetch') } - let content: ReadableStream | undefined - - if (init.body != null) { - content = normalizeContent(init.body, headers) - } + const content = normalizeContent(init.body, headers) const req = [ `${init?.method?.toUpperCase() ?? 'GET'} ${url.pathname ?? '/'} HTTP/1.1`, @@ -61,29 +53,3 @@ async function sendBody (bytes: ByteStream, stream: ReadableStream Date: Thu, 24 Apr 2025 12:25:06 +0100 Subject: [PATCH 07/22] chore: rename for monorepo --- README.md | 2 +- examples/express-server-over-libp2p/server.js | 54 ---- .../README.md | 14 + .../client.js | 17 +- .../package.json | 17 ++ .../server.js | 46 ++++ .../test.js | 0 package.json | 253 +++--------------- packages/http-client/LICENSE | 4 + packages/http-client/LICENSE-APACHE | 5 + packages/http-client/LICENSE-MIT | 19 ++ packages/http-client/README.md | 73 +++++ packages/http-client/package.json | 58 ++++ .../http-client/src}/fetch/body/blob.ts | 0 .../http-client/src}/fetch/body/bytes.ts | 0 .../http-client/src}/fetch/body/form-data.ts | 0 .../src}/fetch/body/readable-stream.ts | 0 .../http-client/src}/fetch/body/string.ts | 0 .../http-client/src}/fetch/index.ts | 0 .../http-client/src}/fetch/read-response.ts | 0 .../http-client/src}/fetch/request.ts | 0 .../http-client/src}/fetch/response.ts | 0 .../http-client/src}/fetch/send-request.ts | 0 .../http-client/src}/fetch/utils.ts | 0 packages/http-client/src/index.ts | 13 + .../http-client/src}/middleware/cookies.ts | 0 .../src}/middleware/peer-id-auth.ts | 0 .../http-client/src}/websocket/events.ts | 0 .../http-client/src}/websocket/index.ts | 0 .../http-client/src}/websocket/message.ts | 0 .../http-client/src}/websocket/server.ts | 0 .../http-client/src}/websocket/utils.ts | 0 .../http-client/src}/websocket/websocket.ts | 0 .../http-client/tsconfig.json | 0 packages/http-client/typedoc.json | 5 + packages/http-ping/LICENSE | 4 + packages/http-ping/LICENSE-APACHE | 5 + packages/http-ping/LICENSE-MIT | 19 ++ packages/http-ping/README.md | 73 +++++ packages/http-ping/package.json | 58 ++++ {src/ping => packages/http-ping/src}/index.ts | 0 {src/ping => packages/http-ping/src}/ping.ts | 0 packages/http-ping/tsconfig.json | 10 + packages/http-ping/typedoc.json | 5 + packages/http-server/LICENSE | 4 + packages/http-server/LICENSE-APACHE | 5 + packages/http-server/LICENSE-MIT | 19 ++ packages/http-server/README.md | 73 +++++ packages/http-server/package.json | 58 ++++ .../http-server/src}/fetch.ts | 0 .../http-server/src}/incoming-message.ts | 0 .../http-server/src}/index.browser.ts | 0 .../http-server/src}/index.ts | 0 .../http-server/src}/node.ts | 0 .../http-server/src}/routes/index.ts | 0 .../http-server/src}/routes/peer-id-auth.ts | 0 .../http-server/src}/routes/websocket.ts | 0 .../http-server/src}/routes/well-known.ts | 0 .../http-server/src}/server-response.ts | 0 .../http-server/src}/server.ts | 0 packages/http-server/tsconfig.json | 10 + packages/http-server/typedoc.json | 5 + packages/http-utils/LICENSE | 4 + packages/http-utils/LICENSE-APACHE | 5 + packages/http-utils/LICENSE-MIT | 19 ++ packages/http-utils/README.md | 73 +++++ packages/http-utils/package.json | 58 ++++ packages/http-utils/src/index.ts | 5 + .../http-utils/src}/stream-to-socket.ts | 0 {src => packages/http-utils/src}/utils.ts | 0 packages/http-utils/tsconfig.json | 10 + packages/http-utils/typedoc.json | 5 + packages/http/LICENSE | 4 + packages/http/LICENSE-APACHE | 5 + packages/http/LICENSE-MIT | 19 ++ packages/http/README.md | 73 +++++ packages/http/package.json | 227 ++++++++++++++++ {src => packages/http/src}/constants.ts | 0 {src => packages/http/src}/http.browser.ts | 0 {src => packages/http/src}/http.ts | 0 {src => packages/http/src}/index.ts | 0 {src => packages/http/src}/registrar.ts | 0 packages/http/tsconfig.json | 10 + packages/http/typedoc.json | 5 + typedoc.json | 9 +- 85 files changed, 1174 insertions(+), 285 deletions(-) delete mode 100644 examples/express-server-over-libp2p/server.js create mode 100644 examples/serving-http-resources-over-libp2p-streams/README.md rename examples/{express-server-over-libp2p => serving-http-resources-over-libp2p-streams}/client.js (79%) create mode 100644 examples/serving-http-resources-over-libp2p-streams/package.json create mode 100644 examples/serving-http-resources-over-libp2p-streams/server.js create mode 100644 examples/serving-http-resources-over-libp2p-streams/test.js create mode 100644 packages/http-client/LICENSE create mode 100644 packages/http-client/LICENSE-APACHE create mode 100644 packages/http-client/LICENSE-MIT create mode 100644 packages/http-client/README.md create mode 100644 packages/http-client/package.json rename {src => packages/http-client/src}/fetch/body/blob.ts (100%) rename {src => packages/http-client/src}/fetch/body/bytes.ts (100%) rename {src => packages/http-client/src}/fetch/body/form-data.ts (100%) rename {src => packages/http-client/src}/fetch/body/readable-stream.ts (100%) rename {src => packages/http-client/src}/fetch/body/string.ts (100%) rename {src => packages/http-client/src}/fetch/index.ts (100%) rename {src => packages/http-client/src}/fetch/read-response.ts (100%) rename {src => packages/http-client/src}/fetch/request.ts (100%) rename {src => packages/http-client/src}/fetch/response.ts (100%) rename {src => packages/http-client/src}/fetch/send-request.ts (100%) rename {src => packages/http-client/src}/fetch/utils.ts (100%) create mode 100644 packages/http-client/src/index.ts rename {src => packages/http-client/src}/middleware/cookies.ts (100%) rename {src => packages/http-client/src}/middleware/peer-id-auth.ts (100%) rename {src => packages/http-client/src}/websocket/events.ts (100%) rename {src => packages/http-client/src}/websocket/index.ts (100%) rename {src => packages/http-client/src}/websocket/message.ts (100%) rename {src => packages/http-client/src}/websocket/server.ts (100%) rename {src => packages/http-client/src}/websocket/utils.ts (100%) rename {src => packages/http-client/src}/websocket/websocket.ts (100%) rename tsconfig.json => packages/http-client/tsconfig.json (100%) create mode 100644 packages/http-client/typedoc.json create mode 100644 packages/http-ping/LICENSE create mode 100644 packages/http-ping/LICENSE-APACHE create mode 100644 packages/http-ping/LICENSE-MIT create mode 100644 packages/http-ping/README.md create mode 100644 packages/http-ping/package.json rename {src/ping => packages/http-ping/src}/index.ts (100%) rename {src/ping => packages/http-ping/src}/ping.ts (100%) create mode 100644 packages/http-ping/tsconfig.json create mode 100644 packages/http-ping/typedoc.json create mode 100644 packages/http-server/LICENSE create mode 100644 packages/http-server/LICENSE-APACHE create mode 100644 packages/http-server/LICENSE-MIT create mode 100644 packages/http-server/README.md create mode 100644 packages/http-server/package.json rename {src/servers => packages/http-server/src}/fetch.ts (100%) rename {src/http => packages/http-server/src}/incoming-message.ts (100%) rename {src/http => packages/http-server/src}/index.browser.ts (100%) rename {src/http => packages/http-server/src}/index.ts (100%) rename {src/servers => packages/http-server/src}/node.ts (100%) rename {src => packages/http-server/src}/routes/index.ts (100%) rename {src => packages/http-server/src}/routes/peer-id-auth.ts (100%) rename {src => packages/http-server/src}/routes/websocket.ts (100%) rename {src => packages/http-server/src}/routes/well-known.ts (100%) rename {src/http => packages/http-server/src}/server-response.ts (100%) rename {src/http => packages/http-server/src}/server.ts (100%) create mode 100644 packages/http-server/tsconfig.json create mode 100644 packages/http-server/typedoc.json create mode 100644 packages/http-utils/LICENSE create mode 100644 packages/http-utils/LICENSE-APACHE create mode 100644 packages/http-utils/LICENSE-MIT create mode 100644 packages/http-utils/README.md create mode 100644 packages/http-utils/package.json create mode 100644 packages/http-utils/src/index.ts rename {src => packages/http-utils/src}/stream-to-socket.ts (100%) rename {src => packages/http-utils/src}/utils.ts (100%) create mode 100644 packages/http-utils/tsconfig.json create mode 100644 packages/http-utils/typedoc.json create mode 100644 packages/http/LICENSE create mode 100644 packages/http/LICENSE-APACHE create mode 100644 packages/http/LICENSE-MIT create mode 100644 packages/http/README.md create mode 100644 packages/http/package.json rename {src => packages/http/src}/constants.ts (100%) rename {src => packages/http/src}/http.browser.ts (100%) rename {src => packages/http/src}/http.ts (100%) rename {src => packages/http/src}/index.ts (100%) rename {src => packages/http/src}/registrar.ts (100%) create mode 100644 packages/http/tsconfig.json create mode 100644 packages/http/typedoc.json diff --git a/README.md b/README.md index 261d0d1..c9fec6e 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) -> Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP +> Accept HTTP requests over libp2p streams and/or use libp2p protocols over HTTP # About diff --git a/examples/express-server-over-libp2p/server.js b/examples/express-server-over-libp2p/server.js deleted file mode 100644 index b18ab77..0000000 --- a/examples/express-server-over-libp2p/server.js +++ /dev/null @@ -1,54 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { http } from '@libp2p/http-fetch' -import { PING_PROTOCOL_ID, servePing } from '@libp2p/http-fetch/ping' -import { tcp } from '@libp2p/tcp' -import express from 'express' -import { createLibp2p } from 'libp2p' - -const app = express() - -const node = await createLibp2p({ - addresses: { - listen: ['/ip4/127.0.0.1/tcp/8000'] - }, - transports: [tcp()], - connectionEncrypters: [noise()], - streamMuxers: [yamux()], - services: { - http: http() - } -}) - -node.services.http.registerProtocol(PING_PROTOCOL_ID, '/ping') - -// start libp2p -await node.start() -console.error('libp2p has started') - -// Also listen on a standard http transport -const server = servePing({ - fetch: app.fetch, - port: 8001, - hostname: '127.0.0.1' -}) - -const listenAddrs = node.getMultiaddrs() -console.error('libp2p is listening on the following addresses:') -console.log('/ip4/127.0.0.1/tcp/8001/http') -for (const addr of listenAddrs) { - console.log(addr.toString()) -} -console.log('') // Empty line to signal we have no more addresses (for test runner) - -// wait for SIGINT -await new Promise(resolve => process.on('SIGINT', resolve)) - -// Stop the http server -server.close() - -// stop libp2p -node.stop() -console.error('libp2p has stopped') diff --git a/examples/serving-http-resources-over-libp2p-streams/README.md b/examples/serving-http-resources-over-libp2p-streams/README.md new file mode 100644 index 0000000..343b2fc --- /dev/null +++ b/examples/serving-http-resources-over-libp2p-streams/README.md @@ -0,0 +1,14 @@ +# Serve HTTP resources over libp2p streams using Express + +In this example we will configure an [Express](https://expressjs.com/) server, +but instead of accepting incoming HTTP requests using a Node.js [http.Server](https://nodejs.org/api/http.html#class-httpserver) +instance, we will configure a libp2p node to listen on the `/http/1.1` protocol, +parse data sent over incoming streams on that protocol as HTTP requests and +inject them into the Express server. + +This lets libp2p take care of the routing, thus taking advantage of features +like multi-routes, NAT transversal and stream multiplexing over a single +connection while integrating seamlessly with existing HTTP applications. + +## Getting started + diff --git a/examples/express-server-over-libp2p/client.js b/examples/serving-http-resources-over-libp2p-streams/client.js similarity index 79% rename from examples/express-server-over-libp2p/client.js rename to examples/serving-http-resources-over-libp2p-streams/client.js index 91dd32a..25885e7 100644 --- a/examples/express-server-over-libp2p/client.js +++ b/examples/serving-http-resources-over-libp2p-streams/client.js @@ -8,20 +8,13 @@ import { tcp } from '@libp2p/tcp' import { multiaddr } from '@multiformats/multiaddr' import { createLibp2p } from 'libp2p' -const node = await createLibp2p({ - // libp2p nodes are started by default, pass false to override this - start: false, - addresses: { - listen: [] - }, +const client = await createLibp2p({ transports: [tcp()], connectionEncrypters: [noise()], streamMuxers: [yamux()], services: { http: http() } }) -// start libp2p -await node.start() console.error('libp2p has started') // Read server multiaddr from the command line @@ -37,13 +30,13 @@ const isHTTPTransport = serverMA.protos().find(p => p.name === 'http') // check if (!isHTTPTransport && serverMA.getPeerId() === null) { // Learn the peer id of the server. This lets us reuse the connection for all our HTTP requests. // Otherwise js-libp2p will open a new connection for each request. - const conn = await node.dial(serverMA) + const conn = await client.dial(serverMA) serverMA = serverMA.encapsulate(`/p2p/${conn.remotePeer.toString()}`) } console.error('Making request to', `${serverMA.toString()}`) try { - const resp = await node.services.http.fetch(new Request(`multiaddr:${serverMA}` + `/http-path/${encodeURIComponent('my-app')}`)) + const resp = await client.services.http.fetch(new Request(`multiaddr:${serverMA}` + `/http-path/${encodeURIComponent('my-app')}`)) const respBody = await resp.text() if (resp.status !== 200) { throw new Error(`Unexpected status code: ${resp.status}`) @@ -53,9 +46,9 @@ try { } const start = new Date().getTime() - await sendPing(node, serverMA) + await sendPing(client, serverMA) const end = new Date().getTime() console.error('HTTP Ping took', end - start, 'ms') } finally { - await node.stop() + await client.stop() } diff --git a/examples/serving-http-resources-over-libp2p-streams/package.json b/examples/serving-http-resources-over-libp2p-streams/package.json new file mode 100644 index 0000000..95661ca --- /dev/null +++ b/examples/serving-http-resources-over-libp2p-streams/package.json @@ -0,0 +1,17 @@ +{ + "name": "@libp2p/http-example-serving-http-resources-over-libp2p-streams", + "type": "module", + "private": true, + "scripts": { + "test": "test-example test" + }, + "dependencies": { + "@chainsafe/libp2p-gossipsub": "^14.0.0", + "@chainsafe/libp2p-noise": "^16.0.0", + "@chainsafe/libp2p-yamux": "^7.0.0", + "libp2p": "^2.0.0" + }, + "devDependencies": { + "test-ipfs-example": "^1.0.0" + } +} diff --git a/examples/serving-http-resources-over-libp2p-streams/server.js b/examples/serving-http-resources-over-libp2p-streams/server.js new file mode 100644 index 0000000..41fa172 --- /dev/null +++ b/examples/serving-http-resources-over-libp2p-streams/server.js @@ -0,0 +1,46 @@ +/* eslint-disable no-console */ + +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { http } from '@libp2p/http' +import { tcp } from '@libp2p/tcp' +import express from 'express' +import { createLibp2p } from 'libp2p' + +// create an express server +const app = express() + +// configure a route +app.get('/my-resource', (req, res) => { + res.send('hello from express!') +}) + +// this libp2p node will pass HTTP requests to Express +const listener = await createLibp2p({ + addresses: { + listen: ['/ip4/127.0.0.1/tcp/0'] + }, + transports: [tcp()], + connectionEncrypters: [noise()], + streamMuxers: [yamux()], + services: { + http: http() + } +}) + +const listenAddrs = listener.getMultiaddrs() +console.error('libp2p is listening on the following addresses:') + +for (const addr of listenAddrs) { + console.info(addr.toString()) +} + +// wait for SIGINT +await new Promise(resolve => process.on('SIGINT', resolve)) + +// Stop the http server +listener.close() + +// stop libp2p +await listener.stop() +console.error('libp2p has stopped') diff --git a/examples/serving-http-resources-over-libp2p-streams/test.js b/examples/serving-http-resources-over-libp2p-streams/test.js new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json index 6307660..9964679 100644 --- a/package.json +++ b/package.json @@ -1,227 +1,54 @@ { - "name": "@libp2p/http", - "version": "0.0.0", - "description": "Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP", + "name": "js-libp2p-http-monorepo", + "version": "1.0.0", + "description": "Accept HTTP requests over libp2p streams and/or use libp2p protocols over HTTP", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", + "homepage": "https://github.com/libp2p/js-libp2p-http#readme", "repository": { "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" + "url": "git+https://github.com/libp2p/js-libp2p-http.git" }, "bugs": { - "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "typesVersions": { - "*": { - "*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ], - "src/*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ] - } - }, - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "types": "./dist/src/index.d.ts", - "import": "./dist/src/index.js" - }, - "./auth": { - "types": "./dist/src/auth/index.d.ts", - "import": "./dist/src/auth/index.js" - }, - "./ping": { - "types": "./dist/src/ping.d.ts", - "import": "./dist/src/ping.js" - }, - "./servers/node": { - "types": "./dist/src/servers/node.d.ts", - "import": "./dist/src/servers/node.js" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "release": { - "branches": [ - "main" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "type": "deps", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Documentation" - }, - { - "type": "deps", - "section": "Dependencies" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] + "url": "https://github.com/libp2p/js-libp2p-http/issues" }, + "private": true, "scripts": { - "build": "aegir build", - "clean": "aegir clean", - "lint": "aegir lint", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:firefox": "aegir test -t browser --browser firefox --cov", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "test:chrome-webworker": "aegir test -t webworker", - "test:webkit": "aegir test -t browser -- --browser webkit", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "dep-check": "aegir dep-check", - "doc-check": "aegir doc-check", + "reset": "aegir run clean && aegir clean interop/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json interop/*/package-lock.json", + "test": "aegir run test", + "test:node": "aegir run test:node", + "test:chrome": "aegir run test:chrome", + "test:chrome-webworker": "aegir run test:chrome-webworker", + "test:firefox": "aegir run test:firefox", + "test:firefox-webworker": "aegir run test:firefox-webworker", + "test:electron-main": "aegir run test:electron-main", + "test:webkit": "aegir run test:webkit", + "test:cli": "aegir run test:cli", + "test:interop": "aegir run test:interop", + "coverage": "aegir run coverage", + "build": "aegir run build", + "clean": "aegir run clean", + "lint": "aegir run lint", + "dep-check": "aegir run dep-check", + "doc-check": "aegir run doc-check", + "spell-check": "aegir spell-check", + "release": "run-s build docs:no-publish npm:release docs", + "npm:release": "aegir exec --bail false npm -- publish", + "release:rc": "aegir release-rc", "docs": "aegir docs", - "release": "aegir release" - }, - "dependencies": { - "@achingbrain/http-parser-js": "^0.5.9", - "@libp2p/crypto": "^5.0.6", - "@libp2p/interface": "^2.2.0", - "@libp2p/interface-internal": "^2.0.10", - "@libp2p/peer-id": "^5.0.7", - "@libp2p/utils": "^6.6.0", - "@multiformats/multiaddr": "^12.3.0", - "@multiformats/multiaddr-to-uri": "^11.0.0", - "@multiformats/uri-to-multiaddr": "^9.0.1", - "cookie": "^1.0.2", - "http-cookie-agent": "^6.0.7", - "it-byte-stream": "^2.0.1", - "it-queueless-pushable": "^2.0.0", - "it-to-browser-readablestream": "^2.0.10", - "multiformats": "^13.3.2", - "p-defer": "^4.0.1", - "race-event": "^1.3.0", - "race-signal": "^1.1.3", - "tough-cookie": "^5.0.0", - "uint8-varint": "^2.0.4", - "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0", - "undici": "^6.21.2" + "docs:no-publish": "aegir docs --publish false -- --exclude interop --exclude doc" }, "devDependencies": { - "@chainsafe/libp2p-noise": "^16.1.0", - "@chainsafe/libp2p-yamux": "^7.0.1", - "@fastify/cookie": "^11.0.2", - "@fastify/websocket": "^11.0.2", - "@libp2p/memory": "^1.1.4", - "@libp2p/ping": "^2.0.27", - "@libp2p/websockets": "^9.2.8", - "@types/cookie-parser": "^1.4.8", - "@types/express": "^5.0.1", - "@types/ws": "^8.18.0", - "aegir": "^45.0.0", - "cookie-parser": "^1.4.7", - "express": "^4.21.2", - "fastify": "^5.2.2", - "it-pair": "^2.0.6", - "libp2p": "^2.2.1", - "p-event": "^6.0.1", - "sinon": "^20.0.0", - "wherearewe": "^2.0.1", - "ws": "^8.18.1" + "aegir": "^45.1.1", + "npm-run-all": "^4.1.5" }, - "browser": { - "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js", - "./dist/src/http.js": "./dist/src/http.browser.js", - "./dist/src/http/index.js": "./dist/src/http/index.browser.js", - "./dist/test/index.spec.js": "./dist/test/index.browser.spec.js", - "node:events": "events", - "node:stream": "readable-stream", - "node:http": false, - "undici": false + "eslintConfig": { + "extends": "ipfs", + "ignorePatterns": [ + "!.aegir.js" + ] }, - "sideEffects": false + "workspaces": [ + "examples/*", + "packages/*" + ] } diff --git a/packages/http-client/LICENSE b/packages/http-client/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http-client/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http-client/LICENSE-APACHE b/packages/http-client/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http-client/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http-client/LICENSE-MIT b/packages/http-client/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http-client/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http-client/README.md b/packages/http-client/README.md new file mode 100644 index 0000000..365d0e8 --- /dev/null +++ b/packages/http-client/README.md @@ -0,0 +1,73 @@ +# @libp2p/http-client + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> Libp2p-compatible implementations of fetch and WebSockets + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http-client/package.json b/packages/http-client/package.json new file mode 100644 index 0000000..282c9d2 --- /dev/null +++ b/packages/http-client/package.json @@ -0,0 +1,58 @@ +{ + "name": "@libp2p/http-client", + "version": "0.0.0", + "description": "Libp2p-compatible implementations of fetch and WebSockets", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http/issues" + }, + "publishConfig": { + "access": "public" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "scripts": { + "build": "aegir build --bundle false", + "test": "aegir test -t node", + "clean": "aegir clean", + "lint": "aegir lint", + "test:node": "aegir test -t node --cov", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check" + }, + "dependencies": { + "@libp2p/crypto": "^5.1.1", + "@libp2p/interface": "^2.9.0", + "@libp2p/keychain": "^5.2.1", + "@libp2p/logger": "^5.1.15", + "interface-datastore": "^8.3.1" + }, + "devDependencies": { + "aegir": "^45.1.1" + }, + "sideEffects": false +} \ No newline at end of file diff --git a/src/fetch/body/blob.ts b/packages/http-client/src/fetch/body/blob.ts similarity index 100% rename from src/fetch/body/blob.ts rename to packages/http-client/src/fetch/body/blob.ts diff --git a/src/fetch/body/bytes.ts b/packages/http-client/src/fetch/body/bytes.ts similarity index 100% rename from src/fetch/body/bytes.ts rename to packages/http-client/src/fetch/body/bytes.ts diff --git a/src/fetch/body/form-data.ts b/packages/http-client/src/fetch/body/form-data.ts similarity index 100% rename from src/fetch/body/form-data.ts rename to packages/http-client/src/fetch/body/form-data.ts diff --git a/src/fetch/body/readable-stream.ts b/packages/http-client/src/fetch/body/readable-stream.ts similarity index 100% rename from src/fetch/body/readable-stream.ts rename to packages/http-client/src/fetch/body/readable-stream.ts diff --git a/src/fetch/body/string.ts b/packages/http-client/src/fetch/body/string.ts similarity index 100% rename from src/fetch/body/string.ts rename to packages/http-client/src/fetch/body/string.ts diff --git a/src/fetch/index.ts b/packages/http-client/src/fetch/index.ts similarity index 100% rename from src/fetch/index.ts rename to packages/http-client/src/fetch/index.ts diff --git a/src/fetch/read-response.ts b/packages/http-client/src/fetch/read-response.ts similarity index 100% rename from src/fetch/read-response.ts rename to packages/http-client/src/fetch/read-response.ts diff --git a/src/fetch/request.ts b/packages/http-client/src/fetch/request.ts similarity index 100% rename from src/fetch/request.ts rename to packages/http-client/src/fetch/request.ts diff --git a/src/fetch/response.ts b/packages/http-client/src/fetch/response.ts similarity index 100% rename from src/fetch/response.ts rename to packages/http-client/src/fetch/response.ts diff --git a/src/fetch/send-request.ts b/packages/http-client/src/fetch/send-request.ts similarity index 100% rename from src/fetch/send-request.ts rename to packages/http-client/src/fetch/send-request.ts diff --git a/src/fetch/utils.ts b/packages/http-client/src/fetch/utils.ts similarity index 100% rename from src/fetch/utils.ts rename to packages/http-client/src/fetch/utils.ts diff --git a/packages/http-client/src/index.ts b/packages/http-client/src/index.ts new file mode 100644 index 0000000..0d2ef17 --- /dev/null +++ b/packages/http-client/src/index.ts @@ -0,0 +1,13 @@ +/** + * @packageDocumentation + * + * This module exports libp2p-compatible versions of the [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) + * and [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) + * APIs. + * + * This is necessary because certain features are disabled in browsers but we + * need access to them in order to serve web pages in a runtime-agnostic way. + */ +export * from './fetch/index.js' +export * from './middleware/index.js' +export * from './websocket/index.js' diff --git a/src/middleware/cookies.ts b/packages/http-client/src/middleware/cookies.ts similarity index 100% rename from src/middleware/cookies.ts rename to packages/http-client/src/middleware/cookies.ts diff --git a/src/middleware/peer-id-auth.ts b/packages/http-client/src/middleware/peer-id-auth.ts similarity index 100% rename from src/middleware/peer-id-auth.ts rename to packages/http-client/src/middleware/peer-id-auth.ts diff --git a/src/websocket/events.ts b/packages/http-client/src/websocket/events.ts similarity index 100% rename from src/websocket/events.ts rename to packages/http-client/src/websocket/events.ts diff --git a/src/websocket/index.ts b/packages/http-client/src/websocket/index.ts similarity index 100% rename from src/websocket/index.ts rename to packages/http-client/src/websocket/index.ts diff --git a/src/websocket/message.ts b/packages/http-client/src/websocket/message.ts similarity index 100% rename from src/websocket/message.ts rename to packages/http-client/src/websocket/message.ts diff --git a/src/websocket/server.ts b/packages/http-client/src/websocket/server.ts similarity index 100% rename from src/websocket/server.ts rename to packages/http-client/src/websocket/server.ts diff --git a/src/websocket/utils.ts b/packages/http-client/src/websocket/utils.ts similarity index 100% rename from src/websocket/utils.ts rename to packages/http-client/src/websocket/utils.ts diff --git a/src/websocket/websocket.ts b/packages/http-client/src/websocket/websocket.ts similarity index 100% rename from src/websocket/websocket.ts rename to packages/http-client/src/websocket/websocket.ts diff --git a/tsconfig.json b/packages/http-client/tsconfig.json similarity index 100% rename from tsconfig.json rename to packages/http-client/tsconfig.json diff --git a/packages/http-client/typedoc.json b/packages/http-client/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http-client/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/packages/http-ping/LICENSE b/packages/http-ping/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http-ping/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http-ping/LICENSE-APACHE b/packages/http-ping/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http-ping/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http-ping/LICENSE-MIT b/packages/http-ping/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http-ping/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http-ping/README.md b/packages/http-ping/README.md new file mode 100644 index 0000000..5e0d5e2 --- /dev/null +++ b/packages/http-ping/README.md @@ -0,0 +1,73 @@ +# @libp2p/http-ping + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> An HTTP version of the ping protocol + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http-ping/package.json b/packages/http-ping/package.json new file mode 100644 index 0000000..c2d10bc --- /dev/null +++ b/packages/http-ping/package.json @@ -0,0 +1,58 @@ +{ + "name": "@libp2p/http-ping", + "version": "0.0.0", + "description": "An HTTP version of the ping protocol", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http/issues" + }, + "publishConfig": { + "access": "public" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "scripts": { + "build": "aegir build --bundle false", + "test": "aegir test -t node", + "clean": "aegir clean", + "lint": "aegir lint", + "test:node": "aegir test -t node --cov", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check" + }, + "dependencies": { + "@libp2p/crypto": "^5.1.1", + "@libp2p/interface": "^2.9.0", + "@libp2p/keychain": "^5.2.1", + "@libp2p/logger": "^5.1.15", + "interface-datastore": "^8.3.1" + }, + "devDependencies": { + "aegir": "^45.1.1" + }, + "sideEffects": false +} \ No newline at end of file diff --git a/src/ping/index.ts b/packages/http-ping/src/index.ts similarity index 100% rename from src/ping/index.ts rename to packages/http-ping/src/index.ts diff --git a/src/ping/ping.ts b/packages/http-ping/src/ping.ts similarity index 100% rename from src/ping/ping.ts rename to packages/http-ping/src/ping.ts diff --git a/packages/http-ping/tsconfig.json b/packages/http-ping/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/http-ping/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/http-ping/typedoc.json b/packages/http-ping/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http-ping/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/packages/http-server/LICENSE b/packages/http-server/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http-server/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http-server/LICENSE-APACHE b/packages/http-server/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http-server/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http-server/LICENSE-MIT b/packages/http-server/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http-server/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http-server/README.md b/packages/http-server/README.md new file mode 100644 index 0000000..5e0d5e2 --- /dev/null +++ b/packages/http-server/README.md @@ -0,0 +1,73 @@ +# @libp2p/http-ping + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> An HTTP version of the ping protocol + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http-server/package.json b/packages/http-server/package.json new file mode 100644 index 0000000..0643ef1 --- /dev/null +++ b/packages/http-server/package.json @@ -0,0 +1,58 @@ +{ + "name": "@libp2p/http-server", + "version": "0.0.0", + "description": "An HTTP version of the ping protocol", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http/issues" + }, + "publishConfig": { + "access": "public" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "scripts": { + "build": "aegir build --bundle false", + "test": "aegir test -t node", + "clean": "aegir clean", + "lint": "aegir lint", + "test:node": "aegir test -t node --cov", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check" + }, + "dependencies": { + "@libp2p/crypto": "^5.1.1", + "@libp2p/interface": "^2.9.0", + "@libp2p/keychain": "^5.2.1", + "@libp2p/logger": "^5.1.15", + "interface-datastore": "^8.3.1" + }, + "devDependencies": { + "aegir": "^45.1.1" + }, + "sideEffects": false +} \ No newline at end of file diff --git a/src/servers/fetch.ts b/packages/http-server/src/fetch.ts similarity index 100% rename from src/servers/fetch.ts rename to packages/http-server/src/fetch.ts diff --git a/src/http/incoming-message.ts b/packages/http-server/src/incoming-message.ts similarity index 100% rename from src/http/incoming-message.ts rename to packages/http-server/src/incoming-message.ts diff --git a/src/http/index.browser.ts b/packages/http-server/src/index.browser.ts similarity index 100% rename from src/http/index.browser.ts rename to packages/http-server/src/index.browser.ts diff --git a/src/http/index.ts b/packages/http-server/src/index.ts similarity index 100% rename from src/http/index.ts rename to packages/http-server/src/index.ts diff --git a/src/servers/node.ts b/packages/http-server/src/node.ts similarity index 100% rename from src/servers/node.ts rename to packages/http-server/src/node.ts diff --git a/src/routes/index.ts b/packages/http-server/src/routes/index.ts similarity index 100% rename from src/routes/index.ts rename to packages/http-server/src/routes/index.ts diff --git a/src/routes/peer-id-auth.ts b/packages/http-server/src/routes/peer-id-auth.ts similarity index 100% rename from src/routes/peer-id-auth.ts rename to packages/http-server/src/routes/peer-id-auth.ts diff --git a/src/routes/websocket.ts b/packages/http-server/src/routes/websocket.ts similarity index 100% rename from src/routes/websocket.ts rename to packages/http-server/src/routes/websocket.ts diff --git a/src/routes/well-known.ts b/packages/http-server/src/routes/well-known.ts similarity index 100% rename from src/routes/well-known.ts rename to packages/http-server/src/routes/well-known.ts diff --git a/src/http/server-response.ts b/packages/http-server/src/server-response.ts similarity index 100% rename from src/http/server-response.ts rename to packages/http-server/src/server-response.ts diff --git a/src/http/server.ts b/packages/http-server/src/server.ts similarity index 100% rename from src/http/server.ts rename to packages/http-server/src/server.ts diff --git a/packages/http-server/tsconfig.json b/packages/http-server/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/http-server/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/http-server/typedoc.json b/packages/http-server/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http-server/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/packages/http-utils/LICENSE b/packages/http-utils/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http-utils/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http-utils/LICENSE-APACHE b/packages/http-utils/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http-utils/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http-utils/LICENSE-MIT b/packages/http-utils/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http-utils/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http-utils/README.md b/packages/http-utils/README.md new file mode 100644 index 0000000..a17a1a8 --- /dev/null +++ b/packages/http-utils/README.md @@ -0,0 +1,73 @@ +# @libp2p/http-utils + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> Shared utils and common code for HTTP modules + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http-utils/package.json b/packages/http-utils/package.json new file mode 100644 index 0000000..07b603d --- /dev/null +++ b/packages/http-utils/package.json @@ -0,0 +1,58 @@ +{ + "name": "@libp2p/http-utils", + "version": "0.0.0", + "description": "Shared utils and common code for HTTP modules", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http/issues" + }, + "publishConfig": { + "access": "public" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "scripts": { + "build": "aegir build --bundle false", + "test": "aegir test -t node", + "clean": "aegir clean", + "lint": "aegir lint", + "test:node": "aegir test -t node --cov", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check" + }, + "dependencies": { + "@libp2p/crypto": "^5.1.1", + "@libp2p/interface": "^2.9.0", + "@libp2p/keychain": "^5.2.1", + "@libp2p/logger": "^5.1.15", + "interface-datastore": "^8.3.1" + }, + "devDependencies": { + "aegir": "^45.1.1" + }, + "sideEffects": false +} \ No newline at end of file diff --git a/packages/http-utils/src/index.ts b/packages/http-utils/src/index.ts new file mode 100644 index 0000000..a74fb53 --- /dev/null +++ b/packages/http-utils/src/index.ts @@ -0,0 +1,5 @@ +/** + * @packageDocumentation + * + * Contains shared code and utilities used by `@libp2p/http-*` modules. + */ diff --git a/src/stream-to-socket.ts b/packages/http-utils/src/stream-to-socket.ts similarity index 100% rename from src/stream-to-socket.ts rename to packages/http-utils/src/stream-to-socket.ts diff --git a/src/utils.ts b/packages/http-utils/src/utils.ts similarity index 100% rename from src/utils.ts rename to packages/http-utils/src/utils.ts diff --git a/packages/http-utils/tsconfig.json b/packages/http-utils/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/http-utils/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/http-utils/typedoc.json b/packages/http-utils/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http-utils/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/packages/http/LICENSE b/packages/http/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http/LICENSE-APACHE b/packages/http/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http/LICENSE-MIT b/packages/http/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http/README.md b/packages/http/README.md new file mode 100644 index 0000000..261d0d1 --- /dev/null +++ b/packages/http/README.md @@ -0,0 +1,73 @@ +# @libp2p/http + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http/package.json b/packages/http/package.json new file mode 100644 index 0000000..6307660 --- /dev/null +++ b/packages/http/package.json @@ -0,0 +1,227 @@ +{ + "name": "@libp2p/http", + "version": "0.0.0", + "description": "Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ], + "src/*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ] + } + }, + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + }, + "./auth": { + "types": "./dist/src/auth/index.d.ts", + "import": "./dist/src/auth/index.js" + }, + "./ping": { + "types": "./dist/src/ping.d.ts", + "import": "./dist/src/ping.js" + }, + "./servers/node": { + "types": "./dist/src/servers/node.d.ts", + "import": "./dist/src/servers/node.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "clean": "aegir clean", + "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", + "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" + }, + "dependencies": { + "@achingbrain/http-parser-js": "^0.5.9", + "@libp2p/crypto": "^5.0.6", + "@libp2p/interface": "^2.2.0", + "@libp2p/interface-internal": "^2.0.10", + "@libp2p/peer-id": "^5.0.7", + "@libp2p/utils": "^6.6.0", + "@multiformats/multiaddr": "^12.3.0", + "@multiformats/multiaddr-to-uri": "^11.0.0", + "@multiformats/uri-to-multiaddr": "^9.0.1", + "cookie": "^1.0.2", + "http-cookie-agent": "^6.0.7", + "it-byte-stream": "^2.0.1", + "it-queueless-pushable": "^2.0.0", + "it-to-browser-readablestream": "^2.0.10", + "multiformats": "^13.3.2", + "p-defer": "^4.0.1", + "race-event": "^1.3.0", + "race-signal": "^1.1.3", + "tough-cookie": "^5.0.0", + "uint8-varint": "^2.0.4", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0", + "undici": "^6.21.2" + }, + "devDependencies": { + "@chainsafe/libp2p-noise": "^16.1.0", + "@chainsafe/libp2p-yamux": "^7.0.1", + "@fastify/cookie": "^11.0.2", + "@fastify/websocket": "^11.0.2", + "@libp2p/memory": "^1.1.4", + "@libp2p/ping": "^2.0.27", + "@libp2p/websockets": "^9.2.8", + "@types/cookie-parser": "^1.4.8", + "@types/express": "^5.0.1", + "@types/ws": "^8.18.0", + "aegir": "^45.0.0", + "cookie-parser": "^1.4.7", + "express": "^4.21.2", + "fastify": "^5.2.2", + "it-pair": "^2.0.6", + "libp2p": "^2.2.1", + "p-event": "^6.0.1", + "sinon": "^20.0.0", + "wherearewe": "^2.0.1", + "ws": "^8.18.1" + }, + "browser": { + "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js", + "./dist/src/http.js": "./dist/src/http.browser.js", + "./dist/src/http/index.js": "./dist/src/http/index.browser.js", + "./dist/test/index.spec.js": "./dist/test/index.browser.spec.js", + "node:events": "events", + "node:stream": "readable-stream", + "node:http": false, + "undici": false + }, + "sideEffects": false +} diff --git a/src/constants.ts b/packages/http/src/constants.ts similarity index 100% rename from src/constants.ts rename to packages/http/src/constants.ts diff --git a/src/http.browser.ts b/packages/http/src/http.browser.ts similarity index 100% rename from src/http.browser.ts rename to packages/http/src/http.browser.ts diff --git a/src/http.ts b/packages/http/src/http.ts similarity index 100% rename from src/http.ts rename to packages/http/src/http.ts diff --git a/src/index.ts b/packages/http/src/index.ts similarity index 100% rename from src/index.ts rename to packages/http/src/index.ts diff --git a/src/registrar.ts b/packages/http/src/registrar.ts similarity index 100% rename from src/registrar.ts rename to packages/http/src/registrar.ts diff --git a/packages/http/tsconfig.json b/packages/http/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/http/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/http/typedoc.json b/packages/http/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/typedoc.json b/typedoc.json index 000b99f..bc9b821 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,8 +1,7 @@ { - "entryPoints": [ - "./src/index.ts", - "./src/auth/index.ts", - "./src/ping.ts", - "./src/well-known-handler.ts" + "$schema": "https://typedoc.org/schema.json", + "name": "@libp2p/http", + "exclude": [ + "examples" ] } From 2aabfdbeda641a7b71f71c61e48004322af25e26 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Mon, 28 Apr 2025 18:17:05 +0100 Subject: [PATCH 08/22] chore: convert to monorepo --- examples/package.json | 18 - .../package.json | 2 +- package.json | 2 +- packages/http-client/package.json | 58 -- packages/http-client/src/index.ts | 13 - .../src/middleware/peer-id-auth.ts | 189 ------- packages/http-client/src/websocket/index.ts | 100 ---- packages/http-client/src/websocket/server.ts | 38 -- packages/{http-client => http-fetch}/LICENSE | 0 .../LICENSE-APACHE | 0 .../{http-client => http-fetch}/LICENSE-MIT | 0 packages/http-fetch/README.md | 73 +++ packages/http-fetch/package.json | 152 ++++++ .../src/fetch => http-fetch/src}/body/blob.ts | 0 .../fetch => http-fetch/src}/body/bytes.ts | 2 +- .../src}/body/form-data.ts | 0 .../src}/body/readable-stream.ts | 0 .../fetch => http-fetch/src}/body/string.ts | 0 .../src/fetch => http-fetch/src}/index.ts | 0 .../fetch => http-fetch/src}/read-response.ts | 2 +- .../fetch => http-fetch/src}/send-request.ts | 2 +- .../src/fetch => http-fetch/src}/utils.ts | 0 packages/http-fetch/test/index.spec.ts | 5 + .../{http-client => http-fetch}/tsconfig.json | 0 .../{http-client => http-fetch}/typedoc.json | 0 packages/http-peer-id-auth/LICENSE | 4 + packages/http-peer-id-auth/LICENSE-APACHE | 5 + packages/http-peer-id-auth/LICENSE-MIT | 19 + .../README.md | 2 +- packages/http-peer-id-auth/package.json | 153 ++++++ packages/http-peer-id-auth/src/client.ts | 322 +++++++++++ .../http-peer-id-auth/src}/errors.ts | 10 + packages/http-peer-id-auth/src/index.ts | 146 +++++ packages/http-peer-id-auth/src/server.ts | 127 +++++ packages/http-peer-id-auth/src/utils.ts | 148 ++++++ packages/http-peer-id-auth/src/validation.ts | 17 + packages/http-peer-id-auth/test/index.spec.ts | 100 ++++ packages/http-peer-id-auth/tsconfig.json | 10 + packages/http-peer-id-auth/typedoc.json | 5 + packages/http-ping/package.json | 124 ++++- packages/http-ping/src/index.ts | 5 +- packages/http-ping/src/ping.ts | 18 +- packages/http-ping/test/index.spec.ts | 5 + packages/http-server/package.json | 157 +++++- .../src/{fetch.ts => fetch-server.ts} | 15 +- packages/http-server/src/index.ts | 3 +- packages/http-server/src/node-server.ts | 40 ++ .../src/{node.ts => node/handler.ts} | 182 ++++--- .../src/{ => node}/incoming-message.ts | 0 .../src/{ => node}/index.browser.ts | 3 + packages/http-server/src/node/index.ts | 27 + .../src/{ => node}/server-response.ts | 2 +- packages/http-server/src/{ => node}/server.ts | 2 +- .../http-server/src/node/websocket-server.ts | 82 +++ packages/http-server/src/routes/index.ts | 86 --- packages/http-server/src/utils.ts | 24 + packages/http-server/test/index.spec.ts | 5 + packages/http-utils/package.json | 134 ++++- packages/http-utils/src/constants.ts | 77 +++ packages/http-utils/src/index.ts | 502 ++++++++++++++++++ .../src/fetch => http-utils/src}/request.ts | 2 +- .../src/fetch => http-utils/src}/response.ts | 4 +- packages/http-utils/src/utils.ts | 466 ---------------- packages/http-utils/test/index.spec.ts | 5 + packages/http-websocket/LICENSE | 4 + packages/http-websocket/LICENSE-APACHE | 5 + packages/http-websocket/LICENSE-MIT | 19 + packages/http-websocket/README.md | 73 +++ packages/http-websocket/package.json | 163 ++++++ .../src}/events.ts | 0 packages/http-websocket/src/index.ts | 54 ++ .../src}/message.ts | 0 .../websocket => http-websocket/src}/utils.ts | 46 +- .../src}/websocket.ts | 26 +- packages/http-websocket/test/index.spec.ts | 5 + .../http-websocket/test}/message.spec.ts | 2 +- packages/http-websocket/tsconfig.json | 10 + packages/http-websocket/typedoc.json | 5 + packages/http/package.json | 67 +-- packages/http/src/constants.ts | 82 +-- packages/http/src/http.browser.ts | 47 +- packages/http/src/http.ts | 7 +- packages/http/src/index.ts | 123 +++-- .../src/middleware/cookies.ts | 30 +- packages/http/src/middleware/index.ts | 2 + packages/http/src/middleware/origin.ts | 19 + packages/http/src/middleware/peer-id-auth.ts | 182 +++++++ packages/http/src/registrar.ts | 21 +- packages/http/src/routes/index.ts | 2 + .../src/routes/peer-id-auth.ts | 221 ++------ packages/http/src/routes/utils.ts | 28 + .../src/routes/websocket.ts | 11 +- .../src/routes/well-known.ts | 3 +- packages/http/src/utils.ts | 26 + packages/http/test/index.spec.ts | 5 + .aegir.js => packages/interop/.aegir.js | 4 +- packages/interop/LICENSE | 4 + packages/interop/LICENSE-APACHE | 5 + packages/interop/LICENSE-MIT | 19 + packages/interop/README.md | 73 +++ packages/interop/package.json | 180 +++++++ packages/interop/src/index.ts | 1 + .../interop/test}/cookies.spec.ts | 18 +- {test => packages/interop/test}/fetch.spec.ts | 6 +- .../interop/test}/fixtures/create-express.ts | 6 +- .../test}/fixtures/create-fastify-http.ts | 6 +- .../fixtures/create-fastify-websocket.ts | 10 +- .../interop/test}/fixtures/create-http.ts | 6 +- .../test}/fixtures/create-websocket-server.ts | 10 +- .../interop/test}/fixtures/create-wss.ts | 10 +- .../interop/test}/fixtures/get-libp2p.ts | 10 +- .../interop/test}/peer-id-auth.spec.ts | 62 ++- {test => packages/interop/test}/ping.spec.ts | 10 +- .../interop/test}/websockets.spec.ts | 6 +- packages/interop/tsconfig.json | 10 + packages/interop/typedoc.json | 5 + src/auth/agent.browser.ts | 11 - src/auth/agent.ts | 18 - src/auth/client.ts | 253 --------- src/auth/common.ts | 78 --- src/auth/index.ts | 6 - src/auth/server.ts | 291 ---------- src/fetch.ts | 375 ------------- test/auth/index.spec.ts | 103 ---- test/fixtures/to-websocket.ts | 36 -- 125 files changed, 3781 insertions(+), 2833 deletions(-) delete mode 100644 examples/package.json delete mode 100644 packages/http-client/package.json delete mode 100644 packages/http-client/src/index.ts delete mode 100644 packages/http-client/src/middleware/peer-id-auth.ts delete mode 100644 packages/http-client/src/websocket/index.ts delete mode 100644 packages/http-client/src/websocket/server.ts rename packages/{http-client => http-fetch}/LICENSE (100%) rename packages/{http-client => http-fetch}/LICENSE-APACHE (100%) rename packages/{http-client => http-fetch}/LICENSE-MIT (100%) create mode 100644 packages/http-fetch/README.md create mode 100644 packages/http-fetch/package.json rename packages/{http-client/src/fetch => http-fetch/src}/body/blob.ts (100%) rename packages/{http-client/src/fetch => http-fetch/src}/body/bytes.ts (87%) rename packages/{http-client/src/fetch => http-fetch/src}/body/form-data.ts (100%) rename packages/{http-client/src/fetch => http-fetch/src}/body/readable-stream.ts (100%) rename packages/{http-client/src/fetch => http-fetch/src}/body/string.ts (100%) rename packages/{http-client/src/fetch => http-fetch/src}/index.ts (100%) rename packages/{http-client/src/fetch => http-fetch/src}/read-response.ts (98%) rename packages/{http-client/src/fetch => http-fetch/src}/send-request.ts (96%) rename packages/{http-client/src/fetch => http-fetch/src}/utils.ts (100%) create mode 100644 packages/http-fetch/test/index.spec.ts rename packages/{http-client => http-fetch}/tsconfig.json (100%) rename packages/{http-client => http-fetch}/typedoc.json (100%) create mode 100644 packages/http-peer-id-auth/LICENSE create mode 100644 packages/http-peer-id-auth/LICENSE-APACHE create mode 100644 packages/http-peer-id-auth/LICENSE-MIT rename packages/{http-client => http-peer-id-auth}/README.md (98%) create mode 100644 packages/http-peer-id-auth/package.json create mode 100644 packages/http-peer-id-auth/src/client.ts rename {src/auth => packages/http-peer-id-auth/src}/errors.ts (66%) create mode 100644 packages/http-peer-id-auth/src/index.ts create mode 100644 packages/http-peer-id-auth/src/server.ts create mode 100644 packages/http-peer-id-auth/src/utils.ts create mode 100644 packages/http-peer-id-auth/src/validation.ts create mode 100644 packages/http-peer-id-auth/test/index.spec.ts create mode 100644 packages/http-peer-id-auth/tsconfig.json create mode 100644 packages/http-peer-id-auth/typedoc.json create mode 100644 packages/http-ping/test/index.spec.ts rename packages/http-server/src/{fetch.ts => fetch-server.ts} (51%) create mode 100644 packages/http-server/src/node-server.ts rename packages/http-server/src/{node.ts => node/handler.ts} (69%) rename packages/http-server/src/{ => node}/incoming-message.ts (100%) rename packages/http-server/src/{ => node}/index.browser.ts (94%) create mode 100644 packages/http-server/src/node/index.ts rename packages/http-server/src/{ => node}/server-response.ts (99%) rename packages/http-server/src/{ => node}/server.ts (98%) create mode 100644 packages/http-server/src/node/websocket-server.ts delete mode 100644 packages/http-server/src/routes/index.ts create mode 100644 packages/http-server/src/utils.ts create mode 100644 packages/http-server/test/index.spec.ts create mode 100644 packages/http-utils/src/constants.ts rename packages/{http-client/src/fetch => http-utils/src}/request.ts (95%) rename packages/{http-client/src/fetch => http-utils/src}/response.ts (91%) delete mode 100644 packages/http-utils/src/utils.ts create mode 100644 packages/http-utils/test/index.spec.ts create mode 100644 packages/http-websocket/LICENSE create mode 100644 packages/http-websocket/LICENSE-APACHE create mode 100644 packages/http-websocket/LICENSE-MIT create mode 100644 packages/http-websocket/README.md create mode 100644 packages/http-websocket/package.json rename packages/{http-client/src/websocket => http-websocket/src}/events.ts (100%) create mode 100644 packages/http-websocket/src/index.ts rename packages/{http-client/src/websocket => http-websocket/src}/message.ts (100%) rename packages/{http-client/src/websocket => http-websocket/src}/utils.ts (72%) rename packages/{http-client/src/websocket => http-websocket/src}/websocket.ts (94%) create mode 100644 packages/http-websocket/test/index.spec.ts rename {test/websocket => packages/http-websocket/test}/message.spec.ts (98%) create mode 100644 packages/http-websocket/tsconfig.json create mode 100644 packages/http-websocket/typedoc.json rename packages/{http-client => http}/src/middleware/cookies.ts (76%) create mode 100644 packages/http/src/middleware/index.ts create mode 100644 packages/http/src/middleware/origin.ts create mode 100644 packages/http/src/middleware/peer-id-auth.ts create mode 100644 packages/http/src/routes/index.ts rename packages/{http-server => http}/src/routes/peer-id-auth.ts (63%) create mode 100644 packages/http/src/routes/utils.ts rename packages/{http-server => http}/src/routes/websocket.ts (83%) rename packages/{http-server => http}/src/routes/well-known.ts (88%) create mode 100644 packages/http/src/utils.ts create mode 100644 packages/http/test/index.spec.ts rename .aegir.js => packages/interop/.aegir.js (97%) create mode 100644 packages/interop/LICENSE create mode 100644 packages/interop/LICENSE-APACHE create mode 100644 packages/interop/LICENSE-MIT create mode 100644 packages/interop/README.md create mode 100644 packages/interop/package.json create mode 100644 packages/interop/src/index.ts rename {test => packages/interop/test}/cookies.spec.ts (91%) rename {test => packages/interop/test}/fetch.spec.ts (97%) rename {test => packages/interop/test}/fixtures/create-express.ts (88%) rename {test => packages/interop/test}/fixtures/create-fastify-http.ts (89%) rename {test => packages/interop/test}/fixtures/create-fastify-websocket.ts (81%) rename {test => packages/interop/test}/fixtures/create-http.ts (86%) rename {test => packages/interop/test}/fixtures/create-websocket-server.ts (72%) rename {test => packages/interop/test}/fixtures/create-wss.ts (76%) rename {test => packages/interop/test}/fixtures/get-libp2p.ts (89%) rename {test => packages/interop/test}/peer-id-auth.spec.ts (77%) rename {test => packages/interop/test}/ping.spec.ts (96%) rename {test => packages/interop/test}/websockets.spec.ts (96%) create mode 100644 packages/interop/tsconfig.json create mode 100644 packages/interop/typedoc.json delete mode 100644 src/auth/agent.browser.ts delete mode 100644 src/auth/agent.ts delete mode 100644 src/auth/client.ts delete mode 100644 src/auth/common.ts delete mode 100644 src/auth/index.ts delete mode 100644 src/auth/server.ts delete mode 100644 src/fetch.ts delete mode 100644 test/auth/index.spec.ts delete mode 100644 test/fixtures/to-websocket.ts diff --git a/examples/package.json b/examples/package.json deleted file mode 100644 index 629fa68..0000000 --- a/examples/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "js-libp2p-whatwg-examples", - "version": "0.0.1", - "type": "module", - "dependencies": { - "@chainsafe/libp2p-noise": "^16.0.0", - "@chainsafe/libp2p-yamux": "^7.0.1", - "@hono/node-server": "^1.11.2", - "@libp2p/http-fetch": "file:..", - "@libp2p/peer-id": "^5.0.7", - "@libp2p/tcp": "^10.0.11", - "@multiformats/multiaddr": "^12.3.0", - "@multiformats/multiaddr-to-uri": "^10.1.0", - "hono": "^4.4.4", - "libp2p": "^2.2.1" - }, - "license": "Apache-2.0 OR MIT" -} diff --git a/examples/serving-http-resources-over-libp2p-streams/package.json b/examples/serving-http-resources-over-libp2p-streams/package.json index 95661ca..e4b7b4e 100644 --- a/examples/serving-http-resources-over-libp2p-streams/package.json +++ b/examples/serving-http-resources-over-libp2p-streams/package.json @@ -3,7 +3,7 @@ "type": "module", "private": true, "scripts": { - "test": "test-example test" + "test": "test-node-example test" }, "dependencies": { "@chainsafe/libp2p-gossipsub": "^14.0.0", diff --git a/package.json b/package.json index 9964679..e860f8d 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "private": true, "scripts": { - "reset": "aegir run clean && aegir clean interop/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json interop/*/package-lock.json", + "reset": "aegir run clean && aegir clean examples/*/node_modules packages/*/node_modules node_modules package-lock.json packages/*/package-lock.json examples/*/package-lock.json", "test": "aegir run test", "test:node": "aegir run test:node", "test:chrome": "aegir run test:chrome", diff --git a/packages/http-client/package.json b/packages/http-client/package.json deleted file mode 100644 index 282c9d2..0000000 --- a/packages/http-client/package.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "name": "@libp2p/http-client", - "version": "0.0.0", - "description": "Libp2p-compatible implementations of fetch and WebSockets", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-http.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-http/issues" - }, - "publishConfig": { - "access": "public" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "files": [ - "src", - "dist", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "types": "./dist/src/index.d.ts", - "import": "./dist/src/index.js" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "project": true, - "sourceType": "module" - } - }, - "scripts": { - "build": "aegir build --bundle false", - "test": "aegir test -t node", - "clean": "aegir clean", - "lint": "aegir lint", - "test:node": "aegir test -t node --cov", - "dep-check": "aegir dep-check", - "doc-check": "aegir doc-check" - }, - "dependencies": { - "@libp2p/crypto": "^5.1.1", - "@libp2p/interface": "^2.9.0", - "@libp2p/keychain": "^5.2.1", - "@libp2p/logger": "^5.1.15", - "interface-datastore": "^8.3.1" - }, - "devDependencies": { - "aegir": "^45.1.1" - }, - "sideEffects": false -} \ No newline at end of file diff --git a/packages/http-client/src/index.ts b/packages/http-client/src/index.ts deleted file mode 100644 index 0d2ef17..0000000 --- a/packages/http-client/src/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @packageDocumentation - * - * This module exports libp2p-compatible versions of the [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) - * and [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) - * APIs. - * - * This is necessary because certain features are disabled in browsers but we - * need access to them in order to serve web pages in a runtime-agnostic way. - */ -export * from './fetch/index.js' -export * from './middleware/index.js' -export * from './websocket/index.js' diff --git a/packages/http-client/src/middleware/peer-id-auth.ts b/packages/http-client/src/middleware/peer-id-auth.ts deleted file mode 100644 index e39858c..0000000 --- a/packages/http-client/src/middleware/peer-id-auth.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' -import { InvalidParametersError } from '@libp2p/interface' -import { peerIdFromPublicKey } from '@libp2p/peer-id' -import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' -import { parseHeader, sign, verify } from '../auth/common.js' -import { InvalidPeerError, InvalidSignatureError, MissingAuthHeaderError } from '../auth/errors.js' -import { DEFAULT_AUTH_TOKEN_TTL, PEER_ID_AUTH_SCHEME } from '../constants.js' -import { SEC_WEBSOCKET_PROTOCOL_PREFIX } from '../routes/peer-id-auth.js' -import { getCacheKey, getHost, isWebSocketInit } from '../utils.js' -import type { HTTP, ClientMiddleware, RequestOptions } from '../index.js' -import type { AbortOptions, ComponentLogger, Logger, PeerId, PrivateKey } from '@libp2p/interface' -import type { Multiaddr } from '@multiformats/multiaddr' - -interface AuthToken { - peer: PeerId - expires: number - bearer: string -} - -interface PeerIdAuthComponents { - privateKey: PrivateKey - logger: ComponentLogger - http: HTTP -} - -export interface PeerIdAuthInit { - verifyPeer?(peerId: PeerId): boolean | Promise - ttl?: number -} - -export class PeerIdAuth implements ClientMiddleware { - private readonly components: PeerIdAuthComponents - private readonly log: Logger - private readonly tokens: Map - private readonly tokenTTL: number - private readonly verifyPeer: (peerId: PeerId, options?: AbortOptions) => boolean | Promise - - constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit) { - this.components = components - this.log = components.logger.forComponent('libp2p:http:peer-id-auth') - this.tokens = new Map() - this.tokenTTL = init.ttl ?? DEFAULT_AUTH_TOKEN_TTL - this.verifyPeer = init.verifyPeer ?? (() => true) - } - - async prepareRequest (resource: URL | Multiaddr[], opts: RequestOptions): Promise { - const token = await this.getOrCreateAuthToken(resource, opts) - - if (isWebSocketInit(opts)) { - opts.protocols = [ - ...(opts.protocols ?? []), - `${SEC_WEBSOCKET_PROTOCOL_PREFIX}${btoa(token.bearer)}` - ] - } else { - if (opts.headers.get('authorization') != null) { - throw new InvalidParametersError('Will not overwrite existing Authorization header') - } - - opts.headers.set('Authorization', token.bearer) - } - } - - async getOrCreateAuthToken (resource: URL | Multiaddr[], opts: RequestOptions): Promise { - const key = getCacheKey(resource, opts.headers) - let token = this.tokens.get(key) - - // check token expiry - if (token?.expires != null && token?.expires < Date.now()) { - this.tokens.delete(key) - token = undefined - } - - // create new token - if (token == null) { - token = await this.createAuthToken(resource, opts) - } - - return token - } - - async createAuthToken (resource: URL | Multiaddr[], opts: RequestOptions): Promise { - const hostname = getHost(resource, opts.headers) - - // Client initiated handshake (server initiated is not implemented yet) - const marshalledClientPubKey = publicKeyToProtobuf(this.components.privateKey.publicKey) - const publicKeyStr = uint8ArrayToString(marshalledClientPubKey, 'base64urlpad') - const challengeServer = generateChallenge() - - // copy existing headers - const challengeHeaders = new Headers(opts.headers) - challengeHeaders.delete('connection') - challengeHeaders.delete('upgrade') - challengeHeaders.set('authorization', encodeAuthParams({ - 'challenge-server': challengeServer, - 'public-key': publicKeyStr - })) - - const resp = await this.components.http.fetch(resource, { - method: 'OPTIONS', - headers: challengeHeaders, - signal: opts.signal, - middleware: opts.middleware - .filter(m => m !== this) - .map(m => () => m) - }) - - // verify the server's challenge - const authHeader = resp.headers.get('www-authenticate') - - if (authHeader == null) { - throw new MissingAuthHeaderError('No www-authenticate header in response') - } - - const authFields = parseHeader(authHeader) - const serverPubKeyBytes = uint8ArrayFromString(authFields['public-key'], 'base64urlpad') - const serverPubKey = publicKeyFromProtobuf(serverPubKeyBytes) - - const valid = await verify(serverPubKey, PEER_ID_AUTH_SCHEME, [ - ['hostname', hostname], - ['client-public-key', marshalledClientPubKey], - ['challenge-server', challengeServer]], uint8ArrayFromString(authFields.sig, 'base64urlpad')) - - if (!valid) { - throw new InvalidSignatureError('Invalid signature') - } - - const serverPublicKey = publicKeyFromProtobuf(serverPubKeyBytes) - const serverID = peerIdFromPublicKey(serverPublicKey) - - if (!await this.verifyPeer(serverID, { signal: opts.signal })) { - throw new InvalidPeerError('Id check failed') - } - - const sig = await sign(this.components.privateKey, PEER_ID_AUTH_SCHEME, [ - ['hostname', hostname], - ['server-public-key', serverPubKeyBytes], - ['challenge-client', authFields['challenge-client']]]) - - const authenticateSelfHeaders = encodeAuthParams({ - opaque: authFields.opaque, - sig: uint8ArrayToString(sig, 'base64urlpad') - }) - - const authToken = { - peer: serverID, - expires: Date.now() + this.tokenTTL, - bearer: authenticateSelfHeaders - } - - const key = getCacheKey(resource, opts.headers) - this.tokens.set(key, authToken) - - return authToken - } - - processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): void { - const serverAuthHeader = response.headers.get('authentication-info') - - if (serverAuthHeader != null) { - const key = getCacheKey(resource, opts.headers) - const token = this.tokens.get(key) - - if (token != null) { - const serverAuthFields = parseHeader(serverAuthHeader) - token.bearer = serverAuthFields.bearer - } - } - } -} - -function generateChallenge (): string { - const randomBytes = new Uint8Array(32) - crypto.getRandomValues(randomBytes) - return uint8ArrayToString(randomBytes, 'base64urlpad') -} - -function encodeAuthParams (params: Record): string { - const encodedParams = Object.entries(params) - .map(([key, value]) => `${key}="${value}"`) - .join(', ') - - return `${PEER_ID_AUTH_SCHEME} ${encodedParams}` -} - -export function peerIdAuth (init: PeerIdAuthInit = {}): (component: any) => ClientMiddleware { - return (components) => { - return new PeerIdAuth(components, init) - } -} diff --git a/packages/http-client/src/websocket/index.ts b/packages/http-client/src/websocket/index.ts deleted file mode 100644 index 1b01780..0000000 --- a/packages/http-client/src/websocket/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { WebSocketServer as WebSocketServerClass } from './server.js' -import type { IncomingMessage } from '../http/incoming-message.js' -import type { TypedEventTarget } from '@libp2p/interface' -import type { Duplex } from 'node:stream' - -export interface WebSocketEvents { - 'close': CloseEvent - 'error': Event - 'message': MessageEvent - 'open': Event -} - -export interface CloseListener { - (evt: CloseEvent): void -} - -export interface ErrorListener { - (evt: Event): void -} - -export interface MessageListener { - (evt: MessageEvent): void -} - -export interface OpenListener { - (evt: Event): void -} - -export interface WebSocket extends TypedEventTarget { - CONNECTING: 0 - OPEN: 1 - CLOSING: 2 - CLOSED: 3 - binaryType: BinaryType - bufferedAmount: number - extensions: string - protocol: string - readyState: number - url: string - onopen: OpenListener | null - onmessage: MessageListener | null - onerror: ErrorListener | null - onclose: CloseListener | null - - close (code?: number, reason?: string): void - send (data: string | Blob | Uint8Array | ArrayBuffer | DataView): void -} - -export class ConnectionEvent extends Event { - webSocket: WebSocket - request: IncomingMessage - - constructor (ws: WebSocket, req: IncomingMessage) { - super('connection') - - this.webSocket = ws - this.request = req - } -} - -export interface WebSocketServerEvents { - connection: ConnectionEvent -} - -export interface WebSocketServer extends TypedEventTarget { - handleUpgrade (request: IncomingMessage, socket: Duplex, head: Uint8Array): void -} - -/** - * Creates a WebSocket server that can handle upgrade requests from clients. - * - * Add a listener for the `connection` event to receive incoming WebSocket - * connections. - * - * @example - * - * ```ts - * import { createServer, createWebSocketServer } from '@libp2p/http' - * - * const wss = createWebSocketServer() - * wss.addEventListener('connection', (evt) => { - * const ws = evt.webSocket - * - * ws.on('message', (data) => { - * ws.send(data) - * }) - * }) - * - * const server = createServer((req, res) => { - * // handle HTTP request - * }) - * - * server.addListener('upgrade', (request, socket, head) => { - * wss.handleUpgrade(request, socket, head) - * }) - * `` - */ -export function createWebSocketServer (): WebSocketServer { - return new WebSocketServerClass() -} diff --git a/packages/http-client/src/websocket/server.ts b/packages/http-client/src/websocket/server.ts deleted file mode 100644 index 6c4cb11..0000000 --- a/packages/http-client/src/websocket/server.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { TypedEventEmitter } from '@libp2p/interface' -import { raceEvent } from 'race-event' -import { INTERNAL_SERVER_ERROR } from '../utils.js' -import { ServerWebSocket } from './websocket.js' -import { ConnectionEvent } from './index.js' -import type { WebSocketServerEvents } from './index.js' -import type { IncomingMessage } from '../http/incoming-message.js' -import type { Duplex } from 'node:stream' - -const DEFAULT_UPGRADE_TIMEOUT = 10_000 - -export interface WebSocketServerInit { - upgradeTimeout?: number -} - -export class WebSocketServer extends TypedEventEmitter { - private readonly upgradeTimeout: number - - constructor (init: WebSocketServerInit = {}) { - super() - - this.upgradeTimeout = init.upgradeTimeout ?? DEFAULT_UPGRADE_TIMEOUT - } - - handleUpgrade (request: IncomingMessage, socket: Duplex, head: Uint8Array): void { - Promise.resolve() - .then(async () => { - const ws = new ServerWebSocket(request, socket) - - await raceEvent(ws, 'open', AbortSignal.timeout(this.upgradeTimeout)) - - this.dispatchEvent(new ConnectionEvent(ws, request)) - }) - .catch(() => { - socket.write(INTERNAL_SERVER_ERROR) - }) - } -} diff --git a/packages/http-client/LICENSE b/packages/http-fetch/LICENSE similarity index 100% rename from packages/http-client/LICENSE rename to packages/http-fetch/LICENSE diff --git a/packages/http-client/LICENSE-APACHE b/packages/http-fetch/LICENSE-APACHE similarity index 100% rename from packages/http-client/LICENSE-APACHE rename to packages/http-fetch/LICENSE-APACHE diff --git a/packages/http-client/LICENSE-MIT b/packages/http-fetch/LICENSE-MIT similarity index 100% rename from packages/http-client/LICENSE-MIT rename to packages/http-fetch/LICENSE-MIT diff --git a/packages/http-fetch/README.md b/packages/http-fetch/README.md new file mode 100644 index 0000000..888025e --- /dev/null +++ b/packages/http-fetch/README.md @@ -0,0 +1,73 @@ +# @libp2p/http-fetch + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> libp2p-compatible implementation of the fetch api + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http-fetch/package.json b/packages/http-fetch/package.json new file mode 100644 index 0000000..3f725fb --- /dev/null +++ b/packages/http-fetch/package.json @@ -0,0 +1,152 @@ +{ + "name": "@libp2p/http-fetch", + "version": "0.0.0", + "description": "libp2p-compatible implementation of the fetch api", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "clean": "aegir clean", + "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", + "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" + }, + "dependencies": { + "@achingbrain/http-parser-js": "^0.5.9", + "@libp2p/interface": "^2.2.0", + "@libp2p/http-utils": "^0.0.0", + "it-byte-stream": "^2.0.1", + "uint8arrays": "^5.1.0" + }, + "devDependencies": { + "aegir": "^45.0.0" + }, + "sideEffects": false +} diff --git a/packages/http-client/src/fetch/body/blob.ts b/packages/http-fetch/src/body/blob.ts similarity index 100% rename from packages/http-client/src/fetch/body/blob.ts rename to packages/http-fetch/src/body/blob.ts diff --git a/packages/http-client/src/fetch/body/bytes.ts b/packages/http-fetch/src/body/bytes.ts similarity index 87% rename from packages/http-client/src/fetch/body/bytes.ts rename to packages/http-fetch/src/body/bytes.ts index b17959a..1b0d79c 100644 --- a/packages/http-client/src/fetch/body/bytes.ts +++ b/packages/http-fetch/src/body/bytes.ts @@ -1,4 +1,4 @@ -import { toUint8Array } from '../../utils.js' +import { toUint8Array } from '@libp2p/http-utils' export function bytesBody (bytes: Uint8Array, headers: Headers): ReadableStream { headers.set('Content-Length', `${bytes.byteLength}`) diff --git a/packages/http-client/src/fetch/body/form-data.ts b/packages/http-fetch/src/body/form-data.ts similarity index 100% rename from packages/http-client/src/fetch/body/form-data.ts rename to packages/http-fetch/src/body/form-data.ts diff --git a/packages/http-client/src/fetch/body/readable-stream.ts b/packages/http-fetch/src/body/readable-stream.ts similarity index 100% rename from packages/http-client/src/fetch/body/readable-stream.ts rename to packages/http-fetch/src/body/readable-stream.ts diff --git a/packages/http-client/src/fetch/body/string.ts b/packages/http-fetch/src/body/string.ts similarity index 100% rename from packages/http-client/src/fetch/body/string.ts rename to packages/http-fetch/src/body/string.ts diff --git a/packages/http-client/src/fetch/index.ts b/packages/http-fetch/src/index.ts similarity index 100% rename from packages/http-client/src/fetch/index.ts rename to packages/http-fetch/src/index.ts diff --git a/packages/http-client/src/fetch/read-response.ts b/packages/http-fetch/src/read-response.ts similarity index 98% rename from packages/http-client/src/fetch/read-response.ts rename to packages/http-fetch/src/read-response.ts index f3f406e..3682a80 100644 --- a/packages/http-client/src/fetch/read-response.ts +++ b/packages/http-fetch/src/read-response.ts @@ -1,5 +1,5 @@ import { HTTPParser } from '@achingbrain/http-parser-js' -import { Response } from './response.js' +import { Response } from '@libp2p/http-utils' import type { SendRequestInit } from './index.js' import type { Stream } from '@libp2p/interface' import type { ByteStream } from 'it-byte-stream' diff --git a/packages/http-client/src/fetch/send-request.ts b/packages/http-fetch/src/send-request.ts similarity index 96% rename from packages/http-client/src/fetch/send-request.ts rename to packages/http-fetch/src/send-request.ts index 46b4bdf..b448884 100644 --- a/packages/http-client/src/fetch/send-request.ts +++ b/packages/http-fetch/src/send-request.ts @@ -1,5 +1,5 @@ +import { writeHeaders } from '@libp2p/http-utils' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' -import { writeHeaders } from '../utils.js' import { normalizeContent } from './utils.js' import type { SendRequestInit } from './index.js' import type { Stream } from '@libp2p/interface' diff --git a/packages/http-client/src/fetch/utils.ts b/packages/http-fetch/src/utils.ts similarity index 100% rename from packages/http-client/src/fetch/utils.ts rename to packages/http-fetch/src/utils.ts diff --git a/packages/http-fetch/test/index.spec.ts b/packages/http-fetch/test/index.spec.ts new file mode 100644 index 0000000..b3ed8f6 --- /dev/null +++ b/packages/http-fetch/test/index.spec.ts @@ -0,0 +1,5 @@ +describe('@libp2p/http-fetch', () => { + it('should run a test', () => { + + }) +}) diff --git a/packages/http-client/tsconfig.json b/packages/http-fetch/tsconfig.json similarity index 100% rename from packages/http-client/tsconfig.json rename to packages/http-fetch/tsconfig.json diff --git a/packages/http-client/typedoc.json b/packages/http-fetch/typedoc.json similarity index 100% rename from packages/http-client/typedoc.json rename to packages/http-fetch/typedoc.json diff --git a/packages/http-peer-id-auth/LICENSE b/packages/http-peer-id-auth/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http-peer-id-auth/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http-peer-id-auth/LICENSE-APACHE b/packages/http-peer-id-auth/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http-peer-id-auth/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http-peer-id-auth/LICENSE-MIT b/packages/http-peer-id-auth/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http-peer-id-auth/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http-client/README.md b/packages/http-peer-id-auth/README.md similarity index 98% rename from packages/http-client/README.md rename to packages/http-peer-id-auth/README.md index 365d0e8..d3112e1 100644 --- a/packages/http-client/README.md +++ b/packages/http-peer-id-auth/README.md @@ -5,7 +5,7 @@ [![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) [![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) -> Libp2p-compatible implementations of fetch and WebSockets +> An implementation of Peer ID Authentication over HTTP # About diff --git a/packages/http-peer-id-auth/package.json b/packages/http-peer-id-auth/package.json new file mode 100644 index 0000000..2a0f69f --- /dev/null +++ b/packages/http-peer-id-auth/package.json @@ -0,0 +1,153 @@ +{ + "name": "@libp2p/http-peer-id-auth", + "version": "0.0.0", + "description": "An implementation of Peer ID Authentication over HTTP", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "clean": "aegir clean", + "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", + "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/crypto": "^5.0.6", + "@libp2p/interface": "^2.2.0", + "@libp2p/peer-id": "^5.0.7", + "@multiformats/multiaddr": "^12.3.0", + "uint8-varint": "^2.0.4", + "uint8arrays": "^5.1.0" + }, + "devDependencies": { + "aegir": "^45.0.0" + }, + "sideEffects": false +} diff --git a/packages/http-peer-id-auth/src/client.ts b/packages/http-peer-id-auth/src/client.ts new file mode 100644 index 0000000..f965270 --- /dev/null +++ b/packages/http-peer-id-auth/src/client.ts @@ -0,0 +1,322 @@ +import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' +import { InvalidMessageError } from '@libp2p/interface' +import { peerIdFromPublicKey } from '@libp2p/peer-id' +import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' +import { InvalidPeerError, InvalidSignatureError, InvalidStateError } from './errors.js' +import { decodeAuthorizationHeader, encodeAuthParams, generateChallenge, sign, verify } from './utils.js' +import { PEER_ID_AUTH_SCHEME } from './index.js' +import type { BearerTokenHeader, ClientChallengeResponseHeader, ClientResponse, ServerChallengeHeader, VerifyClientChallengeResponseOptions, VerifyPeer } from './index.js' +import type { PeerId, PrivateKey, PublicKey } from '@libp2p/interface' +import type { AbortOptions } from '@multiformats/multiaddr' + +export function isClientChallengeResponse (obj?: any): obj is ClientChallengeResponseHeader { + if (obj == null) { + return false + } + + return typeof obj['challenge-client'] === 'string' && + typeof obj['public-key'] === 'string' && + typeof obj.sig === 'string' && + typeof obj.opaque === 'string' +} + +export function isServerChallenge (obj?: any): obj is ServerChallengeHeader { + if (obj == null) { + return false + } + + return typeof obj['challenge-client'] === 'string' && + typeof obj['public-key'] === 'string' && + typeof obj.opaque === 'string' +} + +export function isBearerToken (obj: any): obj is BearerTokenHeader { + if (obj == null) { + return false + } + + return typeof obj.bearer === 'string' +} + +/** + * Verify the response to the client challenge created by + * `createClientChallenge` + */ +export async function verifyClientChallengeResponse (authHeader: ClientChallengeResponseHeader, hostname: string, clientKey: PrivateKey, opts: VerifyClientChallengeResponseOptions = {}): Promise { + const serverPubKeyBytes = uint8ArrayFromString(authHeader['public-key'], 'base64urlpad') + const serverPublicKey = publicKeyFromProtobuf(serverPubKeyBytes) + const marshalledClientPubKey = publicKeyToProtobuf(clientKey.publicKey) + + const valid = await verify(serverPublicKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', hostname], + ['client-public-key', marshalledClientPubKey], + ['challenge-server', authHeader['challenge-client']]], + uint8ArrayFromString(authHeader.sig, 'base64urlpad') + ) + + if (!valid) { + throw new InvalidSignatureError('Invalid signature') + } + + const serverID = peerIdFromPublicKey(serverPublicKey) + + if ((await opts.verifyPeer?.(serverID, opts)) === false) { + throw new InvalidPeerError('verifyPeer check failed') + } + + const sig = await sign(clientKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', hostname], + ['server-public-key', serverPubKeyBytes], + ['challenge-client', authHeader['challenge-client']]]) + + return { + peerId: serverID, + authenticate: encodeAuthParams({ + opaque: authHeader.opaque, + sig: uint8ArrayToString(sig, 'base64urlpad') + }) + } +} + +export async function respondToServerChallenge (serverChallenge: ServerChallengeHeader, hostname: string, clientKey: PrivateKey): Promise { + const serverPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(serverChallenge['public-key'], 'base64urlpad')) + const serverPeerId = peerIdFromPublicKey(serverPublicKey) + + // sign and return challenge + const sig = await sign(clientKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', hostname], + ['server-public-key', publicKeyToProtobuf(serverPublicKey)], + ['challenge-client', serverChallenge['challenge-client']] + ]) + + return { + peerId: serverPeerId, + authenticate: encodeAuthParams({ + 'challenge-server': serverChallenge['challenge-client'], + 'public-key': uint8ArrayToString(publicKeyToProtobuf(clientKey.publicKey), 'base64urlpad'), + sig: uint8ArrayToString(sig, 'base64urlpad'), + opaque: serverChallenge.opaque + }) + } +} + +export async function decodeBearerToken (authHeader: BearerTokenHeader, clientKey: PrivateKey, challenge: string, hostname: string, serverPublicKey: PublicKey): Promise { + if (authHeader.sig != null) { + const marshalledClientPubKey = publicKeyToProtobuf(clientKey.publicKey) + const valid = await verify(serverPublicKey, PEER_ID_AUTH_SCHEME, [ + ['challenge-server', challenge], + ['client-public-key', marshalledClientPubKey], + ['hostname', hostname]], + uint8ArrayFromString(authHeader.sig, 'base64urlpad') + ) + + if (!valid) { + throw new InvalidSignatureError('Invalid signature') + } + } + + return authHeader.bearer +} + +type HandshakeState = 'init' | 'challenge-server' | 'verify-server' | 'respond-to-server' | 'complete' + +export class ClientInitiatedHandshake { + private readonly clientKey: PrivateKey + private readonly challenge: string + private readonly hostname: string + private readonly verifyPeer?: VerifyPeer + private state: HandshakeState + public serverId?: PeerId + public bearer?: string + + constructor (clientKey: PrivateKey, hostname: string, verifyPeer?: VerifyPeer) { + this.state = 'init' + this.clientKey = clientKey + this.challenge = generateChallenge() + this.hostname = hostname + this.verifyPeer = verifyPeer + } + + /** + * Step 1, send the server a challenge + */ + getChallenge (): string { + this.state = 'challenge-server' + + return encodeAuthParams({ + 'challenge-server': this.challenge, + 'public-key': uint8ArrayToString(publicKeyToProtobuf(this.clientKey.publicKey), 'base64urlpad') + }) + } + + /** + * Step 2, verify the server response, and answer the server challenge + */ + async verifyServer (header: string, opts?: AbortOptions): Promise { + if (this.state !== 'challenge-server') { + throw new InvalidStateError(`Client Initiated Handshake state was "${this.state}" and not "challenge-server"`) + } + + const message = decodeAuthorizationHeader(header) + + if (!isClientChallengeResponse(message)) { + throw new InvalidMessageError('Server sent incorrect message') + } + + this.state = 'verify-server' + + const serverPubKeyBytes = uint8ArrayFromString(message['public-key'], 'base64urlpad') + const serverPublicKey = publicKeyFromProtobuf(serverPubKeyBytes) + const marshalledClientPubKey = publicKeyToProtobuf(this.clientKey.publicKey) + + const valid = await verify(serverPublicKey, PEER_ID_AUTH_SCHEME, [ + ['challenge-server', message['challenge-client']], + ['client-public-key', marshalledClientPubKey], + ['hostname', this.hostname] + ], uint8ArrayFromString(message.sig, 'base64urlpad')) + + if (!valid) { + throw new InvalidSignatureError('Invalid signature') + } + + this.serverId = peerIdFromPublicKey(serverPublicKey) + + if ((await this.verifyPeer?.(this.serverId, opts)) === false) { + throw new InvalidPeerError('verifyPeer check failed') + } + + const sig = await sign(this.clientKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', this.hostname], + ['server-public-key', serverPubKeyBytes], + ['challenge-client', message['challenge-client']]]) + + this.state = 'respond-to-server' + + return encodeAuthParams({ + opaque: message.opaque, + sig: uint8ArrayToString(sig, 'base64urlpad') + }) + } + + /** + * Step 3, decode the bearer token sent by the server + */ + decodeBearerToken (header: string): string { + if (this.state !== 'respond-to-server') { + throw new InvalidStateError(`Client Initiated Handshake state was "${this.state}" and not "respond-to-server"`) + } + + const message = decodeAuthorizationHeader(header) + + if (!isBearerToken(message)) { + throw new InvalidMessageError('Server sent incorrect message') + } + + this.state = 'complete' + this.bearer = message.bearer + + return encodeAuthParams({ + bearer: this.bearer + }) + } +} + +export class ServerInitiatedHandshake { + private readonly clientKey: PrivateKey + private readonly hostname: string + private readonly verifyPeer?: VerifyPeer + private state: HandshakeState + public serverId?: PeerId + public bearer?: string + private serverPublicKey?: PublicKey + private challenge?: string + + constructor (clientKey: PrivateKey, hostname: string, verifyPeer?: VerifyPeer) { + this.state = 'init' + this.clientKey = clientKey + this.hostname = hostname + this.verifyPeer = verifyPeer + } + + /** + * Step 1 respond to the server challenge and issue our own challenge + */ + async answerServerChallenge (header: string, opts?: AbortOptions): Promise { + if (this.state !== 'init') { + throw new InvalidStateError(`Client Initiated Handshake state was "${this.state}" and not "init"`) + } + + const message = decodeAuthorizationHeader(header) + + if (!isServerChallenge(message)) { + throw new InvalidMessageError('Server sent incorrect message') + } + + this.state = 'verify-server' + + this.serverPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(message['public-key'], 'base64urlpad')) + this.serverId = peerIdFromPublicKey(this.serverPublicKey) + this.challenge = message['challenge-client'] + + // sign and return challenge + const sig = await sign(this.clientKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', this.hostname], + ['server-public-key', publicKeyToProtobuf(this.serverPublicKey)], + ['challenge-client', message['challenge-client']] + ]) + + if ((await this.verifyPeer?.(this.serverId, opts)) === false) { + throw new InvalidPeerError('verifyPeer check failed') + } + + this.state = 'challenge-server' + + return encodeAuthParams({ + 'challenge-server': message['challenge-client'], + 'public-key': uint8ArrayToString(publicKeyToProtobuf(this.clientKey.publicKey), 'base64urlpad'), + sig: uint8ArrayToString(sig, 'base64urlpad'), + opaque: message.opaque + }) + } + + /** + * Step 2, verify the server response and extract the bearer token + */ + async decodeBearerToken (header: string): Promise { + if (this.state !== 'challenge-server') { + throw new InvalidStateError(`Client Initiated Handshake state was "${this.state}" and not "challenge-server"`) + } + + const message = decodeAuthorizationHeader(header) + + if (!isBearerToken(message)) { + throw new InvalidMessageError('Server sent incorrect message') + } + + if (message.sig == null) { + throw new InvalidMessageError('Server sent incorrect message') + } + + if (this.serverPublicKey == null || this.challenge == null) { + throw new InvalidStateError('Server public key and/or challenge missing') + } + + const valid = await verify(this.serverPublicKey, PEER_ID_AUTH_SCHEME, [ + ['hostname', this.hostname], + ['client-public-key', publicKeyToProtobuf(this.clientKey.publicKey)], + ['challenge-server', this.challenge]], + uint8ArrayFromString(message.sig, 'base64urlpad') + ) + + if (!valid) { + throw new InvalidSignatureError('Invalid signature') + } + + this.state = 'complete' + this.bearer = message.bearer + + return encodeAuthParams({ + bearer: this.bearer + }) + } +} diff --git a/src/auth/errors.ts b/packages/http-peer-id-auth/src/errors.ts similarity index 66% rename from src/auth/errors.ts rename to packages/http-peer-id-auth/src/errors.ts index c46d071..17fe4a5 100644 --- a/src/auth/errors.ts +++ b/packages/http-peer-id-auth/src/errors.ts @@ -17,3 +17,13 @@ export class BadResponseError extends Error { static name = 'BadResponseError' name = 'BadResponseError' } + +export class NotAuthenticatedError extends Error { + static name = 'NotAuthenticatedError' + name = 'NotAuthenticatedError' +} + +export class InvalidStateError extends Error { + static name = 'InvalidStateError' + name = 'InvalidStateError' +} diff --git a/packages/http-peer-id-auth/src/index.ts b/packages/http-peer-id-auth/src/index.ts new file mode 100644 index 0000000..724cc96 --- /dev/null +++ b/packages/http-peer-id-auth/src/index.ts @@ -0,0 +1,146 @@ +import { publicKeyToProtobuf } from '@libp2p/crypto/keys' +import { InvalidMessageError } from '@libp2p/interface' +import { toString as uint8ArrayToString } from 'uint8arrays' +import { isClientChallenge, isOpaqueData, isServerChallengeResponse, issueBearerToken, respondToClientChallenge, respondToServerChallengeResponse, unwrapBearerToken } from './server.js' +import { decodeAuthorizationHeader, encodeAuthParams, generateChallenge, genOpaque } from './utils.js' +import type { AbortOptions, PeerId, PrivateKey, PublicKey } from '@libp2p/interface' + +export * from './errors.js' + +export const PEER_ID_AUTH_SCHEME = 'libp2p-PeerID' +export const HTTP_PEER_ID_AUTH_PROTOCOL = '/http-peer-id-auth/1.0.0' +export const DEFAULT_AUTH_TOKEN_TTL = 60 * 60 * 1000 // 1 hour + +export interface ClientChallengeHeader { + 'challenge-server': string + 'public-key': string +} + +export interface ClientChallengeResponseHeader { + 'challenge-client': string + 'public-key': string + sig: string + opaque: string +} + +export interface BearerTokenHeader { + bearer: string + sig?: string +} + +export interface OpaqueDataHeader { + opaque: string + sig: string +} + +export interface ServerChallengeHeader { + 'challenge-client': string + 'public-key': string + opaque: string +} + +export interface ServerChallengeResponseHeader { + 'challenge-server': string + 'public-key': string + opaque: string + sig: string +} + +function isBearerToken (obj: any): obj is BearerTokenHeader { + if (obj == null) { + return false + } + + return typeof obj.bearer === 'string' +} + +export interface ServerResponse { + /** + * The PeerId of the client + */ + peerId: PeerId + + /** + * If present this should be sent to the client as a `authentication-info` + * header + */ + info?: string + + /** + * If present this should be sent to the client as a `www-authenticate` header + */ + authenticate?: string +} + +export interface ClientResponse { + /** + * The PeerId of the server + */ + peerId: PeerId + + /** + * If present this should be sent to the client as a `www-authenticate` header + */ + authenticate?: string + + /** + * If present this should be used for subsequent requests + */ + bearer?: string +} + +export interface VerifyPeer { + (peerId: PeerId, opts?: AbortOptions): boolean | Promise +} + +export interface VerifyClientChallengeResponseOptions extends AbortOptions { + verifyPeer?: VerifyPeer + tokenTTL?: number +} + +export async function createServerChallenge (hostname: string, serverKey: PrivateKey, clientPublicKey?: PublicKey): Promise { + const challenge = generateChallenge() + + return encodeAuthParams({ + 'challenge-client': challenge, + 'public-key': uint8ArrayToString(publicKeyToProtobuf(serverKey.publicKey), 'base64urlpad'), + opaque: await genOpaque(serverKey, { + challengeClient: challenge, + clientPublicKey: clientPublicKey != null ? uint8ArrayToString(publicKeyToProtobuf(clientPublicKey), 'base64urlpad') : undefined, + hostname, + creationTime: Date.now() + }) + }) +} + +/** + * Handle incoming messages from the authenticating client + */ +export async function serverResponds (authHeader: string, hostname: string, serverKey: PrivateKey, tokenTTL: number = DEFAULT_AUTH_TOKEN_TTL): Promise { + const authFields = decodeAuthorizationHeader(authHeader) + + if (isServerChallengeResponse(authFields)) { + return respondToServerChallengeResponse(authFields, hostname, serverKey) + } + + // client initiates authentication + if (isClientChallenge(authFields)) { + return respondToClientChallenge(authFields, hostname, serverKey) + } + + // client is responding to server challenge + if (isOpaqueData(authFields)) { + return issueBearerToken(authFields, hostname, serverKey, tokenTTL) + } + + // client has previously authenticated + if (isBearerToken(authFields)) { + return { + peerId: await unwrapBearerToken(authFields, hostname, serverKey, tokenTTL) + } + } + + throw new InvalidMessageError('Client sent invalid message') +} + +export { ClientInitiatedHandshake, ServerInitiatedHandshake } from './client.js' diff --git a/packages/http-peer-id-auth/src/server.ts b/packages/http-peer-id-auth/src/server.ts new file mode 100644 index 0000000..46bafd1 --- /dev/null +++ b/packages/http-peer-id-auth/src/server.ts @@ -0,0 +1,127 @@ +import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' +import { InvalidMessageError } from '@libp2p/interface' +import { peerIdFromPublicKey, peerIdFromString } from '@libp2p/peer-id' +import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' +import { encodeAuthParams, genBearerToken, genOpaque, sign, unwrapOpaque, verify, verifyBox } from './utils.js' +import { validateOpaqueData } from './validation.js' +import { DEFAULT_AUTH_TOKEN_TTL, PEER_ID_AUTH_SCHEME } from './index.js' +import type { BearerTokenHeader, ClientChallengeHeader, OpaqueDataHeader, ServerChallengeResponseHeader, ServerResponse } from './index.js' +import type { PeerId, PrivateKey } from '@libp2p/interface' + +export function isClientChallenge (obj: any): obj is ClientChallengeHeader { + if (obj == null) { + return false + } + + return typeof obj['challenge-server'] === 'string' && typeof obj['public-key'] === 'string' +} + +export function isOpaqueData (obj: any): obj is OpaqueDataHeader { + if (obj == null) { + return false + } + + return typeof obj.opaque === 'string' && typeof obj.sig === 'string' +} + +export function isServerChallengeResponse (obj?: any): obj is ServerChallengeResponseHeader { + if (obj == null) { + return false + } + + return typeof obj['challenge-server'] === 'string' && + typeof obj['public-key'] === 'string' && + typeof obj.opaque === 'string' && + typeof obj.sig === 'string' +} + +export async function issueBearerToken (data: OpaqueDataHeader, hostname: string, serverKey: PrivateKey, tokenTTL: number): Promise { + const opaque = await unwrapOpaque(serverKey.publicKey, data) + validateOpaqueData(opaque, hostname, tokenTTL) + + const clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(opaque.clientPublicKey, 'base64urlpad')) + const clientPeerId = peerIdFromPublicKey(clientPublicKey) + + const valid = await verify(clientPublicKey, PEER_ID_AUTH_SCHEME, [ + ['challenge-client', opaque.challengeClient], + ['hostname', hostname], + ['server-public-key', publicKeyToProtobuf(serverKey.publicKey)] + ], uint8ArrayFromString(data.sig, 'base64urlpad')) + + if (!valid) { + throw new InvalidMessageError('Invalid signature') + } + + // return a bearer token + return { + peerId: clientPeerId, + info: encodeAuthParams({ + bearer: await genBearerToken(serverKey, clientPeerId, hostname) + }) + } +} + +export async function respondToClientChallenge (clientChallenge: ClientChallengeHeader, hostname: string, serverKey: PrivateKey): Promise { + const clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(clientChallenge['public-key'], 'base64urlpad')) + const clientPeerId = peerIdFromPublicKey(clientPublicKey) + + // sign and return challenge + const sig = await sign(serverKey, PEER_ID_AUTH_SCHEME, [ + ['challenge-server', clientChallenge['challenge-server']], + ['client-public-key', publicKeyToProtobuf(clientPublicKey)], + ['hostname', hostname] + ]) + + return { + peerId: clientPeerId, + authenticate: encodeAuthParams({ + 'challenge-client': clientChallenge['challenge-server'], + 'public-key': uint8ArrayToString(publicKeyToProtobuf(serverKey.publicKey), 'base64urlpad'), + sig: uint8ArrayToString(sig, 'base64urlpad'), + opaque: await genOpaque(serverKey, { + challengeClient: clientChallenge['challenge-server'], + creationTime: Date.now(), + hostname, + clientPublicKey: clientChallenge['public-key'] + }) + }) + } +} + +export async function respondToServerChallengeResponse (response: ServerChallengeResponseHeader, hostname: string, serverKey: PrivateKey): Promise { + const clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(response['public-key'], 'base64urlpad')) + const clientPeerId = peerIdFromPublicKey(clientPublicKey) + + // sign and return challenge + const sig = await sign(serverKey, PEER_ID_AUTH_SCHEME, [ + ['challenge-server', response['challenge-server']], + ['client-public-key', publicKeyToProtobuf(clientPublicKey)], + ['hostname', hostname] + ]) + + return { + peerId: clientPeerId, + info: encodeAuthParams({ + sig: uint8ArrayToString(sig, 'base64urlpad'), + bearer: await genBearerToken(serverKey, clientPeerId, hostname) + }) + } +} + +export async function unwrapBearerToken (token: BearerTokenHeader, expectedHostname: string, privateKey: PrivateKey, tokenTTL: number): Promise { + const unwrapped = await verifyBox(privateKey.publicKey, token.bearer) as any + + if (typeof unwrapped.peer !== 'string' || typeof unwrapped.h !== 'string' || typeof unwrapped.t !== 'number') { + throw new InvalidMessageError('Invalid bearer token') + } + + if (unwrapped.h !== expectedHostname) { + throw new InvalidMessageError('Invalid hostname') + } + + if (Date.now() - unwrapped.t > (tokenTTL ?? DEFAULT_AUTH_TOKEN_TTL)) { + throw new InvalidMessageError('Token expired') + } + + return peerIdFromString(unwrapped.peer) +} diff --git a/packages/http-peer-id-auth/src/utils.ts b/packages/http-peer-id-auth/src/utils.ts new file mode 100644 index 0000000..c29d2d7 --- /dev/null +++ b/packages/http-peer-id-auth/src/utils.ts @@ -0,0 +1,148 @@ +import { InvalidMessageError } from '@libp2p/interface' +import * as varint from 'uint8-varint' +import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' +import { PEER_ID_AUTH_SCHEME } from './index.js' +import type { OpaqueDataHeader } from './index.js' +import type { PeerId, PrivateKey, PublicKey } from '@libp2p/interface' + +export interface OpaqueUnwrapped { + challengeClient: string + clientPublicKey?: string + hostname: string + creationTime: number +} + +export const MAX_AUTH_HEADER_SIZE = 2048 + +export function generateChallenge (): string { + const randomBytes = new Uint8Array(32) + crypto.getRandomValues(randomBytes) + return uint8ArrayToString(randomBytes, 'base64urlpad') +} + +export function encodeAuthParams (params: Record): string { + const encodedParams = Object.entries(params) + .map(([key, value]) => `${key}="${value}"`) + .join(', ') + + return `${PEER_ID_AUTH_SCHEME} ${encodedParams}` +} + +export async function sign (key: PrivateKey, prefix: string, partsToSign: Array<[string, string | Uint8Array]>): Promise { + const dataToSign = genDataToSign(prefix, partsToSign) + return key.sign(dataToSign) +} + +export async function verify (key: PublicKey, prefix: string, partsToSign: Array<[string, string | Uint8Array]>, sig: Uint8Array): Promise { + const dataToSign = genDataToSign(prefix, partsToSign) + return key.verify(dataToSign, sig) +} + +const textEncoder = new TextEncoder() + +function sizeOfPart ([k, v]: [string, string | Uint8Array]): number { + return k.length + 1 + v.length // key + '=' + value +} + +function genDataToSign (prefix: string, partsToSign: Array<[string, string | Uint8Array]>): Uint8Array { + // Sort the parts + partsToSign.sort((a, b) => a[0].localeCompare(b[0])) + + const size = partsToSign.reduce((acc, p) => acc + varint.encodingLength(sizeOfPart(p)) + sizeOfPart(p), prefix.length) + const out = new Uint8Array(size) + let offset = 0 + const res = textEncoder.encodeInto(prefix, out) + offset += res.written + + for (const [k, v] of partsToSign) { + const len = sizeOfPart([k, v]) + varint.encodeUint8Array(len, out, offset) + offset += varint.encodingLength(len) + let res = textEncoder.encodeInto(k, out.subarray(offset)) + offset += res.written + res = textEncoder.encodeInto('=', out.subarray(offset)) + offset += res.written + + if (typeof v === 'string') { + res = textEncoder.encodeInto(v, out.subarray(offset)) + offset += res.written + } else { + out.set(v, offset) + offset += v.length + } + } + + return out +} + +export function decodeAuthorizationHeader (header: string): unknown { + if (header.length < PEER_ID_AUTH_SCHEME.length + 1) { + throw new InvalidMessageError('Serialized token too short') + } + + if (header.length > MAX_AUTH_HEADER_SIZE) { + throw new InvalidMessageError('Serialized token too long') + } + + if (!header.includes(PEER_ID_AUTH_SCHEME)) { + throw new InvalidMessageError('No peer id auth scheme found') + } + + const rest = header.substring(PEER_ID_AUTH_SCHEME.length).trim() + const params: Record = {} + const regex = /(\w[^=]+)="([^"]+)"/g + + let match + while ((match = regex.exec(rest)) !== null) { + params[match[1]] = match[2] + } + + return params +} + +export async function genOpaque (privateKey: PrivateKey, unwrapped: OpaqueUnwrapped): Promise { + return signBox(privateKey, unwrapped) +} + +export async function unwrapOpaque (publicKey: PublicKey, data: OpaqueDataHeader): Promise { + const unwrapped = await verifyBox(publicKey, data.opaque) as any + + if (typeof unwrapped.challengeClient !== 'string' || typeof unwrapped.hostname !== 'string' || typeof unwrapped.creationTime !== 'number') { + throw new Error('Invalid opaque') + } + + return unwrapped +} + +export async function signBox (key: PrivateKey, data: unknown): Promise { + const dataSerialized = JSON.stringify(data) + const dataBytes = uint8ArrayFromString(dataSerialized) + const sig = await key.sign(dataBytes) + const jsonStr = JSON.stringify({ + val: uint8ArrayToString(dataBytes, 'base64urlpad'), + sig: uint8ArrayToString(sig, 'base64urlpad') + }) + + return uint8ArrayToString(uint8ArrayFromString(jsonStr), 'base64urlpad') +} + +export async function verifyBox (key: PublicKey, data: string): Promise { + const { sig, val } = JSON.parse(uint8ArrayToString(uint8ArrayFromString(data, 'base64urlpad'))) + const valBytes = uint8ArrayFromString(val, 'base64urlpad') + const sigValid = await key.verify(valBytes, uint8ArrayFromString(sig, 'base64urlpad')) + + if (!sigValid) { + throw new Error('Invalid signature') + } + + const valStr = uint8ArrayToString(valBytes) + return JSON.parse(valStr) +} + +export async function genBearerToken (serverKey: PrivateKey, clientPeerId: PeerId, hostname: string): Promise { + return signBox(serverKey, { + peer: clientPeerId.toString(), + h: hostname, + t: Date.now() + }) +} diff --git a/packages/http-peer-id-auth/src/validation.ts b/packages/http-peer-id-auth/src/validation.ts new file mode 100644 index 0000000..ae9f2e8 --- /dev/null +++ b/packages/http-peer-id-auth/src/validation.ts @@ -0,0 +1,17 @@ +import { InvalidMessageError } from '@libp2p/interface' +import type { OpaqueUnwrapped } from './utils.js' + +export function validateOpaqueData (opaque: OpaqueUnwrapped, hostname: string, tokenTTL: number): void { + if (opaque.hostname !== hostname) { + throw new InvalidMessageError('Invalid hostname') + } + + // verify signature + if (opaque.challengeClient == null) { + throw new InvalidMessageError('Missing challenge-client') + } + + if (Date.now() - opaque.creationTime > tokenTTL) { + throw new InvalidMessageError('Token expired') + } +} diff --git a/packages/http-peer-id-auth/test/index.spec.ts b/packages/http-peer-id-auth/test/index.spec.ts new file mode 100644 index 0000000..055f1f8 --- /dev/null +++ b/packages/http-peer-id-auth/test/index.spec.ts @@ -0,0 +1,100 @@ +/* eslint-env mocha */ +import { generateKeyPair, privateKeyFromProtobuf } from '@libp2p/crypto/keys' +import { peerIdFromPrivateKey } from '@libp2p/peer-id' +import { expect } from 'aegir/chai' +import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' +import { ClientInitiatedHandshake, ServerInitiatedHandshake } from '../src/client.js' +import { PEER_ID_AUTH_SCHEME, createServerChallenge, serverResponds } from '../src/index.js' +import { sign } from '../src/utils.js' +import type { PeerId, PrivateKey } from '@libp2p/interface' + +describe('@libp2p/http-peer-id-auth', () => { + let init = false + let clientPrivateKey: PrivateKey + let serverPrivateKey: PrivateKey + let serverPeerId: PeerId + let clientPeerId: PeerId + const hostname = 'example.com' + + beforeEach(async () => { + if (!init) { + init = true + clientPrivateKey = await generateKeyPair('Ed25519') + clientPeerId = peerIdFromPrivateKey(clientPrivateKey) + serverPrivateKey = await generateKeyPair('Ed25519') + serverPeerId = peerIdFromPrivateKey(serverPrivateKey) + } + }) + + it('should allow client to initiate authentication', async () => { + const client = new ClientInitiatedHandshake(clientPrivateKey, hostname) + + const clientChallenge = client.getChallenge() + + // server responds to client challenge, issues server challenge + const serverResponse = await serverResponds(clientChallenge, hostname, serverPrivateKey) + expect(serverResponse.peerId).to.deep.equal(clientPeerId) + + if (serverResponse.authenticate == null) { + throw new Error('Server did not challenge client') + } + + // client verifies server response and responds to server challenge + const clientAnswer = await client.verifyServer(serverResponse.authenticate) + + // client responds to the server challenge + const serverResponse2 = await serverResponds(clientAnswer, hostname, serverPrivateKey) + expect(serverResponse2.peerId).to.deep.equal(clientPeerId) + + if (serverResponse2.info == null) { + throw new Error('Server did not issue bearer token') + } + + // read bearer token from response + const bearer = client.decodeBearerToken(serverResponse2.info) + + // use the bearer token for a subsequent request + const serverResponse3 = await serverResponds(bearer, hostname, serverPrivateKey) + expect(serverResponse3.peerId).to.deep.equal(clientPeerId) + + expect(client.serverId).to.deep.equal(serverPeerId) + }) + + it('should allow server to initiate authentication', async () => { + const client = new ServerInitiatedHandshake(clientPrivateKey, hostname) + + const serverChallenge = await createServerChallenge(hostname, serverPrivateKey) + + // client responds to server challenge, issues client challenge + const clientResponse = await client.answerServerChallenge(serverChallenge) + expect(client.serverId).to.deep.equal(serverPeerId) + + // server responds to client challenge, issues bearer token with signature + const serverResponse = await serverResponds(clientResponse, hostname, serverPrivateKey) + expect(serverResponse.peerId).to.deep.equal(clientPeerId) + + if (serverResponse.info == null) { + throw new Error('Server did not issue bearer token') + } + + const bearer = await client.decodeBearerToken(serverResponse.info) + + // use the bearer token for a subsequent request + const serverResponse2 = await serverResponds(bearer, hostname, serverPrivateKey) + expect(serverResponse2.peerId).to.deep.equal(clientPeerId) + }) + + it('should match the test vectors', async () => { + const clientKeyHex = '080112208139770ea87d175f56a35466c34c7ecccb8d8a91b4ee37a25df60f5b8fc9b394' + const serverKeyHex = '0801124001010101010101010101010101010101010101010101010101010101010101018a88e3dd7409f195fd52db2d3cba5d72ca6709bf1d94121bf3748801b40f6f5c' + const clientPubKeyEncoded = uint8ArrayFromString(clientKeyHex, 'base16') + const serverKey = privateKeyFromProtobuf(uint8ArrayFromString(serverKeyHex, 'base16')) + + const serverSig = await sign(serverKey, PEER_ID_AUTH_SCHEME, [ + ['challenge-server', 'ERERERERERERERERERERERERERERERERERERERERERE='], + ['client-public-key', clientPubKeyEncoded], + ['hostname', 'example.com'] + ]) + expect(uint8ArrayToString(serverSig, 'base64urlpad')).to.equal('UA88qZbLUzmAxrD9KECbDCgSKAUBAvBHrOCF2X0uPLR1uUCF7qGfLPc7dw3Olo-LaFCDpk5sXN7TkLWPVvuXAA==') + }) +}) diff --git a/packages/http-peer-id-auth/tsconfig.json b/packages/http-peer-id-auth/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/http-peer-id-auth/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/http-peer-id-auth/typedoc.json b/packages/http-peer-id-auth/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http-peer-id-auth/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/packages/http-ping/package.json b/packages/http-ping/package.json index c2d10bc..9bc69ef 100644 --- a/packages/http-ping/package.json +++ b/packages/http-ping/package.json @@ -3,16 +3,17 @@ "version": "0.0.0", "description": "An HTTP version of the ping protocol", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", "repository": { "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-http.git" + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" }, "bugs": { - "url": "https://github.com/libp2p/js-libp2p-http/issues" + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" }, "publishConfig": { - "access": "public" + "access": "public", + "provenance": true }, "type": "module", "types": "./dist/src/index.d.ts", @@ -35,24 +36,119 @@ "sourceType": "module" } }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "build": "aegir build --bundle false", - "test": "aegir test -t node", + "build": "aegir build", "clean": "aegir clean", "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", "dep-check": "aegir dep-check", - "doc-check": "aegir doc-check" + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" }, "dependencies": { - "@libp2p/crypto": "^5.1.1", - "@libp2p/interface": "^2.9.0", - "@libp2p/keychain": "^5.2.1", - "@libp2p/logger": "^5.1.15", - "interface-datastore": "^8.3.1" + "@libp2p/http": "^0.0.0", + "@libp2p/http-utils": "^0.0.0", + "@libp2p/interface": "^2.2.0", + "@multiformats/multiaddr": "^12.3.0", + "race-event": "^1.3.0", + "race-signal": "^1.1.3", + "uint8arrays": "^5.1.0" }, "devDependencies": { - "aegir": "^45.1.1" + "aegir": "^45.0.0" }, "sideEffects": false -} \ No newline at end of file +} diff --git a/packages/http-ping/src/index.ts b/packages/http-ping/src/index.ts index 13c0c94..c9780a7 100644 --- a/packages/http-ping/src/index.ts +++ b/packages/http-ping/src/index.ts @@ -1,6 +1,5 @@ -// http-ping implementation import { PingHTTPService as PingHTTPServiceClass } from './ping.js' -import type { FetchInit, WebSocketInit, HTTP } from '../index.js' +import type { HTTP, FetchInit, ConnectInit } from '@libp2p/http' import type { ComponentLogger, PeerId } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -14,7 +13,7 @@ export interface PingHTTPComponents { export interface PingHTTPOptions extends FetchInit { } -export interface PingWebSocketOptions extends WebSocketInit { +export interface PingWebSocketOptions extends ConnectInit { /** * Make a request over a WebSocket instead of HTTP */ diff --git a/packages/http-ping/src/ping.ts b/packages/http-ping/src/ping.ts index 59c7225..6664824 100644 --- a/packages/http-ping/src/ping.ts +++ b/packages/http-ping/src/ping.ts @@ -1,11 +1,9 @@ -// http-ping implementation +import { authenticatedWebSocketRoute } from '@libp2p/http' +import { toMultiaddrs } from '@libp2p/http-utils' import { ProtocolError, serviceDependencies } from '@libp2p/interface' import { raceEvent } from 'race-event' import { raceSignal } from 'race-signal' import { equals as uint8ArrayEquals } from 'uint8arrays/equals' -import { Response } from '../fetch/response.js' -import { authenticatedWebSocketRoute } from '../routes/peer-id-auth.js' -import { toMultiaddrs } from '../utils.js' import { HTTP_PING_PROTOCOL } from './index.js' import type { PingHTTPComponents, PingHTTP as PingHTTPInterface, PingHTTPOptions, PingWebSocketOptions } from './index.js' import type { Logger, PeerId, Startable } from '@libp2p/interface' @@ -117,7 +115,8 @@ export class PingHTTPService implements PingHTTPInterface, Startable { const res = await this.components.http.fetch(dialTarget, { ...options, method: 'POST', - body: buf + body: buf, + signal: options.signal ?? undefined }) if (res.status !== 200) { @@ -127,12 +126,15 @@ export class PingHTTPService implements PingHTTPInterface, Startable { return res.arrayBuffer() } - async webSocketPing (dialTarget: Multiaddr[], buf: Uint8Array, options: PingWebSocketOptions): Promise { + async webSocketPing (dialTarget: Multiaddr[], buf: Uint8Array, options: PingHTTPOptions): Promise { this.log('opening websocket connection to %a', dialTarget) - const socket = await this.components.http.connect(dialTarget, options) + const socket = await this.components.http.connect(dialTarget, { + ...options, + signal: options.signal ?? undefined + }) if (socket.readyState !== WebSocket.OPEN) { - await raceEvent(socket, 'open', options.signal) + await raceEvent(socket, 'open', options.signal ?? undefined) this.log('websocket connection to %a open', dialTarget) } diff --git a/packages/http-ping/test/index.spec.ts b/packages/http-ping/test/index.spec.ts new file mode 100644 index 0000000..a1c577b --- /dev/null +++ b/packages/http-ping/test/index.spec.ts @@ -0,0 +1,5 @@ +describe('@libp2p/http-ping', () => { + it('should run a test', () => { + + }) +}) diff --git a/packages/http-server/package.json b/packages/http-server/package.json index 0643ef1..a313117 100644 --- a/packages/http-server/package.json +++ b/packages/http-server/package.json @@ -3,19 +3,36 @@ "version": "0.0.0", "description": "An HTTP version of the ping protocol", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", "repository": { "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-http.git" + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" }, "bugs": { - "url": "https://github.com/libp2p/js-libp2p-http/issues" + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" }, "publishConfig": { - "access": "public" + "access": "public", + "provenance": true }, "type": "module", "types": "./dist/src/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ], + "src/*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ] + } + }, "files": [ "src", "dist", @@ -26,6 +43,11 @@ ".": { "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" + }, + "./node": { + "types": "./dist/src/node/index.d.ts", + "browser": "./dist/src/node/index.browser.js", + "import": "./dist/src/node/index.js" } }, "eslintConfig": { @@ -35,24 +57,129 @@ "sourceType": "module" } }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "build": "aegir build --bundle false", - "test": "aegir test -t node", + "build": "aegir build", "clean": "aegir clean", "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", "test:node": "aegir test -t node --cov", - "dep-check": "aegir dep-check", - "doc-check": "aegir doc-check" + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check -i events -i readable-stream", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" }, "dependencies": { - "@libp2p/crypto": "^5.1.1", - "@libp2p/interface": "^2.9.0", - "@libp2p/keychain": "^5.2.1", - "@libp2p/logger": "^5.1.15", - "interface-datastore": "^8.3.1" + "@achingbrain/http-parser-js": "^0.5.9", + "@libp2p/http": "^0.0.0", + "@libp2p/http-utils": "^0.0.0", + "@libp2p/http-websocket": "^0.0.0", + "@libp2p/interface": "^2.2.0", + "events": "^3.3.0", + "race-event": "^1.3.0", + "readable-stream": "^4.7.0", + "uint8arrays": "^5.1.0", + "ws": "^8.18.1" }, "devDependencies": { - "aegir": "^45.1.1" + "aegir": "^45.0.0" + }, + "browser": { + "./dist/src/node/index.js": "./dist/src/node/index.browser.js", + "node:events": "events", + "node:stream": "readable-stream", + "node:http": false, + "undici": false }, "sideEffects": false -} \ No newline at end of file +} diff --git a/packages/http-server/src/fetch.ts b/packages/http-server/src/fetch-server.ts similarity index 51% rename from packages/http-server/src/fetch.ts rename to packages/http-server/src/fetch-server.ts index 0bab821..0b0de5e 100644 --- a/packages/http-server/src/fetch.ts +++ b/packages/http-server/src/fetch-server.ts @@ -1,5 +1,6 @@ -import { responseToStream, streamToRequest } from '../utils.js' -import type { Endpoint, HeaderInfo } from '../index.js' +import { responseToStream, streamToRequest } from '@libp2p/http-utils' +import type { WebServer } from '@libp2p/http' +import type { HeaderInfo } from '@libp2p/http-utils' import type { Stream, Connection } from '@libp2p/interface' export interface Fetch { @@ -10,7 +11,7 @@ export interface FetchServerInit { server: Fetch } -export class FetchServer implements Endpoint { +class FetchServer implements WebServer { private readonly server: Fetch constructor (init: FetchServerInit) { @@ -22,3 +23,11 @@ export class FetchServer implements Endpoint { await responseToStream(res, stream) } } + +/** + * A WebServer implementation that lets W3C Request/Response-orientated servers + * accept incoming HTTP requests opened over libp2p streams + */ +export function fetchServer (server: Fetch): WebServer { + return new FetchServer({ server }) +} diff --git a/packages/http-server/src/index.ts b/packages/http-server/src/index.ts index f5701de..ad82307 100644 --- a/packages/http-server/src/index.ts +++ b/packages/http-server/src/index.ts @@ -1 +1,2 @@ -export { createServer } from 'node:http' +export { fetchServer } from './fetch-server.js' +export { nodeServer } from './node-server.js' diff --git a/packages/http-server/src/node-server.ts b/packages/http-server/src/node-server.ts new file mode 100644 index 0000000..48b68d8 --- /dev/null +++ b/packages/http-server/src/node-server.ts @@ -0,0 +1,40 @@ +import { streamToSocket } from '@libp2p/http-utils' +import type { WebServer } from '@libp2p/http' +import type { HeaderInfo } from '@libp2p/http-utils' +import type { Stream, Connection } from '@libp2p/interface' +import type { Socket } from 'node:net' + +export interface ConnectionHandler { + emit (event: 'connection', socket: Socket): void +} + +export interface NodeServerInit { + server: ConnectionHandler +} + +class NodeServer implements WebServer { + private readonly server: ConnectionHandler + + constructor (init: NodeServerInit) { + this.server = init.server + } + + async inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise { + // re-yield the headers to enable node to set up the request properly + const streamSource = stream.source + stream.source = (async function * () { + yield info.raw + yield * streamSource + })() + + this.server.emit('connection', streamToSocket(stream, connection)) + } +} + +/** + * A WebServer implementation that lets `node.HTTPServer` instances accept + * incoming HTTP requests opened over libp2p streams + */ +export function nodeServer (server: ConnectionHandler): WebServer { + return new NodeServer({ server }) +} diff --git a/packages/http-server/src/node.ts b/packages/http-server/src/node/handler.ts similarity index 69% rename from packages/http-server/src/node.ts rename to packages/http-server/src/node/handler.ts index 6bb11d3..8e5acca 100644 --- a/packages/http-server/src/node.ts +++ b/packages/http-server/src/node/handler.ts @@ -1,39 +1,110 @@ -import { streamToSocket } from '../stream-to-socket.js' +import { normalizeUrl } from '@libp2p/http-utils' import { readableToReadableStream } from '../utils.js' -import type { Endpoint, HTTP, HeaderInfo } from '../index.js' -import type { Stream, Connection, Libp2p } from '@libp2p/interface' +import type { HTTP } from '@libp2p/http' +import type { Libp2p } from '@libp2p/interface' import type { ServerResponse, IncomingMessage } from 'node:http' -import type { Socket } from 'node:net' - -export interface ConnectionHandler { - emit (event: 'connection', socket: Socket): void +import type { WebSocket as WSSWebSocket } from 'ws' + +export interface CanHandle { + /** + * Pass either a WebSocket instance or a IncomingMessage/ServerResponse pair + */ + (ws: WebSocket): boolean + (req: IncomingMessage, res: ServerResponse): boolean } -export interface NodeServerInit { - server: ConnectionHandler -} +/** + * Helper function to determine whether the passed libp2p node handled the + * incoming HTTP or WebSocket request. + * + * @example Delegating handling of HTTP requests + * + * ```ts + * import { createLibp2p } from 'libp2p' + * import { canHandle } from '@libp2p/http/servers' + * import createServer from 'node:http' + * + * const libp2p = await createLibp2p({ + * // ...options + * }) + * + * const handled = canHandle(libp2p) + * + * createServer((req, res) => { + * if (handled(req, res)) { + * // libp2p handled the request, nothing else to do + * return + * } + * + * // handle request normally - pass off to express/fastify/etc or return 404 + * }) + * ``` + */ +export function canHandle (libp2p: Libp2p<{ http: HTTP }>): CanHandle { + return (...args: any[]): boolean => { + if (args.length === 1) { + const ws: WebSocket = args[0] -class NodeServer implements Endpoint { - private readonly server: ConnectionHandler + if (libp2p.services.http.canHandle(ws)) { + libp2p.services.http.onWebSocket(ws) + return true + } + } else if (args.length === 2) { + const req: IncomingMessage = args[0] + const res: ServerResponse = args[1] + + if (libp2p.services.http.canHandle(req)) { + libp2p.services.http.onRequest(incomingMessageToRequest(req)) + .then(result => { + writeResponse(result, res) + }) + .catch(err => { + res.writeHead(500, err.toString()) + res.end() + }) + return true + } + } - constructor (init: NodeServerInit) { - this.server = init.server + return false } +} + +/** + * Adds properties/methods to a `WebSocket` instance from the `ws` module to be + * compatible with the `globalThis.WebSocket` API + */ +export function toWebSocket (ws: WSSWebSocket, req: IncomingMessage): WebSocket { + const url = normalizeUrl(req) + + Object.defineProperty(ws, 'url', { + value: url.toString(), + writable: false + }) + + // @ts-expect-error not a WS/WebSocket method + ws.dispatchEvent = (evt: Event) => { + if (evt.type === 'close') { + ws.emit('close') + } + + if (evt.type === 'open') { + ws.emit('open') + } - async inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise { - // re-yield the headers to enable node to set up the request properly - const streamSource = stream.source - stream.source = (async function * () { - yield info.raw - yield * streamSource - })() + if (evt.type === 'message') { + const m = evt as MessageEvent + ws.emit('data', m.data) + } - this.server.emit('connection', streamToSocket(stream, connection)) + if (evt.type === 'error') { + ws.emit('error', new Error('An error occurred')) + } + ws.emit(evt.type, evt) } -} -export function nodeServer (server: ConnectionHandler): Endpoint { - return new NodeServer({ server }) + // @ts-expect-error ws is now WebSocket + return ws } function incomingMessageToRequest (req: IncomingMessage): Request { @@ -107,64 +178,3 @@ function writeResponse (res: Response, ser: ServerResponse): void { }) } } - -export interface DidHandle { - (...args: any[]): boolean -} - -/** - * Helper function to ascertain whether the passed libp2p node handled the - * incoming HTTP or WebSocket request. - * - * @example Delegating handling of HTTP requests - * - * ```ts - * import { createLibp2p } from 'libp2p' - * import { canHandle } from '@libp2p/http/servers' - * import createServer from 'node:http' - * - * const libp2p = await createLibp2p({ - * // ...options - * }) - * - * const handled = canHandle(libp2p) - * - * createServer((req, res) => { - * if (handled(req, res)) { - * // libp2p handled the request, nothing else to do - * return - * } - * - * // handle request normally - pass off to express/fastify/etc or return 404 - * }) - * ``` - */ -export function canHandle (libp2p: Libp2p<{ http: HTTP }>): DidHandle { - return (...args: any[]): boolean => { - if (args.length === 1) { - const ws: WebSocket = args[0] - - if (libp2p.services.http.canHandle(ws)) { - libp2p.services.http.onWebSocket(ws) - return true - } - } else if (args.length === 2) { - const req: IncomingMessage = args[0] - const res: ServerResponse = args[1] - - if (libp2p.services.http.canHandle(req)) { - libp2p.services.http.onRequest(incomingMessageToRequest(req)) - .then(result => { - writeResponse(result, res) - }) - .catch(err => { - res.writeHead(500, err.toString()) - res.end() - }) - return true - } - } - - return false - } -} diff --git a/packages/http-server/src/incoming-message.ts b/packages/http-server/src/node/incoming-message.ts similarity index 100% rename from packages/http-server/src/incoming-message.ts rename to packages/http-server/src/node/incoming-message.ts diff --git a/packages/http-server/src/index.browser.ts b/packages/http-server/src/node/index.browser.ts similarity index 94% rename from packages/http-server/src/index.browser.ts rename to packages/http-server/src/node/index.browser.ts index fbe13a2..74a141a 100644 --- a/packages/http-server/src/index.browser.ts +++ b/packages/http-server/src/node/index.browser.ts @@ -1,6 +1,9 @@ import { HTTPServer } from './server.js' import type { ServerOptions, RequestListener, IncomingMessage, ServerResponse, Server } from 'node:http' +export { createWebSocketServer } from './websocket-server.js' +export * from './handler.js' + /** * Implements the same interface as `createServer` from `node:http` just without * any node internals. diff --git a/packages/http-server/src/node/index.ts b/packages/http-server/src/node/index.ts new file mode 100644 index 0000000..b5e3b70 --- /dev/null +++ b/packages/http-server/src/node/index.ts @@ -0,0 +1,27 @@ +import type { IncomingMessage } from './incoming-message.js' +import type { ConnectionEvent } from './websocket-server.js' +import type { TypedEventTarget } from '@libp2p/interface' +import type { Duplex } from 'node:stream' + +export { createServer } from 'node:http' +export { createWebSocketServer } from './websocket-server.js' + +export interface HTTPRequestHandler { + (req: Request): Promise +} + +export interface WebSocketHandler { + (ws: WebSocket): void +} + +export interface WebSocketServerEvents { + connection: ConnectionEvent +} + +export interface WebSocketServer extends TypedEventTarget { + handleUpgrade (request: IncomingMessage, socket: Duplex, head: Uint8Array): void +} + +export type { IncomingMessage } +export type { ServerResponse } from './server-response.js' +export * from './handler.js' diff --git a/packages/http-server/src/server-response.ts b/packages/http-server/src/node/server-response.ts similarity index 99% rename from packages/http-server/src/server-response.ts rename to packages/http-server/src/node/server-response.ts index 782c1e8..db6c4b6 100644 --- a/packages/http-server/src/server-response.ts +++ b/packages/http-server/src/node/server-response.ts @@ -1,7 +1,7 @@ import { Writable } from 'node:stream' +import { STATUS_CODES } from '@libp2p/http-utils' import { InvalidParametersError } from '@libp2p/interface' import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' -import { STATUS_CODES } from '../constants.js' import type { IncomingMessage } from './incoming-message.js' import type { OutgoingHttpHeader, OutgoingHttpHeaders } from 'node:http' import type { Socket } from 'node:net' diff --git a/packages/http-server/src/server.ts b/packages/http-server/src/node/server.ts similarity index 98% rename from packages/http-server/src/server.ts rename to packages/http-server/src/node/server.ts index ee56e36..aa80dba 100644 --- a/packages/http-server/src/server.ts +++ b/packages/http-server/src/node/server.ts @@ -1,6 +1,6 @@ import { EventEmitter } from 'node:events' import { HTTPParser } from '@achingbrain/http-parser-js' -import { NOT_IMPLEMENTED_ERROR } from '../utils.js' +import { NOT_IMPLEMENTED_ERROR } from '@libp2p/http-utils' import { IncomingMessage as IncomingMessageClass } from './incoming-message.js' import { ServerResponse as ServerResponseClass } from './server-response.js' import type { ServerOptions, ServerResponse, IncomingMessage } from 'node:http' diff --git a/packages/http-server/src/node/websocket-server.ts b/packages/http-server/src/node/websocket-server.ts new file mode 100644 index 0000000..fe99ac7 --- /dev/null +++ b/packages/http-server/src/node/websocket-server.ts @@ -0,0 +1,82 @@ +import { INTERNAL_SERVER_ERROR } from '@libp2p/http-utils' +import { ServerWebSocket } from '@libp2p/http-websocket' +import { TypedEventEmitter } from '@libp2p/interface' +import { raceEvent } from 'race-event' +import type { IncomingMessage } from './incoming-message.js' +import type { WebSocketServerEvents, WebSocketServer as WebSocketServerInterface } from './index.js' +import type { Duplex } from 'node:stream' + +const DEFAULT_UPGRADE_TIMEOUT = 10_000 + +export interface WebSocketServerInit { + upgradeTimeout?: number +} + +class WebSocketServer extends TypedEventEmitter { + private readonly upgradeTimeout: number + + constructor (init: WebSocketServerInit = {}) { + super() + + this.upgradeTimeout = init.upgradeTimeout ?? DEFAULT_UPGRADE_TIMEOUT + } + + handleUpgrade (request: IncomingMessage, socket: Duplex, head: Uint8Array): void { + Promise.resolve() + .then(async () => { + const ws = new ServerWebSocket(request, socket) + + await raceEvent(ws, 'open', AbortSignal.timeout(this.upgradeTimeout)) + + this.dispatchEvent(new ConnectionEvent(ws, request)) + }) + .catch(() => { + socket.write(INTERNAL_SERVER_ERROR) + }) + } +} + +export class ConnectionEvent extends Event { + webSocket: WebSocket + request: IncomingMessage + + constructor (ws: WebSocket, req: IncomingMessage) { + super('connection') + + this.webSocket = ws + this.request = req + } +} + +/** + * Creates a WebSocket server that can handle upgrade requests from clients. + * + * Add a listener for the `connection` event to receive incoming WebSocket + * connections. + * + * @example + * + * ```ts + * import { createServer, createWebSocketServer } from '@libp2p/http' + * + * const wss = createWebSocketServer() + * wss.addEventListener('connection', (evt) => { + * const ws = evt.webSocket + * + * ws.on('message', (data) => { + * ws.send(data) + * }) + * }) + * + * const server = createServer((req, res) => { + * // handle HTTP request + * }) + * + * server.addListener('upgrade', (request, socket, head) => { + * wss.handleUpgrade(request, socket, head) + * }) + * `` + */ +export function createWebSocketServer (): WebSocketServerInterface { + return new WebSocketServer() +} diff --git a/packages/http-server/src/routes/index.ts b/packages/http-server/src/routes/index.ts deleted file mode 100644 index 9fc16e6..0000000 --- a/packages/http-server/src/routes/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import type { WEBSOCKET_HANDLER } from '../constants.js' -import type { HTTPRequestHandler, WebSocketHandler } from '../index.js' - -/** - * Options used to define a HTTP route that can handle requests - */ -export interface RouteOptions { - /** - * Specify a path to serve the protocol from. If omitted the protocol name - * will be used. - * - * Paths can be looked up from the protocol map using `getProtocolMap()` or by - * making a GET request to `/.well-known/libp2p/protocols`. - */ - path?: string - - /** - * A list of HTTP verbs this handler will respond to. If the handler is found - * but the request method is not present a 405 will be returned. - * - * @default ['GET'] - */ - method?: string | string[] - - /** - * By default all handlers support CORS headers, pass `false` here to disallow - * access to fetch requests. - * - * @default true - */ - cors?: boolean -} - -/** - * A simple route that defines a handler function - */ -export interface HandlerRoute extends RouteOptions { - handler: H -} - -/** - * A route that requires initialization before use - */ -export interface ServiceRoute extends RouteOptions { - init(components: any): H -} - -/** - * A WebSocket route can make it's handler available for invocation with a - * pre-upgraded WebSocket object - */ -export interface WebSocketRoute { - [WEBSOCKET_HANDLER]?: WebSocketHandler -} - -/** - * A union of the various route types - */ -export type HTTPRoute = (HandlerRoute | ServiceRoute) & WebSocketRoute - -/** - * Returns true if the passed route requires initialization - */ -export function isInitializable , S extends ServiceRoute> (obj: H | S): obj is S { - // @ts-expect-error init is not a property of H - return typeof obj.init === 'function' -} - -/** - * Initializes a `ServiceRoute` and converts it to a `HandlerRoute`. - * - * If the passed route has an `init` method, it invokes it and sets the - * `handler` field on the endpoint with the return value, then deletes the - * `init` property, otherwise it returns the endpoint unaltered. - */ -export function initializeRoute (serviceOrHandler: HTTPRoute, components: any): HandlerRoute { - if (isInitializable(serviceOrHandler)) { - const route: any = serviceOrHandler - route.handler = serviceOrHandler.init(components) - delete route.init - - return route - } - - return serviceOrHandler -} diff --git a/packages/http-server/src/utils.ts b/packages/http-server/src/utils.ts new file mode 100644 index 0000000..c9f0361 --- /dev/null +++ b/packages/http-server/src/utils.ts @@ -0,0 +1,24 @@ +import type { Readable } from 'node:stream' + +export function readableToReadableStream (readable: Readable): ReadableStream { + return new ReadableStream({ + start (controller) { + readable.on('data', buf => { + controller.enqueue(buf) + + // pause until more data requested (backpressure) + readable.pause() + }) + readable.on('end', () => { + controller.close() + }) + readable.on('error', (err) => { + controller.error(err) + }) + }, + pull () { + // let data flow again + readable.resume() + } + }) +} diff --git a/packages/http-server/test/index.spec.ts b/packages/http-server/test/index.spec.ts new file mode 100644 index 0000000..9eb526c --- /dev/null +++ b/packages/http-server/test/index.spec.ts @@ -0,0 +1,5 @@ +describe('@libp2p/http-server', () => { + it('should run a test', () => { + + }) +}) diff --git a/packages/http-utils/package.json b/packages/http-utils/package.json index 07b603d..5663482 100644 --- a/packages/http-utils/package.json +++ b/packages/http-utils/package.json @@ -3,16 +3,17 @@ "version": "0.0.0", "description": "Shared utils and common code for HTTP modules", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-http/tree/main/packages/config#readme", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", "repository": { "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-http.git" + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" }, "bugs": { - "url": "https://github.com/libp2p/js-libp2p-http/issues" + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" }, "publishConfig": { - "access": "public" + "access": "public", + "provenance": true }, "type": "module", "types": "./dist/src/index.d.ts", @@ -35,24 +36,127 @@ "sourceType": "module" } }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, "scripts": { - "build": "aegir build --bundle false", - "test": "aegir test -t node", + "build": "aegir build", "clean": "aegir clean", "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", "test:node": "aegir test -t node --cov", - "dep-check": "aegir dep-check", - "doc-check": "aegir doc-check" + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check -i readable-stream", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" }, "dependencies": { - "@libp2p/crypto": "^5.1.1", - "@libp2p/interface": "^2.9.0", - "@libp2p/keychain": "^5.2.1", - "@libp2p/logger": "^5.1.15", - "interface-datastore": "^8.3.1" + "@libp2p/interface": "^2.2.0", + "@libp2p/peer-id": "^5.0.7", + "@multiformats/multiaddr": "^12.3.0", + "@multiformats/multiaddr-to-uri": "^11.0.0", + "@multiformats/uri-to-multiaddr": "^9.0.1", + "it-byte-stream": "^2.0.1", + "it-queueless-pushable": "^2.0.0", + "it-to-browser-readablestream": "^2.0.10", + "multiformats": "^13.3.2", + "readable-stream": "^4.7.0", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" }, "devDependencies": { - "aegir": "^45.1.1" + "aegir": "^45.0.0" + }, + "browser": { + "node:stream": "readable-stream" }, "sideEffects": false -} \ No newline at end of file +} diff --git a/packages/http-utils/src/constants.ts b/packages/http-utils/src/constants.ts new file mode 100644 index 0000000..72bb937 --- /dev/null +++ b/packages/http-utils/src/constants.ts @@ -0,0 +1,77 @@ +export const HTTP_PATH_CODEC = 0x01e1 +export const HTTP_CODEC = 0x01e0 +export const DNS_CODEC = 0x35 +export const DNS4_CODEC = 0x36 +export const DNS6_CODEC = 0x37 +export const DNSADDR_CODEC = 0x38 +export const DNS_CODECS = [ + DNS_CODEC, + DNS4_CODEC, + DNS6_CODEC, + DNSADDR_CODEC +] +export const STATUS_CODES: Record = { + 100: 'Continue', // RFC 7231 6.2.1 + 101: 'Switching Protocols', // RFC 7231 6.2.2 + 102: 'Processing', // RFC 2518 10.1 (obsoleted by RFC 4918) + 103: 'Early Hints', // RFC 8297 2 + 200: 'OK', // RFC 7231 6.3.1 + 201: 'Created', // RFC 7231 6.3.2 + 202: 'Accepted', // RFC 7231 6.3.3 + 203: 'Non-Authoritative Information', // RFC 7231 6.3.4 + 204: 'No Content', // RFC 7231 6.3.5 + 205: 'Reset Content', // RFC 7231 6.3.6 + 206: 'Partial Content', // RFC 7233 4.1 + 207: 'Multi-Status', // RFC 4918 11.1 + 208: 'Already Reported', // RFC 5842 7.1 + 226: 'IM Used', // RFC 3229 10.4.1 + 300: 'Multiple Choices', // RFC 7231 6.4.1 + 301: 'Moved Permanently', // RFC 7231 6.4.2 + 302: 'Found', // RFC 7231 6.4.3 + 303: 'See Other', // RFC 7231 6.4.4 + 304: 'Not Modified', // RFC 7232 4.1 + 305: 'Use Proxy', // RFC 7231 6.4.5 + 307: 'Temporary Redirect', // RFC 7231 6.4.7 + 308: 'Permanent Redirect', // RFC 7238 3 + 400: 'Bad Request', // RFC 7231 6.5.1 + 401: 'Unauthorized', // RFC 7235 3.1 + 402: 'Payment Required', // RFC 7231 6.5.2 + 403: 'Forbidden', // RFC 7231 6.5.3 + 404: 'Not Found', // RFC 7231 6.5.4 + 405: 'Method Not Allowed', // RFC 7231 6.5.5 + 406: 'Not Acceptable', // RFC 7231 6.5.6 + 407: 'Proxy Authentication Required', // RFC 7235 3.2 + 408: 'Request Timeout', // RFC 7231 6.5.7 + 409: 'Conflict', // RFC 7231 6.5.8 + 410: 'Gone', // RFC 7231 6.5.9 + 411: 'Length Required', // RFC 7231 6.5.10 + 412: 'Precondition Failed', // RFC 7232 4.2 + 413: 'Payload Too Large', // RFC 7231 6.5.11 + 414: 'URI Too Long', // RFC 7231 6.5.12 + 415: 'Unsupported Media Type', // RFC 7231 6.5.13 + 416: 'Range Not Satisfiable', // RFC 7233 4.4 + 417: 'Expectation Failed', // RFC 7231 6.5.14 + 418: 'I\'m a Teapot', // RFC 7168 2.3.3 + 421: 'Misdirected Request', // RFC 7540 9.1.2 + 422: 'Unprocessable Entity', // RFC 4918 11.2 + 423: 'Locked', // RFC 4918 11.3 + 424: 'Failed Dependency', // RFC 4918 11.4 + 425: 'Too Early', // RFC 8470 5.2 + 426: 'Upgrade Required', // RFC 2817 and RFC 7231 6.5.15 + 428: 'Precondition Required', // RFC 6585 3 + 429: 'Too Many Requests', // RFC 6585 4 + 431: 'Request Header Fields Too Large', // RFC 6585 5 + 451: 'Unavailable For Legal Reasons', // RFC 7725 3 + 500: 'Internal Server Error', // RFC 7231 6.6.1 + 501: 'Not Implemented', // RFC 7231 6.6.2 + 502: 'Bad Gateway', // RFC 7231 6.6.3 + 503: 'Service Unavailable', // RFC 7231 6.6.4 + 504: 'Gateway Timeout', // RFC 7231 6.6.5 + 505: 'HTTP Version Not Supported', // RFC 7231 6.6.6 + 506: 'Variant Also Negotiates', // RFC 2295 8.1 + 507: 'Insufficient Storage', // RFC 4918 11.5 + 508: 'Loop Detected', // RFC 5842 7.2 + 509: 'Bandwidth Limit Exceeded', + 510: 'Not Extended', // RFC 2774 7 + 511: 'Network Authentication Required' // RFC 6585 6 +} diff --git a/packages/http-utils/src/index.ts b/packages/http-utils/src/index.ts index a74fb53..a1820f0 100644 --- a/packages/http-utils/src/index.ts +++ b/packages/http-utils/src/index.ts @@ -3,3 +3,505 @@ * * Contains shared code and utilities used by `@libp2p/http-*` modules. */ + +import { InvalidParametersError, isPeerId, ProtocolError } from '@libp2p/interface' +import { peerIdFromString } from '@libp2p/peer-id' +import { fromStringTuples, isMultiaddr, multiaddr } from '@multiformats/multiaddr' +import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' +import { uriToMultiaddr } from '@multiformats/uri-to-multiaddr' +import { queuelessPushable } from 'it-queueless-pushable' +import itToBrowserReadableStream from 'it-to-browser-readablestream' +import { base36 } from 'multiformats/bases/base36' +import { base64pad } from 'multiformats/bases/base64' +import { sha1 } from 'multiformats/hashes/sha1' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { DNS_CODECS, HTTP_CODEC, HTTP_PATH_CODEC } from './constants.js' +import { Request } from './request.js' +import type { AbortOptions, PeerId, Stream } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' +import type { Uint8ArrayList } from 'uint8arraylist' + +/** + * A subset of options passed to middleware + */ +export interface MiddlewareOptions extends AbortOptions { + method: string + headers: Headers + middleware: Middleware[] + credentials?: RequestCredentials + keepalive?: boolean + redirect?: RequestRedirect + integrity?: string + mode?: RequestMode + referrer?: string + referrerPolicy?: ReferrerPolicy +} + +/** + * Middleware that allows augmenting the client request/response with additional + * fields or headers. + */ +export interface Middleware { + /** + * Called before a request is made + */ + prepareRequest?(resource: URL | Multiaddr[], opts: MiddlewareOptions): void | Promise + + /** + * Called after a request is made but before the body has been read - the + * processor may do any necessary housekeeping based on the server response + */ + processResponse?(resource: URL | Multiaddr[], opts: MiddlewareOptions, response: Response): void | Promise +} + +export function toURL (resource: URL | Multiaddr[], headers: Headers): URL { + if (resource instanceof URL) { + return resource + } + + const host = getHost(resource, headers) + const { httpPath } = stripHTTPPath(resource) + + return new URL(`http://${host}${httpPath}`) +} + +/** + * Normalizes byte-like input to a `Uint8Array` + */ +export function toUint8Array (obj: DataView | ArrayBuffer | Uint8Array): Uint8Array { + if (obj instanceof Uint8Array) { + return obj + } + + if (obj instanceof DataView) { + return new Uint8Array(obj.buffer, obj.byteOffset, obj.byteLength) + } + + return new Uint8Array(obj, 0, obj.byteLength) +} + +export function streamToRequest (info: HeaderInfo, stream: Stream): globalThis.Request { + const init: RequestInit = { + method: info.method, + headers: info.headers + } + + if ((init.method !== 'GET' || info.upgrade) && init.method !== 'HEAD') { + let source: AsyncGenerator = stream.source + + if (!info.upgrade) { + source = takeBytes(stream.source, info.headers.get('content-length')) + } + + init.body = itToBrowserReadableStream(source) + // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit + init.duplex = 'half' + } + + return new Request(normalizeUrl(info).toString(), init) +} + +export async function responseToStream (res: Response, stream: Stream): Promise { + const pushable = queuelessPushable() + stream.sink(pushable) + .catch(err => { + stream.abort(err) + }) + + await pushable.push(uint8ArrayFromString([ + `HTTP/1.1 ${res.status} ${res.statusText}`, + ...writeHeaders(res.headers), + '', + '' + ].join('\r\n'))) + + if (res.body == null) { + await pushable.end() + return + } + + const reader = res.body.getReader() + let result = await reader.read() + + while (true) { + if (result.value != null) { + await pushable.push(result.value) + } + + if (result.done) { + break + } + + result = await reader.read() + } + + await pushable.end() + + await stream.closeWrite() + .catch(err => { + stream.abort(err) + }) +} + +export const NOT_FOUND_RESPONSE = uint8ArrayFromString([ + 'HTTP/1.1 404 Not Found', + 'Connection: close', + '', + '' +].join('\r\n')) + +export const BAD_REQUEST = uint8ArrayFromString([ + 'HTTP/1.1 400 Bad Request', + 'Connection: close', + '', + '' +].join('\r\n')) + +export const INTERNAL_SERVER_ERROR = uint8ArrayFromString([ + 'HTTP/1.1 500 Internal Server Error', + 'Connection: close', + '', + '' +].join('\r\n')) + +export const NOT_IMPLEMENTED_ERROR = uint8ArrayFromString([ + 'HTTP/1.1 501 Not Implemented', + 'Connection: close', + '', + '' +].join('\r\n')) + +/** + * Normalizes the dial target to a list of multiaddrs with an optionally + * encapsulated suffix + */ +export function toMultiaddrs (peer: PeerId | Multiaddr | Multiaddr[], suffix?: string): Multiaddr[] { + let mas: Multiaddr[] + + if (isPeerId(peer)) { + mas = [ + multiaddr(`/p2p/${peer}`) + ] + } else if (Array.isArray(peer)) { + mas = peer + } else { + mas = [ + peer + ] + } + + if (suffix != null) { + mas = mas.map(ma => ma.encapsulate(suffix)) + } + + return mas +} + +export function writeHeaders (headers: Headers): string[] { + const output = [] + + if (headers.get('Connection') == null) { + headers.set('Connection', 'close') + } + + for (const [key, value] of headers.entries()) { + output.push(`${key}: ${value}`) + } + + return output +} + +async function * takeBytes (source: AsyncGenerator, bytes?: number | string | null): AsyncGenerator { + bytes = parseInt(`${bytes ?? ''}`) + + if (bytes == null || isNaN(bytes)) { + return source + } + + let count = 0 + + for await (const buf of source) { + count += buf.byteLength + + if (count > bytes) { + yield buf.subarray(0, count - bytes) + return + } + + yield buf.subarray() + + if (count === bytes) { + return + } + } +} + +/** + * Attempts to convert the passed `resource` into a HTTP(s) URL or an array of + * multiaddrs. + * + * The returned URL should be handled by the global fetch, the multiaddr(s) + * should be handled by libp2p. + */ +export function toResource (resource: string | URL | Multiaddr | Multiaddr[]): URL | Multiaddr[] { + if (typeof resource === 'string') { + if (resource.startsWith('/')) { + resource = multiaddr(resource) + } else { + resource = new URL(resource) + } + } + + if (resource instanceof URL) { + if (resource.protocol === 'multiaddr:') { + resource = uriToMultiaddr(resource.toString()) + } + } + + if (isMultiaddr(resource)) { + resource = [resource] + } + + // check for `/http/` tuple and transform to URL if present + if (Array.isArray(resource)) { + for (const ma of resource) { + const stringTuples = ma.stringTuples() + + if (stringTuples.find(([codec]) => codec === HTTP_CODEC) != null) { + const uri = multiaddrToUri(ma) + return new URL(uri) + } + } + } + + return resource +} + +export function getHeaders (init: RequestInit = {}): Headers { + if (init.headers instanceof Headers) { + return init.headers + } + + init.headers = new Headers(init.headers) + + return init.headers +} + +export function getHeader (header: string, headers: HeadersInit = {}): string | undefined { + if (headers instanceof Headers) { + return headers.get(header) ?? undefined + } + + if (Array.isArray(headers)) { + return headers.find(([key, value]) => { + if (key === header) { + return value + } + + return undefined + })?.[1] + } + + return headers[header] +} + +function isValidHost (host?: string): host is string { + return host != null && host !== '' +} + +export function getHost (addresses: URL | Multiaddr[], headers: Headers): string { + let host: string | undefined + let port = 80 + let protocol = 'http:' + + if (addresses instanceof URL) { + host = addresses.hostname + port = parseInt(addresses.port, 10) + protocol = addresses.protocol + } + + if (!isValidHost(host)) { + host = headers.get('host') ?? undefined + } + + // try to extract domain from DNS addresses + if (!isValidHost(host) && Array.isArray(addresses)) { + for (const address of addresses) { + const stringTuples = address.stringTuples() + const filtered = stringTuples.filter(([key]) => DNS_CODECS.includes(key))?.[0]?.[1] + + if (filtered != null) { + host = filtered + break + } + } + } + + // try to use remote PeerId as domain + if (!isValidHost(host) && Array.isArray(addresses)) { + for (const address of addresses) { + const peerStr = address.getPeerId() + + // try to extract port from multiaddr if it is available + try { + const options = address.toOptions() + port = options.port + } catch {} + + if (peerStr != null) { + const peerId = peerIdFromString(peerStr) + // host has to be case-insensitive + host = peerId.toCID().toString(base36) + break + } + } + } + + if (isValidHost(host)) { + // add port if not standard + if (protocol === 'http:' && port !== 80) { + host = `${host}:${port}` + } + + if (protocol === 'https:' && port !== 443) { + host = `${host}:${port}` + } + + return host + } + + throw new InvalidParametersError('Could not determine request host name - a request must have a host header, be made to a DNS-based multiaddr or an http(s) URL') +} + +export function stripHTTPPath (addresses: Multiaddr[]): { httpPath: string, addresses: Multiaddr[] } { + // strip http-path tuple but record the value if set + let httpPath = '/' + addresses = addresses.map(ma => { + return fromStringTuples( + ma.stringTuples().filter(t => { + if (t[0] === HTTP_PATH_CODEC && t[1] != null) { + httpPath = `/${t[1]}` + } + + return t[0] !== HTTP_PATH_CODEC + }) + ) + }) + + return { + httpPath, + addresses + } +} + +export function normalizeMethod (method?: string | string[], defaultMethod = ['GET']): string[] { + if (method == null) { + return defaultMethod + } + + if (typeof method === 'string') { + method = [method] + } + + return method.map(m => m.toUpperCase()) +} + +/** + * Returns a fully qualified URL representing the resource that is being + * requested + */ +export function normalizeUrl (req: { url?: string, headers?: Headers | { host?: string } }): URL { + const url = req.url ?? '/' + + if (url.startsWith('http')) { + return new URL(url) + } + + const host = getHostFromReq(req) + + return new URL(`http://${host}${url}`) +} + +function getHostFromReq (req: any): string { + let host = req.headers?.host + + if (host == null) { + host = req.headers?.Host + } + + if (host == null && typeof req.headers.get === 'function') { + host = req.headers.get('host') + } + + if (host == null) { + throw new InvalidParametersError('Could not read host') + } + + return host +} + +export function isWebSocketUpgrade (method: string, headers: Headers): boolean { + return method === 'GET' && headers.get('connection')?.toLowerCase() === 'upgrade' && headers.get('upgrade')?.toLowerCase() === 'websocket' +} + +/** + * Handles node.js-style headers for which the values can be string[] + */ +function getHeaderFromHeaders (headers: Headers | Record, key: string): string | undefined { + if (headers instanceof Headers) { + return headers.get(key) ?? undefined + } + + const header = headers[key] + + if (Array.isArray(header)) { + return header.join(',') + } + + return header +} + +export async function getServerUpgradeHeaders (headers: Headers | Record): Promise { + if (getHeaderFromHeaders(headers, 'sec-websocket-version') !== '13') { + throw new ProtocolError('Invalid version') + } + + const secWebSocketKey = getHeaderFromHeaders(headers, 'sec-websocket-key') + + if (secWebSocketKey == null) { + throw new ProtocolError('Missing sec-websocket-key') + } + + const token = `${secWebSocketKey}258EAFA5-E914-47DA-95CA-C5AB0DC85B11` + const hash = await sha1.digest(uint8ArrayFromString(token)) + const webSocketAccept = base64pad.encode( + hash.digest + ).substring(1) + + return new Headers({ + Upgrade: 'websocket', + Connection: 'upgrade', + 'Sec-WebSocket-Accept': webSocketAccept + }) +} + +/** + * Parsed from the incoming HTTP message + */ +export interface HeaderInfo { + versionMajor: number + versionMinor: number + headers: Headers + method: string + url: string + statusCode: number + statusMessage: string + upgrade: boolean + shouldKeepAlive: boolean + raw: Uint8ArrayList +} + +export * from './request.js' +export * from './response.js' +export * from './constants.js' +export * from './stream-to-socket.js' diff --git a/packages/http-client/src/fetch/request.ts b/packages/http-utils/src/request.ts similarity index 95% rename from packages/http-client/src/fetch/request.ts rename to packages/http-utils/src/request.ts index bbbb079..c3a880b 100644 --- a/packages/http-client/src/fetch/request.ts +++ b/packages/http-utils/src/request.ts @@ -1,4 +1,4 @@ -import { getHeaders, isWebSocketUpgrade } from '../utils.js' +import { getHeaders, isWebSocketUpgrade } from './index.js' /** * Extends the native Request class to be more flexible. diff --git a/packages/http-client/src/fetch/response.ts b/packages/http-utils/src/response.ts similarity index 91% rename from packages/http-client/src/fetch/response.ts rename to packages/http-utils/src/response.ts index f170c62..0c58d66 100644 --- a/packages/http-client/src/fetch/response.ts +++ b/packages/http-utils/src/response.ts @@ -1,5 +1,5 @@ -import { STATUS_CODES } from '../constants.js' -import { getHeaders } from '../utils.js' +import { STATUS_CODES } from './constants.js' +import { getHeaders } from './index.js' /** * Extends the native Response class to be more flexible. diff --git a/packages/http-utils/src/utils.ts b/packages/http-utils/src/utils.ts deleted file mode 100644 index a9f1a2d..0000000 --- a/packages/http-utils/src/utils.ts +++ /dev/null @@ -1,466 +0,0 @@ -import { InvalidParametersError, isPeerId } from '@libp2p/interface' -import { peerIdFromString } from '@libp2p/peer-id' -import { fromStringTuples, isMultiaddr, multiaddr } from '@multiformats/multiaddr' -import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' -import { uriToMultiaddr } from '@multiformats/uri-to-multiaddr' -import { queuelessPushable } from 'it-queueless-pushable' -import itToBrowserReadableStream from 'it-to-browser-readablestream' -import { base36 } from 'multiformats/bases/base36' -import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' -import { DNS_CODECS, HTTP_CODEC, HTTP_PATH_CODEC } from './constants.js' -import { Request } from './fetch/request.js' -import type { HeaderInfo, RequestOptions, WebSocketInit } from './index.js' -import type { PeerId, Stream } from '@libp2p/interface' -import type { Multiaddr } from '@multiformats/multiaddr' -import type { Readable } from 'node:stream' -import type { Uint8ArrayList } from 'uint8arraylist' - -/** - * Normalizes byte-like input to a `Uint8Array` - */ -export function toUint8Array (obj: DataView | ArrayBuffer | Uint8Array): Uint8Array { - if (obj instanceof Uint8Array) { - return obj - } - - if (obj instanceof DataView) { - return new Uint8Array(obj.buffer, obj.byteOffset, obj.byteLength) - } - - return new Uint8Array(obj, 0, obj.byteLength) -} - -export function streamToRequest (info: HeaderInfo, stream: Stream): globalThis.Request { - const init: RequestInit = { - method: info.method, - headers: info.headers - } - - if ((init.method !== 'GET' || info.upgrade) && init.method !== 'HEAD') { - let source: AsyncGenerator = stream.source - - if (!info.upgrade) { - source = takeBytes(stream.source, info.headers.get('content-length')) - } - - init.body = itToBrowserReadableStream(source) - // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit - init.duplex = 'half' - } - - return new Request(normalizeUrl(info).toString(), init) -} - -export async function responseToStream (res: Response, stream: Stream): Promise { - const pushable = queuelessPushable() - stream.sink(pushable) - .catch(err => { - stream.abort(err) - }) - - await pushable.push(uint8arrayFromString([ - `HTTP/1.1 ${res.status} ${res.statusText}`, - ...writeHeaders(res.headers), - '', - '' - ].join('\r\n'))) - - if (res.body == null) { - await pushable.end() - return - } - - const reader = res.body.getReader() - let result = await reader.read() - - while (true) { - if (result.value != null) { - await pushable.push(result.value) - } - - if (result.done) { - break - } - - result = await reader.read() - } - - await pushable.end() - - await stream.closeWrite() - .catch(err => { - stream.abort(err) - }) -} - -export const NOT_FOUND_RESPONSE = uint8arrayFromString([ - 'HTTP/1.1 404 Not Found', - 'Connection: close', - '', - '' -].join('\r\n')) - -export const BAD_REQUEST = uint8arrayFromString([ - 'HTTP/1.1 400 Bad Request', - 'Connection: close', - '', - '' -].join('\r\n')) - -export const INTERNAL_SERVER_ERROR = uint8arrayFromString([ - 'HTTP/1.1 500 Internal Server Error', - 'Connection: close', - '', - '' -].join('\r\n')) - -export const NOT_IMPLEMENTED_ERROR = uint8arrayFromString([ - 'HTTP/1.1 501 Not Implemented', - 'Connection: close', - '', - '' -].join('\r\n')) - -/** - * Normalizes the dial target to a list of multiaddrs with an optionally - * encapsulated suffix - */ -export function toMultiaddrs (peer: PeerId | Multiaddr | Multiaddr[], suffix?: string): Multiaddr[] { - let mas: Multiaddr[] - - if (isPeerId(peer)) { - mas = [ - multiaddr(`/p2p/${peer}`) - ] - } else if (Array.isArray(peer)) { - mas = peer - } else { - mas = [ - peer - ] - } - - if (suffix != null) { - mas = mas.map(ma => ma.encapsulate(suffix)) - } - - return mas -} - -export function writeHeaders (headers: Headers): string[] { - const output = [] - - if (headers.get('Connection') == null) { - headers.set('Connection', 'close') - } - - for (const [key, value] of headers.entries()) { - output.push(`${key}: ${value}`) - } - - return output -} - -export function readableToReadableStream (readable: Readable): ReadableStream { - return new ReadableStream({ - start (controller) { - readable.on('data', buf => { - controller.enqueue(buf) - - // pause until more data requested (backpressure) - readable.pause() - }) - readable.on('end', () => { - controller.close() - }) - readable.on('error', (err) => { - controller.error(err) - }) - }, - pull () { - // let data flow again - readable.resume() - } - }) -} - -async function * takeBytes (source: AsyncGenerator, bytes?: number | string | null): AsyncGenerator { - bytes = parseInt(`${bytes ?? ''}`) - - if (bytes == null || isNaN(bytes)) { - return source - } - - let count = 0 - - for await (const buf of source) { - count += buf.byteLength - - if (count > bytes) { - yield buf.subarray(0, count - bytes) - return - } - - yield buf.subarray() - - if (count === bytes) { - return - } - } -} - -/** - * Attempts to convert the passed `resource` into a HTTP(s) URL or an array of - * multiaddrs. - * - * The returned URL should be handled by the global fetch, the multiaddr(s) - * should be handled by libp2p. - */ -export function toResource (resource: string | URL | Multiaddr | Multiaddr[]): URL | Multiaddr[] { - if (typeof resource === 'string') { - if (resource.startsWith('/')) { - resource = multiaddr(resource) - } else { - resource = new URL(resource) - } - } - - if (resource instanceof URL) { - if (resource.protocol === 'multiaddr:') { - resource = uriToMultiaddr(resource.toString()) - } - } - - if (isMultiaddr(resource)) { - resource = [resource] - } - - // check for `/http/` tuple and transform to URL if present - if (Array.isArray(resource)) { - for (const ma of resource) { - const stringTuples = ma.stringTuples() - - if (stringTuples.find(([codec]) => codec === HTTP_CODEC) != null) { - const uri = multiaddrToUri(ma) - return new URL(uri) - } - } - } - - return resource -} - -export function getHeaders (init: RequestInit = {}): Headers { - if (init.headers instanceof Headers) { - return init.headers - } - - init.headers = new Headers(init.headers) - - return init.headers -} - -export function getHeader (header: string, headers: HeadersInit = {}): string | undefined { - if (headers instanceof Headers) { - return headers.get(header) ?? undefined - } - - if (Array.isArray(headers)) { - return headers.find(([key, value]) => { - if (key === header) { - return value - } - - return undefined - })?.[1] - } - - return headers[header] -} - -function isValidHost (host?: string): host is string { - return host != null && host !== '' -} - -export function getHost (addresses: URL | Multiaddr[], headers: Headers): string { - let host: string | undefined - let port = 80 - let protocol = 'http:' - - if (addresses instanceof URL) { - host = addresses.hostname - port = parseInt(addresses.port, 10) - protocol = addresses.protocol - } - - if (!isValidHost(host)) { - host = headers.get('host') ?? undefined - } - - // try to extract domain from DNS addresses - if (!isValidHost(host) && Array.isArray(addresses)) { - for (const address of addresses) { - const stringTuples = address.stringTuples() - const filtered = stringTuples.filter(([key]) => DNS_CODECS.includes(key))?.[0]?.[1] - - if (filtered != null) { - host = filtered - break - } - } - } - - // try to use remote PeerId as domain - if (!isValidHost(host) && Array.isArray(addresses)) { - for (const address of addresses) { - const peerStr = address.getPeerId() - - // try to extract port from multiaddr if it is available - try { - const options = address.toOptions() - port = options.port - } catch {} - - if (peerStr != null) { - const peerId = peerIdFromString(peerStr) - // host has to be case-insensitive - host = peerId.toCID().toString(base36) - break - } - } - } - - if (isValidHost(host)) { - // add port if not standard - if (protocol === 'http:' && port !== 80) { - host = `${host}:${port}` - } - - if (protocol === 'https:' && port !== 443) { - host = `${host}:${port}` - } - - return host - } - - throw new InvalidParametersError('Could not determine request host name - a request must have a host header, be made to a DNS-based multiaddr or an http(s) URL') -} - -export function getCacheKey (resource: URL | Multiaddr[], headers: Headers): string { - let prefix = '' - - if (Array.isArray(resource)) { - const peer = resource.map(ma => ma.getPeerId()) - .filter(Boolean) - .pop() - - if (peer != null) { - prefix = `${peer}-` - } - } - - return `${prefix}${getHost(resource, headers)}` -} - -export async function prepareAndSendRequest (resource: URL | Multiaddr[], opts: RequestOptions, sendRequest: () => Promise): Promise { - for (const middleware of opts.middleware) { - await middleware.prepareRequest?.(resource, opts) - } - - return sendRequest() -} - -export async function prepareAndConnect (resource: URL | Multiaddr[], opts: RequestOptions, connect: () => Promise): Promise { - for (const middleware of opts.middleware) { - await middleware.prepareRequest?.(resource, opts) - } - - return connect() -} - -export async function processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): Promise { - for (const middleware of opts.middleware) { - await middleware.processResponse?.(resource, opts, response) - } - - return response -} - -export function stripHTTPPath (addresses: Multiaddr[]): { httpPath: string, addresses: Multiaddr[] } { - // strip http-path tuple but record the value if set - let httpPath = '/' - addresses = addresses.map(ma => { - return fromStringTuples( - ma.stringTuples().filter(t => { - if (t[0] === HTTP_PATH_CODEC && t[1] != null) { - httpPath = `/${t[1]}` - } - - return t[0] !== HTTP_PATH_CODEC - }) - ) - }) - - return { - httpPath, - addresses - } -} - -export function normalizeMethod (method?: string | string[], defaultMethod = ['GET']): string[] { - if (method == null) { - return defaultMethod - } - - if (typeof method === 'string') { - method = [method] - } - - return method.map(m => m.toUpperCase()) -} - -/** - * Returns a fully qualified URL representing the resource that is being - * requested - */ -export function normalizeUrl (req: { url?: string, headers?: Headers | { host?: string } }): URL { - const url = req.url ?? '/' - - if (url.startsWith('http')) { - return new URL(url) - } - - const host = getHostFromReq(req) - - return new URL(`http://${host}${url}`) -} - -function getHostFromReq (req: any): string { - let host = req.headers?.host - - if (host == null) { - host = req.headers?.Host - } - - if (host == null && typeof req.headers.get === 'function') { - host = req.headers.get('host') - } - - if (host == null) { - throw new InvalidParametersError('Could not read host') - } - - return host -} - -export function isWebSocketUpgrade (method: string, headers: Headers): boolean { - return method === 'GET' && headers.get('connection')?.toLowerCase() === 'upgrade' && headers.get('upgrade')?.toLowerCase() === 'websocket' -} - -export function isWebSocketInit (opts?: any): opts is WebSocketInit { - if (opts == null) { - return false - } - - return isWebSocketUpgrade(opts.method, opts.headers) -} diff --git a/packages/http-utils/test/index.spec.ts b/packages/http-utils/test/index.spec.ts new file mode 100644 index 0000000..8ef9719 --- /dev/null +++ b/packages/http-utils/test/index.spec.ts @@ -0,0 +1,5 @@ +describe('@libp2p/http-utils', () => { + it('should run a test', () => { + + }) +}) diff --git a/packages/http-websocket/LICENSE b/packages/http-websocket/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/http-websocket/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/http-websocket/LICENSE-APACHE b/packages/http-websocket/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/http-websocket/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/http-websocket/LICENSE-MIT b/packages/http-websocket/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/http-websocket/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/http-websocket/README.md b/packages/http-websocket/README.md new file mode 100644 index 0000000..3710548 --- /dev/null +++ b/packages/http-websocket/README.md @@ -0,0 +1,73 @@ +# @libp2p/http-client + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> libp2p-compatible implementation of the WebSocket api + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/http-websocket/package.json b/packages/http-websocket/package.json new file mode 100644 index 0000000..8611cc0 --- /dev/null +++ b/packages/http-websocket/package.json @@ -0,0 +1,163 @@ +{ + "name": "@libp2p/http-websocket", + "version": "0.0.0", + "description": "libp2p-compatible implementation of the WebSocket api", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "clean": "aegir clean", + "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", + "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" + }, + "dependencies": { + "@achingbrain/http-parser-js": "^0.5.9", + "@libp2p/http-utils": "^0.0.0", + "@libp2p/interface": "^2.2.0", + "@libp2p/interface-internal": "^2.0.10", + "@libp2p/utils": "^6.6.0", + "@multiformats/multiaddr": "^12.3.0", + "it-byte-stream": "^2.0.1", + "multiformats": "^13.3.2", + "uint8arraylist": "^2.4.8", + "uint8arrays": "^5.1.0" + }, + "devDependencies": { + "aegir": "^45.0.0" + }, + "browser": { + "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js", + "./dist/src/http.js": "./dist/src/http.browser.js", + "./dist/src/http/index.js": "./dist/src/http/index.browser.js", + "./dist/test/index.spec.js": "./dist/test/index.browser.spec.js" + }, + "sideEffects": false +} diff --git a/packages/http-client/src/websocket/events.ts b/packages/http-websocket/src/events.ts similarity index 100% rename from packages/http-client/src/websocket/events.ts rename to packages/http-websocket/src/events.ts diff --git a/packages/http-websocket/src/index.ts b/packages/http-websocket/src/index.ts new file mode 100644 index 0000000..089c1ab --- /dev/null +++ b/packages/http-websocket/src/index.ts @@ -0,0 +1,54 @@ +import type { AbortOptions } from '@libp2p/interface' + +export interface WebSocketEvents { + 'close': CloseEvent + 'error': Event + 'message': MessageEvent + 'open': Event +} + +export interface CloseListener { + (evt: CloseEvent): void +} + +export interface ErrorListener { + (evt: Event): void +} + +export interface MessageListener { + (evt: MessageEvent): void +} + +export interface OpenListener { + (evt: Event): void +} +/* +export interface WebSocket extends TypedEventTarget { + CONNECTING: 0 + OPEN: 1 + CLOSING: 2 + CLOSED: 3 + binaryType: BinaryType + bufferedAmount: number + extensions: string + protocol: string + readyState: number + url: string + onopen: OpenListener | null + onmessage: MessageListener | null + onerror: ErrorListener | null + onclose: CloseListener | null + + close (code?: number, reason?: string): void + send (data: string | Blob | Uint8Array | ArrayBuffer | DataView): void +} + */ + +export interface WebSocketInit extends AbortOptions { + headers: Headers + protocols?: string[] + onHandshakeResponse?(res: Response): Promise +} + +export { WebSocket, RequestWebSocket, StreamWebSocket, ServerWebSocket } from './websocket.js' +export { CLOSE_CODES, CLOSE_MESSAGES } from './message.js' diff --git a/packages/http-client/src/websocket/message.ts b/packages/http-websocket/src/message.ts similarity index 100% rename from packages/http-client/src/websocket/message.ts rename to packages/http-websocket/src/message.ts diff --git a/packages/http-client/src/websocket/utils.ts b/packages/http-websocket/src/utils.ts similarity index 72% rename from packages/http-client/src/websocket/utils.ts rename to packages/http-websocket/src/utils.ts index 753cac7..ec4e801 100644 --- a/packages/http-client/src/websocket/utils.ts +++ b/packages/http-websocket/src/utils.ts @@ -1,12 +1,10 @@ import { HTTPParser } from '@achingbrain/http-parser-js' -import { InvalidParametersError, ProtocolError } from '@libp2p/interface' +import { Response, BAD_REQUEST, toUint8Array, writeHeaders, getServerUpgradeHeaders } from '@libp2p/http-utils' +import { InvalidParametersError } from '@libp2p/interface' import { base64pad } from 'multiformats/bases/base64' -import { sha1 } from 'multiformats/hashes/sha1' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { Response } from '../fetch/response.js' -import { BAD_REQUEST, toUint8Array, writeHeaders } from '../utils.js' import { StreamWebSocket } from './websocket.js' -import type { HeaderInfo } from '../index.js' +import type { HeaderInfo } from '@libp2p/http-utils' import type { AbortOptions, Stream } from '@libp2p/interface' import type { ByteStream } from 'it-byte-stream' @@ -79,20 +77,6 @@ export async function readResponse (bytes: ByteStream, options: AbortOptions): P }) } -function getHeader (headers: Headers | Record, key: string): string | undefined { - if (headers instanceof Headers) { - return headers.get(key) ?? undefined - } - - const header = headers[key] - - if (Array.isArray(header)) { - return header.join(',') - } - - return header -} - /** * Implements the WebSocket handshake from the client's perspective */ @@ -121,30 +105,6 @@ export async function * performClientUpgrade (url: URL, protocols: string[] = [] ].join('\r\n')) } -export async function getServerUpgradeHeaders (headers: Headers | Record): Promise { - if (getHeader(headers, 'sec-websocket-version') !== '13') { - throw new ProtocolError('Invalid version') - } - - const secWebSocketKey = getHeader(headers, 'sec-websocket-key') - - if (secWebSocketKey == null) { - throw new ProtocolError('Missing sec-websocket-key') - } - - const token = `${secWebSocketKey}258EAFA5-E914-47DA-95CA-C5AB0DC85B11` - const hash = await sha1.digest(uint8ArrayFromString(token)) - const webSocketAccept = base64pad.encode( - hash.digest - ).substring(1) - - return new Headers({ - Upgrade: 'websocket', - Connection: 'upgrade', - 'Sec-WebSocket-Accept': webSocketAccept - }) -} - /** * Implements the WebSocket handshake from the server's perspective */ diff --git a/packages/http-client/src/websocket/websocket.ts b/packages/http-websocket/src/websocket.ts similarity index 94% rename from packages/http-client/src/websocket/websocket.ts rename to packages/http-websocket/src/websocket.ts index 329a2a2..933f5e6 100644 --- a/packages/http-client/src/websocket/websocket.ts +++ b/packages/http-websocket/src/websocket.ts @@ -1,15 +1,14 @@ +import { getHeaders } from '@libp2p/http-utils' import { InvalidParametersError, TypedEventEmitter } from '@libp2p/interface' import { isPromise } from '@libp2p/utils/is-promise' import { byteStream, type ByteStream } from 'it-byte-stream' import { Uint8ArrayList } from 'uint8arraylist' -import { PROTOCOL } from '../constants.js' -import { getHeaders } from '../utils.js' import { CloseEvent, ErrorEvent } from './events.js' import { encodeMessage, decodeMessage, CLOSE_MESSAGES } from './message.js' import { performClientUpgrade, performServerUpgrade, readResponse, toBytes } from './utils.js' -import type { CloseListener, ErrorListener, MessageListener, OpenListener, WebSocketEvents } from './index.js' +import type { CloseListener, ErrorListener, MessageListener, OpenListener, WebSocketEvents, WebSocketInit } from './index.js' import type { MESSAGE_TYPE } from './message.js' -import type { HeaderInfo, ClientMiddleware, RequestOptions } from '../index.js' +import type { HeaderInfo } from '@libp2p/http-utils' import type { AbortOptions, Stream } from '@libp2p/interface' import type { ConnectionManager } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -19,16 +18,16 @@ import type { Duplex } from 'node:stream' const DATA_MESSAGES: MESSAGE_TYPE[] = ['BINARY', 'TEXT', 'CONTINUATION'] const MAX_MESSAGE_SIZE = 10_485_760 const DEFAULT_HOST = 'example.com' +export const HTTP_PROTOCOL = '/http/1.1' -export interface AbstractWebSocketInit extends AbortOptions { +interface AbstractWebSocketInit extends AbortOptions { protocols?: string[] isClient?: boolean maxMessageSize?: number - headers?: HeadersInit - ignoreCookies?: boolean + headers?: Headers } -export abstract class AbstractWebSocket extends TypedEventEmitter { +abstract class AbstractWebSocket extends TypedEventEmitter { public readonly binaryType: 'arraybuffer' | 'blob' = 'arraybuffer' public bufferedAmount = 0 public extensions = '' @@ -415,11 +414,6 @@ export class RequestWebSocket extends AbstractWebSocket { } } -export interface WebSocketInit extends RequestOptions { - middleware: ClientMiddleware[] - protocols?: string[] -} - export class WebSocket extends AbstractWebSocket { private bytes?: ByteStream @@ -432,7 +426,7 @@ export class WebSocket extends AbstractWebSocket { Promise.resolve() .then(async () => { const connection = await connectionManager.openConnection(mas, init) - const stream = await connection.newStream(PROTOCOL, init) + const stream = await connection.newStream(HTTP_PROTOCOL, init) this.bytes = byteStream(stream) for await (const buf of performClientUpgrade(url, init.protocols, getHeaders(init))) { @@ -445,9 +439,7 @@ export class WebSocket extends AbstractWebSocket { throw new Error('Invalid WebSocket handshake - response status ' + res.status) } - for (const middleware of init.middleware) { - await middleware.processResponse?.(mas, init, res) - } + await init.onHandshakeResponse?.(res) // if a protocol was selected by the server, expose it this.protocol = res.headers.get('Sec-WebSocket-Protocol') ?? '' diff --git a/packages/http-websocket/test/index.spec.ts b/packages/http-websocket/test/index.spec.ts new file mode 100644 index 0000000..60d708b --- /dev/null +++ b/packages/http-websocket/test/index.spec.ts @@ -0,0 +1,5 @@ +describe('@libp2p/http-websocket', () => { + it('should run a test', () => { + + }) +}) diff --git a/test/websocket/message.spec.ts b/packages/http-websocket/test/message.spec.ts similarity index 98% rename from test/websocket/message.spec.ts rename to packages/http-websocket/test/message.spec.ts index 10ce3b7..a63e0d7 100644 --- a/test/websocket/message.spec.ts +++ b/packages/http-websocket/test/message.spec.ts @@ -1,7 +1,7 @@ import { expect } from 'aegir/chai' import { Uint8ArrayList } from 'uint8arraylist' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { decodeMessage, encodeMessage } from '../../src/websocket/message.js' +import { decodeMessage, encodeMessage } from '../src/message.js' describe('websocket messages', () => { it('should encode and decode a small message', () => { diff --git a/packages/http-websocket/tsconfig.json b/packages/http-websocket/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/http-websocket/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/http-websocket/typedoc.json b/packages/http-websocket/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/http-websocket/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/packages/http/package.json b/packages/http/package.json index 6307660..d7116cc 100644 --- a/packages/http/package.json +++ b/packages/http/package.json @@ -44,17 +44,13 @@ "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" }, - "./auth": { - "types": "./dist/src/auth/index.d.ts", - "import": "./dist/src/auth/index.js" + "./middleware": { + "types": "./dist/src/middleware/index.d.ts", + "import": "./dist/src/middleware/index.js" }, - "./ping": { - "types": "./dist/src/ping.d.ts", - "import": "./dist/src/ping.js" - }, - "./servers/node": { - "types": "./dist/src/servers/node.d.ts", - "import": "./dist/src/servers/node.js" + "./routes": { + "types": "./dist/src/routes/index.d.ts", + "import": "./dist/src/routes/index.js" } }, "eslintConfig": { @@ -168,60 +164,23 @@ }, "dependencies": { "@achingbrain/http-parser-js": "^0.5.9", - "@libp2p/crypto": "^5.0.6", + "@libp2p/http-peer-id-auth": "^0.0.0", "@libp2p/interface": "^2.2.0", "@libp2p/interface-internal": "^2.0.10", - "@libp2p/peer-id": "^5.0.7", - "@libp2p/utils": "^6.6.0", "@multiformats/multiaddr": "^12.3.0", - "@multiformats/multiaddr-to-uri": "^11.0.0", - "@multiformats/uri-to-multiaddr": "^9.0.1", "cookie": "^1.0.2", - "http-cookie-agent": "^6.0.7", - "it-byte-stream": "^2.0.1", "it-queueless-pushable": "^2.0.0", - "it-to-browser-readablestream": "^2.0.10", - "multiformats": "^13.3.2", - "p-defer": "^4.0.1", - "race-event": "^1.3.0", - "race-signal": "^1.1.3", - "tough-cookie": "^5.0.0", - "uint8-varint": "^2.0.4", "uint8arraylist": "^2.4.8", - "uint8arrays": "^5.1.0", - "undici": "^6.21.2" + "undici": "^6.21.2", + "@libp2p/http-fetch": "^0.0.0", + "@libp2p/http-websocket": "^0.0.0", + "@libp2p/http-utils": "^0.0.0" }, "devDependencies": { - "@chainsafe/libp2p-noise": "^16.1.0", - "@chainsafe/libp2p-yamux": "^7.0.1", - "@fastify/cookie": "^11.0.2", - "@fastify/websocket": "^11.0.2", - "@libp2p/memory": "^1.1.4", - "@libp2p/ping": "^2.0.27", - "@libp2p/websockets": "^9.2.8", - "@types/cookie-parser": "^1.4.8", - "@types/express": "^5.0.1", - "@types/ws": "^8.18.0", - "aegir": "^45.0.0", - "cookie-parser": "^1.4.7", - "express": "^4.21.2", - "fastify": "^5.2.2", - "it-pair": "^2.0.6", - "libp2p": "^2.2.1", - "p-event": "^6.0.1", - "sinon": "^20.0.0", - "wherearewe": "^2.0.1", - "ws": "^8.18.1" + "aegir": "^45.0.0" }, "browser": { - "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js", - "./dist/src/http.js": "./dist/src/http.browser.js", - "./dist/src/http/index.js": "./dist/src/http/index.browser.js", - "./dist/test/index.spec.js": "./dist/test/index.browser.spec.js", - "node:events": "events", - "node:stream": "readable-stream", - "node:http": false, - "undici": false + "./dist/src/http.js": "./dist/src/http.browser.js" }, "sideEffects": false } diff --git a/packages/http/src/constants.ts b/packages/http/src/constants.ts index 5db034d..8dab3b0 100644 --- a/packages/http/src/constants.ts +++ b/packages/http/src/constants.ts @@ -1,83 +1,5 @@ -export const PROTOCOL = '/http/1.1' -export const WEBSOCKET_HANDLER = Symbol.for('@libp2p/http/websocket-handler') +export const HTTP_PROTOCOL = '/http/1.1' export const PEER_ID_AUTH_SCHEME = 'libp2p-PeerID' export const HTTP_PEER_ID_AUTH_PROTO = '/http-peer-id-auth/1.0.0' -export const DEFAULT_AUTH_TOKEN_TTL = 60 * 60 * 1000 // 1 hour -export const HTTP_PATH_CODEC = 0x01e1 -export const HTTP_CODEC = 0x01e0 -export const DNS_CODEC = 0x35 -export const DNS4_CODEC = 0x36 -export const DNS6_CODEC = 0x37 -export const DNSADDR_CODEC = 0x38 -export const DNS_CODECS = [ - DNS_CODEC, - DNS4_CODEC, - DNS6_CODEC, - DNSADDR_CODEC -] export const DEFAULT_COOKIE_EXPIRY_CHECK_INTERVAL = 60_000 -export const STATUS_CODES: Record = { - 100: 'Continue', // RFC 7231 6.2.1 - 101: 'Switching Protocols', // RFC 7231 6.2.2 - 102: 'Processing', // RFC 2518 10.1 (obsoleted by RFC 4918) - 103: 'Early Hints', // RFC 8297 2 - 200: 'OK', // RFC 7231 6.3.1 - 201: 'Created', // RFC 7231 6.3.2 - 202: 'Accepted', // RFC 7231 6.3.3 - 203: 'Non-Authoritative Information', // RFC 7231 6.3.4 - 204: 'No Content', // RFC 7231 6.3.5 - 205: 'Reset Content', // RFC 7231 6.3.6 - 206: 'Partial Content', // RFC 7233 4.1 - 207: 'Multi-Status', // RFC 4918 11.1 - 208: 'Already Reported', // RFC 5842 7.1 - 226: 'IM Used', // RFC 3229 10.4.1 - 300: 'Multiple Choices', // RFC 7231 6.4.1 - 301: 'Moved Permanently', // RFC 7231 6.4.2 - 302: 'Found', // RFC 7231 6.4.3 - 303: 'See Other', // RFC 7231 6.4.4 - 304: 'Not Modified', // RFC 7232 4.1 - 305: 'Use Proxy', // RFC 7231 6.4.5 - 307: 'Temporary Redirect', // RFC 7231 6.4.7 - 308: 'Permanent Redirect', // RFC 7238 3 - 400: 'Bad Request', // RFC 7231 6.5.1 - 401: 'Unauthorized', // RFC 7235 3.1 - 402: 'Payment Required', // RFC 7231 6.5.2 - 403: 'Forbidden', // RFC 7231 6.5.3 - 404: 'Not Found', // RFC 7231 6.5.4 - 405: 'Method Not Allowed', // RFC 7231 6.5.5 - 406: 'Not Acceptable', // RFC 7231 6.5.6 - 407: 'Proxy Authentication Required', // RFC 7235 3.2 - 408: 'Request Timeout', // RFC 7231 6.5.7 - 409: 'Conflict', // RFC 7231 6.5.8 - 410: 'Gone', // RFC 7231 6.5.9 - 411: 'Length Required', // RFC 7231 6.5.10 - 412: 'Precondition Failed', // RFC 7232 4.2 - 413: 'Payload Too Large', // RFC 7231 6.5.11 - 414: 'URI Too Long', // RFC 7231 6.5.12 - 415: 'Unsupported Media Type', // RFC 7231 6.5.13 - 416: 'Range Not Satisfiable', // RFC 7233 4.4 - 417: 'Expectation Failed', // RFC 7231 6.5.14 - 418: 'I\'m a Teapot', // RFC 7168 2.3.3 - 421: 'Misdirected Request', // RFC 7540 9.1.2 - 422: 'Unprocessable Entity', // RFC 4918 11.2 - 423: 'Locked', // RFC 4918 11.3 - 424: 'Failed Dependency', // RFC 4918 11.4 - 425: 'Too Early', // RFC 8470 5.2 - 426: 'Upgrade Required', // RFC 2817 and RFC 7231 6.5.15 - 428: 'Precondition Required', // RFC 6585 3 - 429: 'Too Many Requests', // RFC 6585 4 - 431: 'Request Header Fields Too Large', // RFC 6585 5 - 451: 'Unavailable For Legal Reasons', // RFC 7725 3 - 500: 'Internal Server Error', // RFC 7231 6.6.1 - 501: 'Not Implemented', // RFC 7231 6.6.2 - 502: 'Bad Gateway', // RFC 7231 6.6.3 - 503: 'Service Unavailable', // RFC 7231 6.6.4 - 504: 'Gateway Timeout', // RFC 7231 6.6.5 - 505: 'HTTP Version Not Supported', // RFC 7231 6.6.6 - 506: 'Variant Also Negotiates', // RFC 2295 8.1 - 507: 'Insufficient Storage', // RFC 4918 11.5 - 508: 'Loop Detected', // RFC 5842 7.2 - 509: 'Bandwidth Limit Exceeded', - 510: 'Not Extended', // RFC 2774 7 - 511: 'Network Authentication Required' // RFC 6585 6 -} +export const WEBSOCKET_HANDLER = Symbol.for('@libp2p/http/websocket-handler') diff --git a/packages/http/src/http.browser.ts b/packages/http/src/http.browser.ts index 266c672..88a191e 100644 --- a/packages/http/src/http.browser.ts +++ b/packages/http/src/http.browser.ts @@ -1,13 +1,14 @@ +import { fetch } from '@libp2p/http-fetch' +import { getHeaders, getHost, stripHTTPPath, toMultiaddrs, toResource } from '@libp2p/http-utils' +import { WebSocket } from '@libp2p/http-websocket' import { UnsupportedOperationError, serviceCapabilities, start, stop } from '@libp2p/interface' -import { PROTOCOL } from './constants.js' -import { fetch } from './fetch/index.js' +import { HTTP_PROTOCOL } from './constants.js' import { Cookies } from './middleware/cookies.js' +import { Origin } from './middleware/origin.js' import { HTTPRegistrar } from './registrar.js' -import { getHeaders, getHost, prepareAndConnect, prepareAndSendRequest, processResponse, stripHTTPPath, toMultiaddrs, toResource } from './utils.js' -import { WebSocket as WebSocketClass } from './websocket/websocket.js' +import { prepareAndConnect, prepareAndSendRequest, processResponse } from './utils.js' import { WELL_KNOWN_PROTOCOLS_PATH } from './index.js' -import type { HTTPInit, HTTP as HTTPInterface, WebSocketInit, ProtocolMap, FetchInit, RequestOptions } from './index.js' -import type { HTTPRoute } from './routes/index.js' +import type { HTTPInit, HTTP as HTTPInterface, ProtocolMap, FetchInit, HTTPRoute, ConnectInit, MiddlewareOptions } from './index.js' import type { ComponentLogger, Logger, PeerId, PrivateKey, Startable } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' import type { Multiaddr } from '@multiformats/multiaddr' @@ -23,12 +24,14 @@ export class HTTP implements HTTPInterface, Startable { private readonly log: Logger protected readonly components: HTTPComponents private readonly httpRegistrar: HTTPRegistrar + private readonly origin: Origin private readonly cookies: Cookies constructor (components: HTTPComponents, init: HTTPInit = {}) { this.components = components this.log = components.logger.forComponent('libp2p:http') this.httpRegistrar = new HTTPRegistrar(components, init) + this.origin = new Origin() this.cookies = new Cookies(components, init) } @@ -58,17 +61,14 @@ export class HTTP implements HTTPInterface, Startable { throw new UnsupportedOperationError('This method is not supported in browsers') } - async connect (resource: string | URL | Multiaddr | Multiaddr[], init: WebSocketInit = {}): Promise { + async connect (resource: string | URL | Multiaddr | Multiaddr[], init: ConnectInit = {}): Promise { const url = toResource(resource) const headers = getHeaders(init) - const opts: RequestOptions = { + const opts: MiddlewareOptions = { ...init, headers, method: 'GET', - middleware: init.middleware?.map(fn => fn(this.components)) ?? [], - // WebSocket requests are not subject to cross-origin checks so do not use - // cookies as it introduces a security vulnerability - ignoreCookies: true + middleware: init.middleware?.map(fn => fn(this.components)) ?? [] } headers.set('connection', 'upgrade') @@ -85,7 +85,7 @@ export class HTTP implements HTTPInterface, Startable { // strip http-path tuple but record the value if set const { addresses, httpPath } = stripHTTPPath(url) - return new WebSocketClass( + return new WebSocket( addresses, new URL(`http://${getHost(url, opts.headers)}${decodeURIComponent(httpPath)}`), this.components.connectionManager, @@ -96,15 +96,15 @@ export class HTTP implements HTTPInterface, Startable { async fetch (resource: string | URL | Multiaddr | Multiaddr[], init: FetchInit = {}): Promise { const url = toResource(resource) - const opts: RequestOptions = { + const opts: MiddlewareOptions = { ...init, headers: getHeaders(init), method: 'GET', middleware: [ + this.origin, this.cookies, ...init.middleware?.map(fn => fn(this.components)) ?? [] - ], - ignoreCookies: init.ignoreCookies ?? false + ] } const response = await prepareAndSendRequest(url, opts, async () => { @@ -148,7 +148,7 @@ export class HTTP implements HTTPInterface, Startable { return this.httpRegistrar.onRequest(req) } - onWebSocket (ws: WebSocket): void { + onWebSocket (ws: globalThis.WebSocket): void { this.httpRegistrar.onWebSocket(ws) } @@ -179,7 +179,7 @@ export class HTTP implements HTTPInterface, Startable { const connection = await this.components.connectionManager.openConnection(addresses, { signal: init.signal ?? undefined }) - const stream = await connection.newStream(PROTOCOL, { + const stream = await connection.newStream(HTTP_PROTOCOL, { signal: init.signal ?? undefined }) @@ -189,14 +189,3 @@ export class HTTP implements HTTPInterface, Startable { }) } } - -export function toURL (resource: URL | Multiaddr[], headers: Headers): URL { - if (resource instanceof URL) { - return resource - } - - const host = getHost(resource, headers) - const { httpPath } = stripHTTPPath(resource) - - return new URL(`http://${host}${httpPath}`) -} diff --git a/packages/http/src/http.ts b/packages/http/src/http.ts index 07cd175..42ffe56 100644 --- a/packages/http/src/http.ts +++ b/packages/http/src/http.ts @@ -1,10 +1,9 @@ import { Agent as NodeAgent } from 'node:http' +import { streamToSocket, toResource } from '@libp2p/http-utils' import { isPeerId } from '@libp2p/interface' import { Agent as UnidiciAgent } from 'undici' -import { PROTOCOL } from './constants.js' +import { HTTP_PROTOCOL } from './constants.js' import { HTTP as HTTPBrowser } from './http.browser.js' -import { streamToSocket } from './stream-to-socket.js' -import { toResource } from './utils.js' import type { HTTP as HTTPInterface } from './index.js' import type { AbortOptions, PeerId } from '@libp2p/interface' import type { ConnectionManager, Registrar } from '@libp2p/interface-internal' @@ -17,7 +16,7 @@ export type { HTTPComponents } from './http.browser.js' async function createConnection (connectionManager: ConnectionManager, peer: PeerId | Multiaddr | Multiaddr[], options?: AbortOptions): Promise { const connection = await connectionManager.openConnection(peer, options) - const stream = await connection.newStream(PROTOCOL, options) + const stream = await connection.newStream(HTTP_PROTOCOL, options) return streamToSocket(stream, connection) } diff --git a/packages/http/src/index.ts b/packages/http/src/index.ts index 012b702..e91c065 100644 --- a/packages/http/src/index.ts +++ b/packages/http/src/index.ts @@ -343,12 +343,12 @@ */ import { HTTP as HTTPClass } from './http.js' +import type { WEBSOCKET_HANDLER } from './constants.js' import type { HTTPComponents } from './http.js' -import type { HTTPRoute } from './routes/index.js' +import type { HeaderInfo, MiddlewareOptions, Middleware } from '@libp2p/http-utils' import type { AbortOptions, Connection, PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' import type { Agent, AgentOptions, IncomingMessage } from 'node:http' -import type { Uint8ArrayList } from 'uint8arraylist' import type { Dispatcher, Agent as UnidiciAgent } from 'undici' export { WELL_KNOWN_PROTOCOLS_PATH } from './routes/well-known.js' @@ -362,14 +362,7 @@ export interface HTTPRequestOptions extends AbortOptions { * A list of request processors that can augment requests - if specified will * override any processors passed to the `http` service */ - middleware?: Array<(components: any) => ClientMiddleware> - - /** - * If true, cookies will not be used for this request - * - * @default false - */ - ignoreCookies?: boolean + middleware?: Array<(components: any) => Middleware> /** * The maximum number of bytes that will be parsed as response headers @@ -386,7 +379,7 @@ export interface HTTPRequestOptions extends AbortOptions { authenticateServer?: boolean } -export interface WebSocketInit extends HTTPRequestOptions { +export interface ConnectInit extends HTTPRequestOptions { /** * The maximum message size to be sent or received over the socket in bytes * @@ -450,6 +443,63 @@ export interface RequestHandlerOptions { cors?: boolean } +/** + * Options used to define a HTTP route that can handle requests + */ +export interface RouteOptions { + /** + * Specify a path to serve the protocol from. If omitted the protocol name + * will be used. + * + * Paths can be looked up from the protocol map using `getProtocolMap()` or by + * making a GET request to `/.well-known/libp2p/protocols`. + */ + path?: string + + /** + * A list of HTTP verbs this handler will respond to. If the handler is found + * but the request method is not present a 405 will be returned. + * + * @default ['GET'] + */ + method?: string | string[] + + /** + * By default all handlers support CORS headers, pass `false` here to disallow + * access to fetch requests. + * + * @default true + */ + cors?: boolean +} + +/** + * A simple route that defines a handler function + */ +export interface HandlerRoute extends RouteOptions { + handler: H +} + +/** + * A route that requires initialization before use + */ +export interface ServiceRoute extends RouteOptions { + init(components: any): H +} + +/** + * A WebSocket route can make it's handler available for invocation with a + * pre-upgraded WebSocket object + */ +export interface WebSocketRoute { + [WEBSOCKET_HANDLER]?: WebSocketHandler +} + +/** + * A union of the various route types + */ +export type HTTPRoute = (HandlerRoute | ServiceRoute) & WebSocketRoute + /** * HTTP service interface */ @@ -475,7 +525,7 @@ export interface HTTP { * URLs can start with the `multiaddr:` scheme if the global URL class in the * runtime environment supports it. */ - connect (resource: string | URL | Multiaddr | Multiaddr[], init?: WebSocketInit): Promise + connect (resource: string | URL | Multiaddr | Multiaddr[], init?: ConnectInit): Promise /** * Get a libp2p-enabled Agent for use with node's `http` module. This method @@ -545,22 +595,10 @@ export interface HTTP { } /** - * Parsed from the incoming HTTP message + * A WebServer that can accept incoming libp2p streams and transform them into + * an HTTP request that can be processed */ -export interface HeaderInfo { - versionMajor: number - versionMinor: number - headers: Headers - method: string - url: string - statusCode: number - statusMessage: string - upgrade: boolean - shouldKeepAlive: boolean - raw: Uint8ArrayList -} - -export interface Endpoint { +export interface WebServer { /** * Accept an incoming request. The headers have already been parsed, the * stream/connection should be transformed into whatever format the HTTP @@ -569,29 +607,7 @@ export interface Endpoint { inject (info: HeaderInfo, stream: Stream, connection: Connection): Promise } -export interface RequestOptions extends AbortOptions { - method: string - headers: Headers - middleware: ClientMiddleware[] - ignoreCookies: boolean -} - -/** - * Middleware that allows augmenting the client request/response with additional - * fields or headers. - */ -export interface ClientMiddleware { - /** - * Called before a request is made - */ - prepareRequest?(resource: URL | Multiaddr[], opts: RequestOptions): void | Promise - - /** - * Called after a request is made but before the body has been read - the - * processor may do any necessary housekeeping based on the server response - */ - processResponse?(resource: URL | Multiaddr[], opts: RequestOptions, response: Response): void | Promise -} +export type { MiddlewareOptions, Middleware } /** * Options to configure the HTTP service. @@ -603,7 +619,7 @@ export interface HTTPInit { /** * A server that will receive incoming requests */ - server?: Endpoint + server?: WebServer /** * How long in ms an auth token for a server will be valid for, defaults to @@ -617,7 +633,7 @@ export interface HTTPInit { * A list of request processors that can augment requests. Middleware passed * here will be invoked on every outgoing request. */ - middleware?: Array<(components: any) => ClientMiddleware> + middleware?: Array<(components: any) => Middleware> /** * How often to evict stale cookies from the cache in ms. @@ -638,3 +654,6 @@ export interface HTTPInit { export function http (init: HTTPInit = {}): (components: HTTPComponents) => HTTP { return (components) => new HTTPClass(components, init) } + +export { authenticatedRoute, authenticatedWebSocketRoute } from './routes/peer-id-auth.js' +export { webSocketRoute } from './routes/websocket.js' diff --git a/packages/http-client/src/middleware/cookies.ts b/packages/http/src/middleware/cookies.ts similarity index 76% rename from packages/http-client/src/middleware/cookies.ts rename to packages/http/src/middleware/cookies.ts index 090552c..b229f2d 100644 --- a/packages/http-client/src/middleware/cookies.ts +++ b/packages/http/src/middleware/cookies.ts @@ -1,6 +1,6 @@ +import { toURL } from '@libp2p/http-utils' import cookie from 'cookie' -import { toURL } from '../http.browser.js' -import type { ClientMiddleware, RequestOptions } from '../index.js' +import type { Middleware, MiddlewareOptions } from '@libp2p/http-utils' import type { ComponentLogger, Logger } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' @@ -20,7 +20,7 @@ interface Cookie { path?: string } -export class Cookies implements ClientMiddleware { +export class Cookies implements Middleware { private readonly log: Logger private readonly cookies: Map @@ -29,8 +29,16 @@ export class Cookies implements ClientMiddleware { this.cookies = new Map() } - async prepareRequest (resource: URL | Multiaddr[], opts: RequestOptions): Promise { - if (opts.ignoreCookies) { + async prepareRequest (resource: URL | Multiaddr[], opts: MiddlewareOptions): Promise { + const credentials = opts.credentials ?? 'same-origin' + + if (credentials === 'omit') { + return + } + + const origin = opts.headers.get('origin') + + if (origin == null || origin === 'null') { return } @@ -54,15 +62,21 @@ export class Cookies implements ClientMiddleware { } } - async processResponse (resource: URL | Multiaddr[], opts: RequestOptions, response: Response): Promise { - if (opts.ignoreCookies) { + async processResponse (resource: URL | Multiaddr[], opts: MiddlewareOptions, response: Response): Promise { + const credentials = opts.credentials ?? 'same-origin' + + if (credentials === 'omit') { removeSetCookie(response) + return + } + const origin = opts.headers.get('origin') + + if (origin == null || origin === 'null') { return } const url = toURL(resource, opts.headers) - for (const value of response.headers.getSetCookie()) { const cookies = [ ...(this.cookies.get(url.hostname) ?? []), diff --git a/packages/http/src/middleware/index.ts b/packages/http/src/middleware/index.ts new file mode 100644 index 0000000..3c82d7a --- /dev/null +++ b/packages/http/src/middleware/index.ts @@ -0,0 +1,2 @@ +export * from './cookies.js' +export * from './peer-id-auth.js' diff --git a/packages/http/src/middleware/origin.ts b/packages/http/src/middleware/origin.ts new file mode 100644 index 0000000..e55b727 --- /dev/null +++ b/packages/http/src/middleware/origin.ts @@ -0,0 +1,19 @@ +import { toURL } from '@libp2p/http-utils' +import type { Middleware, MiddlewareOptions } from '@libp2p/http-utils' +import type { Multiaddr } from '@multiformats/multiaddr' + +export class Origin implements Middleware { + async prepareRequest (resource: URL | Multiaddr[], opts: MiddlewareOptions): Promise { + if (opts.headers.get('origin') != null) { + return + } + + if (opts.mode === 'no-cors') { + return + } + + const url = toURL(resource, opts.headers) + + opts.headers.set('origin', `${url.protocol}//${url.host}`) + } +} diff --git a/packages/http/src/middleware/peer-id-auth.ts b/packages/http/src/middleware/peer-id-auth.ts new file mode 100644 index 0000000..c9543c5 --- /dev/null +++ b/packages/http/src/middleware/peer-id-auth.ts @@ -0,0 +1,182 @@ +import { MissingAuthHeaderError, DEFAULT_AUTH_TOKEN_TTL, ClientInitiatedHandshake, type VerifyPeer } from '@libp2p/http-peer-id-auth' +import { getHost, isWebSocketUpgrade } from '@libp2p/http-utils' +import { InvalidMessageError, InvalidParametersError } from '@libp2p/interface' +import type { Middleware, MiddlewareOptions, HTTP } from '../index.js' +import type { ComponentLogger, PeerId, PrivateKey } from '@libp2p/interface' +import type { Multiaddr } from '@multiformats/multiaddr' + +interface AuthToken { + /** + * The PeerId of the server + */ + peerId: PeerId + + /** + * When the token expires + */ + expires: number + + /** + * The authorization header to send + */ + authorization: string + + /** + * The handshake + */ + handshake: ClientInitiatedHandshake +} + +interface PeerIdAuthComponents { + privateKey: PrivateKey + logger: ComponentLogger + http: HTTP +} + +export const SEC_WEBSOCKET_PROTOCOL_PREFIX = 'authorization=' + +export interface PeerIdAuthInit { + verifyPeer?: VerifyPeer + tokenTTL?: number +} + +export class PeerIdAuth implements Middleware { + private readonly components: PeerIdAuthComponents + private readonly tokens: Map + private readonly tokenTTL: number + private readonly verifyPeer?: VerifyPeer + + constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit) { + this.components = components + this.tokens = new Map() + this.tokenTTL = init.tokenTTL ?? DEFAULT_AUTH_TOKEN_TTL + this.verifyPeer = init.verifyPeer + } + + async prepareRequest (resource: URL | Multiaddr[], opts: MiddlewareOptions): Promise { + const authorization = await this.getOrCreateAuthToken(resource, opts) + + if (isWebSocketInit(opts)) { + opts.protocols = [ + ...(opts.protocols ?? []), + `${SEC_WEBSOCKET_PROTOCOL_PREFIX}${btoa(authorization)}` + ] + } else { + if (opts.headers.get('authorization') != null) { + throw new InvalidParametersError('Will not overwrite existing Authorization header') + } + + opts.headers.set('Authorization', authorization) + } + } + + async getOrCreateAuthToken (resource: URL | Multiaddr[], opts: MiddlewareOptions): Promise { + const key = getCacheKey(resource, opts.headers) + let token = this.tokens.get(key) + + // check token expiry + if (token?.expires != null && token?.expires < Date.now()) { + this.tokens.delete(key) + token = undefined + } + + // create new token + if (token == null) { + return this.createAuthToken(resource, opts) + } + + return token?.authorization + } + + async createAuthToken (resource: URL | Multiaddr[], opts: MiddlewareOptions): Promise { + const hostname = getHost(resource, opts.headers) + const handshake = new ClientInitiatedHandshake(this.components.privateKey, hostname, this.verifyPeer) + const challenge = handshake.getChallenge() + + // copy existing headers + const challengeHeaders = new Headers(opts.headers) + challengeHeaders.set('authorization', challenge) + + // remove any WebSocket upgrade headers + challengeHeaders.delete('connection') + challengeHeaders.delete('upgrade') + + // get the server's response + const resp = await this.components.http.fetch(resource, { + method: 'OPTIONS', + headers: challengeHeaders, + signal: opts.signal, + middleware: opts.middleware + .filter(m => m !== this) + .map(m => () => m) + }) + + // verify the server's challenge + const response = resp.headers.get('www-authenticate') + + if (response == null) { + throw new MissingAuthHeaderError('No www-authenticate header in response') + } + + // verify remote server and answer the server challenge + const authorization = await handshake.verifyServer(response, opts) + + if (handshake.serverId == null) { + throw new InvalidMessageError('Failed to get server PeerId') + } + + const key = getCacheKey(resource, opts.headers) + this.tokens.set(key, { + peerId: handshake.serverId, + authorization, + expires: Date.now() + this.tokenTTL, + handshake + }) + + return authorization + } + + processResponse (resource: URL | Multiaddr[], opts: MiddlewareOptions, response: Response): void { + // store the bearer token if the server provided it + const serverAuthHeader = response.headers.get('authentication-info') + + if (serverAuthHeader != null) { + const key = getCacheKey(resource, opts.headers) + const token = this.tokens.get(key) + + if (token != null) { + token.authorization = token.handshake.decodeBearerToken(serverAuthHeader) + } + } + } +} + +export function peerIdAuth (init: PeerIdAuthInit = {}): (component: any) => Middleware { + return (components) => { + return new PeerIdAuth(components, init) + } +} + +function isWebSocketInit (opts?: any): opts is { protocols?: string[] } { + if (opts == null) { + return false + } + + return isWebSocketUpgrade(opts.method, opts.headers) +} + +function getCacheKey (resource: URL | Multiaddr[], headers: Headers): string { + let prefix = '' + + if (Array.isArray(resource)) { + const peer = resource.map(ma => ma.getPeerId()) + .filter(Boolean) + .pop() + + if (peer != null) { + prefix = `${peer}-` + } + } + + return `${prefix}${getHost(resource, headers)}` +} diff --git a/packages/http/src/registrar.ts b/packages/http/src/registrar.ts index 39a1b1e..51557f6 100644 --- a/packages/http/src/registrar.ts +++ b/packages/http/src/registrar.ts @@ -1,15 +1,14 @@ import { HTTPParser } from '@achingbrain/http-parser-js' +import { NOT_FOUND_RESPONSE, normalizeMethod, normalizeUrl, responseToStream, streamToRequest } from '@libp2p/http-utils' +import { CLOSE_MESSAGES } from '@libp2p/http-websocket' import { InvalidParametersError } from '@libp2p/interface' import { queuelessPushable } from 'it-queueless-pushable' import { Uint8ArrayList } from 'uint8arraylist' -import { PROTOCOL, WEBSOCKET_HANDLER } from './constants.js' -import { Response } from './fetch/response.js' -import { initializeRoute } from './routes/index.js' +import { HTTP_PROTOCOL, WEBSOCKET_HANDLER } from './constants.js' +import { initializeRoute } from './routes/utils.js' import { wellKnownRoute } from './routes/well-known.js' -import { NOT_FOUND_RESPONSE, normalizeMethod, normalizeUrl, responseToStream, streamToRequest } from './utils.js' -import { CLOSE_MESSAGES } from './websocket/message.js' -import type { Endpoint, HTTPRequestHandler, HeaderInfo, ProtocolMap, WebSocketHandler } from './index.js' -import type { HTTPRoute, HandlerRoute } from './routes/index.js' +import type { WebServer, HTTPRequestHandler, ProtocolMap, WebSocketHandler, HTTPRoute, HandlerRoute } from './index.js' +import type { HeaderInfo } from '@libp2p/http-utils' import type { ComponentLogger, IncomingStreamData, Logger, Stream } from '@libp2p/interface' import type { Registrar } from '@libp2p/interface-internal' @@ -19,7 +18,7 @@ export interface HTTPRegistrarComponents { } export interface HTTPRegistrarInit { - server?: Endpoint + server?: WebServer } interface ProtocolHandler { @@ -31,7 +30,7 @@ export class HTTPRegistrar { private readonly log: Logger private readonly components: HTTPRegistrarComponents private protocols: ProtocolHandler[] - private readonly endpoint?: Endpoint + private readonly endpoint?: WebServer constructor (components: HTTPRegistrarComponents, init: HTTPRegistrarInit = {}) { this.components = components @@ -43,7 +42,7 @@ export class HTTPRegistrar { } async start (): Promise { - await this.components.registrar.handle(PROTOCOL, (data) => { + await this.components.registrar.handle(HTTP_PROTOCOL, (data) => { this.onStream(data) .catch(err => { this.log.error('could not handle incoming stream - %e', err) @@ -52,7 +51,7 @@ export class HTTPRegistrar { } async stop (): Promise { - await this.components.registrar.unhandle(PROTOCOL) + await this.components.registrar.unhandle(HTTP_PROTOCOL) } private async onStream ({ stream, connection }: IncomingStreamData): Promise { diff --git a/packages/http/src/routes/index.ts b/packages/http/src/routes/index.ts new file mode 100644 index 0000000..0a30ae2 --- /dev/null +++ b/packages/http/src/routes/index.ts @@ -0,0 +1,2 @@ +export * from './peer-id-auth.js' +export * from './websocket.js' diff --git a/packages/http-server/src/routes/peer-id-auth.ts b/packages/http/src/routes/peer-id-auth.ts similarity index 63% rename from packages/http-server/src/routes/peer-id-auth.ts rename to packages/http/src/routes/peer-id-auth.ts index f20390c..b14d6f9 100644 --- a/packages/http-server/src/routes/peer-id-auth.ts +++ b/packages/http/src/routes/peer-id-auth.ts @@ -1,29 +1,18 @@ -import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' -import { peerIdFromPublicKey, peerIdFromString } from '@libp2p/peer-id' -import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' -import { encodeAuthParams, parseHeader, sign, verify } from '../auth/common.js' -import { DEFAULT_AUTH_TOKEN_TTL, WEBSOCKET_HANDLER } from '../constants.js' -import { normalizeMethod } from '../utils.js' +import { createServerChallenge, serverResponds } from '@libp2p/http-peer-id-auth' +import { normalizeMethod } from '@libp2p/http-utils' +import { WEBSOCKET_HANDLER } from '../constants.js' +import { initializeRoute } from './utils.js' import { webSocketRoute } from './websocket.js' -import { initializeRoute } from './index.js' -import type { HTTPRoute, HandlerRoute } from './index.js' +import type { HTTPRoute, HandlerRoute } from '../index.js' import type { ComponentLogger, Logger, PeerId, PrivateKey, PublicKey } from '@libp2p/interface' -export const PeerIDAuthScheme = 'libp2p-PeerID' -export const HTTPPeerIDAuthProto = '/http-peer-id-auth/1.0.0' +export const DEFAULT_AUTH_TOKEN_TTL = 60 * 60 * 1000 // 1 hour interface PeerIdAuthComponents { privateKey: PrivateKey logger: ComponentLogger } -interface OpaqueUnwrapped { - challengeClient: string - clientPublicKey?: string - hostname: string - creationTime: number -} - interface AuthenticationResult { status: number headers?: Headers @@ -33,6 +22,12 @@ interface AuthenticationResult { interface PeerIdAuthInit { tokenTTL?: number verifyHostname?(hostname: string): boolean | Promise + + /** + * If true, and the client has not initiated the HTTP PeerId Auth handshake, + * have the server do it. + */ + requireAuth?: boolean } export class PeerIdAuth { @@ -40,12 +35,13 @@ export class PeerIdAuth { public readonly log: Logger private readonly tokenTTL: number private readonly verifyHostname: (hostname: string) => boolean | Promise + private readonly requireAuth: boolean constructor (components: PeerIdAuthComponents, init: PeerIdAuthInit) { this.components = components this.log = components.logger.forComponent('libp2p:http:server-peer-id-auth') this.tokenTTL = init.tokenTTL ?? DEFAULT_AUTH_TOKEN_TTL - + this.requireAuth = init.requireAuth ?? false this.verifyHostname = init.verifyHostname ?? (() => true) } @@ -57,185 +53,56 @@ export class PeerIdAuth { } if (authHeader == null || authHeader === '') { - return this.returnChallenge(hostname, null, {}) - } - - const authFields = parseHeader(authHeader) - if (authFields.bearer !== undefined && authFields.bearer !== '') { - const peer = await this.unwrapBearerToken(hostname, authFields.bearer) - return { status: 200, peer } - } - - let opaqueState: OpaqueUnwrapped | undefined - if (authFields.opaque !== undefined) { - try { - const opaque = await this.unwrapOpaque(authFields.opaque) - if (opaque.hostname !== hostname) { - this.log.error('invalid hostname') - return { status: 400 } - } - if (Date.now() - opaque.creationTime > this.tokenTTL) { - this.log.error('token expired') - return { status: 400 } - } - - opaqueState = opaque - } catch (e) { - this.log.error('invalid opaque') - return { status: 400 } + if (this.requireAuth) { + return this.returnChallenge(hostname) } - } - let clientPublicKey: PublicKey | null = null - if (opaqueState?.clientPublicKey !== undefined) { - clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(opaqueState.clientPublicKey, 'base64urlpad')) - } else if (authFields['public-key'] !== undefined) { - clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(authFields['public-key'], 'base64urlpad')) + return { status: 200 } } - const returnParams: Record = {} - let clientPeerId: PeerId | undefined - if (authFields.sig !== undefined) { - // Verify signature - if (clientPublicKey === null) { - this.log.error('missing public-key') - return { status: 400 } - } - if (opaqueState?.challengeClient === null) { - this.log.error('missing challenge-client') - return { status: 400 } - } + try { + const result = await serverResponds(authHeader, hostname, this.components.privateKey, this.tokenTTL) + const headers = new Headers() - const valid = await verify(clientPublicKey, PeerIDAuthScheme, [ - ['challenge-client', opaqueState?.challengeClient ?? ''], - ['hostname', hostname], - ['server-public-key', publicKeyToProtobuf(this.components.privateKey.publicKey)] - ], uint8ArrayFromString(authFields.sig, 'base64urlpad')) - if (!valid) { - this.log.error('invalid signature') - return { status: 400 } + if (result.info != null) { + headers.set('authentication-info', result.info) + headers.set('access-control-expose-headers', 'authentication-info') } - // Return a bearer token - clientPeerId = peerIdFromPublicKey(clientPublicKey) - returnParams.bearer = this.genBearerToken(clientPeerId, hostname) - } - - if (authFields['challenge-server'] !== undefined) { - if (clientPublicKey === null) { - this.log.error('missing public-key') - return { status: 400 } + if (result.authenticate != null) { + headers.set('www-authenticate', result.authenticate) + headers.set('access-control-expose-headers', 'www-authenticate') } - // Sign and return challenge - const sig = await sign(this.components.privateKey, PeerIDAuthScheme, [ - ['hostname', hostname], - ['client-public-key', publicKeyToProtobuf(clientPublicKey)], - ['challenge-server', authFields['challenge-server']] - ]) - returnParams['public-key'] = uint8ArrayToString(publicKeyToProtobuf(this.components.privateKey.publicKey), 'base64urlpad') - returnParams.sig = uint8ArrayToString(sig, 'base64urlpad') - } - - if (returnParams.bearer !== undefined) { return { status: 200, - peer: clientPeerId, - headers: new Headers({ - 'Authentication-info': encodeAuthParams(returnParams) - }) + headers, + peer: result.peerId } - } + } catch (err: any) { + this.log.error('failed to respond to client challenge - %e', err) - // Not authenticated - return this.returnChallenge(hostname, clientPublicKey, returnParams) - } + if (err.name === 'InvalidMessageError') { + return { status: 400 } + } - private async returnChallenge (hostname: string, clientPublicKey: PublicKey | null, returnParams: Record): Promise { - const challenge = this.generateChallenge() - returnParams['challenge-client'] = challenge + if (err.name === 'NotAuthenticatedError') { + return this.returnChallenge(hostname) + } - returnParams.opaque = this.genOpaque({ - challengeClient: challenge, - clientPublicKey: clientPublicKey !== null ? uint8ArrayToString(publicKeyToProtobuf(clientPublicKey), 'base64urlpad') : undefined, - hostname, - creationTime: Date.now() - }) + throw err + } + } + private async returnChallenge (hostname: string, clientPublicKey?: PublicKey): Promise { return { status: 401, headers: new Headers({ - 'www-authenticate': encodeAuthParams(returnParams), + 'www-authenticate': await createServerChallenge(hostname, this.components.privateKey, clientPublicKey), 'access-control-expose-headers': 'www-authenticate' }) } } - - private genBearerToken (clientPeerId: PeerId, hostname: string): string { - return this.signBox(this.components.privateKey, { - peer: clientPeerId.toString(), - h: hostname, - t: Date.now() - }) - } - - private async unwrapBearerToken (expectedHostname: string, token: string): Promise { - if (token.length < PeerIDAuthScheme.length + 1) { - throw new Error('Invalid bearer token') - } - const bearer = parseHeader(token).bearer - const unwrapped = await this.verifyBox(this.components.privateKey.publicKey, bearer) as any - if (typeof unwrapped.peer !== 'string' || typeof unwrapped.h !== 'string' || typeof unwrapped.t !== 'number') { - throw new Error('Invalid bearer token') - } - if (unwrapped.h !== expectedHostname) { - throw new Error('Invalid hostname') - } - if (Date.now() - unwrapped.t > this.tokenTTL) { - throw new Error('Token expired') - } - return peerIdFromString(unwrapped.peer) - } - - private genOpaque (unwrapped: OpaqueUnwrapped): string { - return this.signBox(this.components.privateKey, unwrapped) - } - - private async unwrapOpaque (opaque: string): Promise { - const unwrapped = await this.verifyBox(this.components.privateKey.publicKey, opaque) as any - if (typeof unwrapped.challengeClient !== 'string' || typeof unwrapped.hostname !== 'string' || typeof unwrapped.creationTime !== 'number') { - throw new Error('Invalid opaque') - } - return unwrapped - } - - private signBox (key: PrivateKey, data: unknown): string { - const dataSerialized = JSON.stringify(data) - const dataBytes = uint8ArrayFromString(dataSerialized) - const sig = key.sign(dataBytes) - const jsonStr = JSON.stringify({ - val: uint8ArrayToString(dataBytes, 'base64urlpad'), - sig: uint8ArrayToString(sig, 'base64urlpad') - }) - return uint8ArrayToString(uint8ArrayFromString(jsonStr), 'base64urlpad') - } - - private async verifyBox (key: PublicKey, data: string): Promise { - const { sig, val } = JSON.parse(uint8ArrayToString(uint8ArrayFromString(data, 'base64urlpad'))) - const valBytes = uint8ArrayFromString(val, 'base64urlpad') - const sigValid = await key.verify(valBytes, uint8ArrayFromString(sig, 'base64urlpad')) - if (!sigValid) { - throw new Error('Invalid signature') - } - const valStr = uint8ArrayToString(valBytes) - return JSON.parse(valStr) - } - - private generateChallenge (): string { - const randomBytes = new Uint8Array(32) - crypto.getRandomValues(randomBytes) - return uint8ArrayToString(randomBytes, 'base64urlpad') - } } export interface AuthenticationOptions { @@ -380,6 +247,12 @@ type AuthenticatedEndpoint = HTTPRoute & Authen * Attempt to authenticate the client before request processing to discover * their PeerID. * + * If the `requireAuth` option is false, no authentication will be attempted + * unless the client initiates it. + * + * If it is `true` or `undefined`, the server will initiate the authentication + * handshake if the client has not done so. + * * @see https://github.com/libp2p/specs/blob/master/http/peer-id-auth.md */ export function authenticatedRoute (handler: OptionallyAuthenticatedEndpoint): HTTPRoute diff --git a/packages/http/src/routes/utils.ts b/packages/http/src/routes/utils.ts new file mode 100644 index 0000000..765dea0 --- /dev/null +++ b/packages/http/src/routes/utils.ts @@ -0,0 +1,28 @@ +import type { HTTPRoute, HandlerRoute, ServiceRoute } from '../index.js' + +/** + * Returns true if the passed route requires initialization + */ +export function isInitializable , S extends ServiceRoute> (obj: H | S): obj is S { + // @ts-expect-error init is not a property of H + return typeof obj.init === 'function' +} + +/** + * Initializes a `ServiceRoute` and converts it to a `HandlerRoute`. + * + * If the passed route has an `init` method, it invokes it and sets the + * `handler` field on the endpoint with the return value, then deletes the + * `init` property, otherwise it returns the endpoint unaltered. + */ +export function initializeRoute (serviceOrHandler: HTTPRoute, components: any): HandlerRoute { + if (isInitializable(serviceOrHandler)) { + const route: any = serviceOrHandler + route.handler = serviceOrHandler.init(components) + delete route.init + + return route + } + + return serviceOrHandler +} diff --git a/packages/http-server/src/routes/websocket.ts b/packages/http/src/routes/websocket.ts similarity index 83% rename from packages/http-server/src/routes/websocket.ts rename to packages/http/src/routes/websocket.ts index 05e744d..d4ce366 100644 --- a/packages/http-server/src/routes/websocket.ts +++ b/packages/http/src/routes/websocket.ts @@ -1,12 +1,9 @@ +import { Response, isWebSocketUpgrade, normalizeMethod, getServerUpgradeHeaders } from '@libp2p/http-utils' +import { RequestWebSocket } from '@libp2p/http-websocket' import { InvalidParametersError } from '@libp2p/interface' import { WEBSOCKET_HANDLER } from '../constants.js' -import { Response } from '../fetch/response.js' -import { isWebSocketUpgrade, normalizeMethod } from '../utils.js' -import { getServerUpgradeHeaders } from '../websocket/utils.js' -import { RequestWebSocket } from '../websocket/websocket.js' -import { initializeRoute } from './index.js' -import type { HTTPRequestHandler, WebSocketHandler } from '../index.js' -import type { HTTPRoute, RouteOptions } from './index.js' +import { initializeRoute } from './utils.js' +import type { HTTPRoute, RouteOptions, HTTPRequestHandler, WebSocketHandler } from '../index.js' export interface WebSocketRouteOptions extends RouteOptions { /** diff --git a/packages/http-server/src/routes/well-known.ts b/packages/http/src/routes/well-known.ts similarity index 88% rename from packages/http-server/src/routes/well-known.ts rename to packages/http/src/routes/well-known.ts index 9ee30e5..df83f28 100644 --- a/packages/http-server/src/routes/well-known.ts +++ b/packages/http/src/routes/well-known.ts @@ -1,7 +1,6 @@ -import { Response } from '../fetch/response.js' import { webSocketRoute } from './websocket.js' +import type { HTTPRoute } from '../index.js' import type { HTTPRegistrar } from '../registrar.js' -import type { HTTPRoute } from './index.js' export const WELL_KNOWN_PROTOCOLS_PATH = '/.well-known/libp2p/protocols' diff --git a/packages/http/src/utils.ts b/packages/http/src/utils.ts new file mode 100644 index 0000000..ac3ceaa --- /dev/null +++ b/packages/http/src/utils.ts @@ -0,0 +1,26 @@ +import type { MiddlewareOptions } from './index.js' +import type { Multiaddr } from '@multiformats/multiaddr' + +export async function prepareAndSendRequest (resource: URL | Multiaddr[], opts: MiddlewareOptions, sendRequest: () => Promise): Promise { + for (const middleware of opts.middleware) { + await middleware.prepareRequest?.(resource, opts) + } + + return sendRequest() +} + +export async function prepareAndConnect (resource: URL | Multiaddr[], opts: MiddlewareOptions, connect: () => Promise): Promise { + for (const middleware of opts.middleware) { + await middleware.prepareRequest?.(resource, opts) + } + + return connect() +} + +export async function processResponse (resource: URL | Multiaddr[], opts: MiddlewareOptions, response: Response): Promise { + for (const middleware of opts.middleware) { + await middleware.processResponse?.(resource, opts, response) + } + + return response +} diff --git a/packages/http/test/index.spec.ts b/packages/http/test/index.spec.ts new file mode 100644 index 0000000..a59c147 --- /dev/null +++ b/packages/http/test/index.spec.ts @@ -0,0 +1,5 @@ +describe('@libp2p/http', () => { + it('should run a test', () => { + + }) +}) diff --git a/.aegir.js b/packages/interop/.aegir.js similarity index 97% rename from .aegir.js rename to packages/interop/.aegir.js index 0f5505c..03bbd8c 100644 --- a/.aegir.js +++ b/packages/interop/.aegir.js @@ -37,8 +37,8 @@ export default { }, test: { before: async () => { - const { createServer } = await import('./dist/src/http/index.js') - const { nodeServer, canHandle } = await import('./dist/src/servers/node.js') + const { createServer, canHandle } = await import('@libp2p/http-server/node') + const { nodeServer } = await import('@libp2p/http-server') const { getHTTPOverLibp2pHandler } = await import('./dist/test/fixtures/get-libp2p.js') const { createHttp } = await import('./dist/test/fixtures/create-http.js') const { createFastifyHTTP } = await import('./dist/test/fixtures/create-fastify-http.js') diff --git a/packages/interop/LICENSE b/packages/interop/LICENSE new file mode 100644 index 0000000..20ce483 --- /dev/null +++ b/packages/interop/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interop/LICENSE-APACHE b/packages/interop/LICENSE-APACHE new file mode 100644 index 0000000..14478a3 --- /dev/null +++ b/packages/interop/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interop/LICENSE-MIT b/packages/interop/LICENSE-MIT new file mode 100644 index 0000000..72dc60d --- /dev/null +++ b/packages/interop/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interop/README.md b/packages/interop/README.md new file mode 100644 index 0000000..261d0d1 --- /dev/null +++ b/packages/interop/README.md @@ -0,0 +1,73 @@ +# @libp2p/http + +[![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) +[![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) +[![codecov](https://img.shields.io/codecov/c/github/libp2p/js-libp2p-http.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-http) +[![CI](https://img.shields.io/github/actions/workflow/status/libp2p/js-libp2p-http/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/libp2p/js-libp2p-http/actions/workflows/js-test-and-release.yml?query=branch%3Amain) + +> Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP + +# About + + + +This module allows you to use HTTP requests as a transport for libp2p +protocols (libp2p over HTTP), and also libp2p streams as a transport for HTTP +requests (HTTP over libp2p). + +It integrates with existing Node.js friendly HTTP frameworks such as +[express](https://expressjs.com/) and [Fastify](https://fastify.dev) as well +as [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request)/ +[Response](https://developer.mozilla.org/en-US/docs/Web/API/Response)-based +frameworks like [Hono](https://hono.dev/). + +It even allows creating Node.js-style [http.Server](https://nodejs.org/api/http.html#class-httpserver)s +and [WebSocketServer](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#class-websocketserver)s +in browsers to truly realize the power of the distributed web. + +In addition to URL-based addressing, it can use a libp2p PeerId and/or +multiaddr(s) and lets libp2p take care of the routing, thus taking advantage +of features like multi-routes, NAT transversal and stream multiplexing over a +single connection. + +# Install + +```console +$ npm i @libp2p/http +``` + +## Browser ` +``` + +# API Docs + +- + +# License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](https://github.com/libp2p/js-libp2p-http/LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](https://github.com/libp2p/js-libp2p-http/LICENSE-MIT) / ) + +# Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interop/package.json b/packages/interop/package.json new file mode 100644 index 0000000..a5303b4 --- /dev/null +++ b/packages/interop/package.json @@ -0,0 +1,180 @@ +{ + "name": "@libp2p/http-interop", + "version": "0.0.0", + "description": "Accept HTTP requests over libp2p streams or use libp2p protocols over HTTP", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-http-fetch#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-http-fetch.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-http-fetch/issues" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "project": true, + "sourceType": "module" + } + }, + "release": { + "branches": [ + "main" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "type": "deps", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Documentation" + }, + { + "type": "deps", + "section": "Dependencies" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "build": "aegir build", + "clean": "aegir clean", + "lint": "aegir lint", + "test": "aegir test", + "test:chrome": "aegir test -t browser --cov", + "test:firefox": "aegir test -t browser --browser firefox --cov", + "test:node": "aegir test -t node --cov", + "test:electron-main": "aegir test -t electron-main", + "test:chrome-webworker": "aegir test -t webworker", + "test:webkit": "aegir test -t browser -- --browser webkit", + "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", + "dep-check": "aegir dep-check", + "doc-check": "aegir doc-check", + "docs": "aegir docs", + "release": "aegir release" + }, + "devDependencies": { + "@chainsafe/libp2p-noise": "^16.1.0", + "@chainsafe/libp2p-yamux": "^7.0.1", + "@fastify/cookie": "^11.0.2", + "@fastify/websocket": "^11.0.2", + "@libp2p/crypto": "^5.1.1", + "@libp2p/http": "^0.0.0", + "@libp2p/http-ping": "^0.0.0", + "@libp2p/http-server": "^0.0.0", + "@libp2p/interface": "^2.9.0", + "@libp2p/memory": "^1.1.4", + "@libp2p/peer-id": "^5.1.2", + "@libp2p/ping": "^2.0.27", + "@libp2p/websockets": "^9.2.8", + "@multiformats/multiaddr": "^12.4.0", + "@types/cookie-parser": "^1.4.8", + "@types/express": "^5.0.1", + "@types/ws": "^8.18.0", + "aegir": "^45.0.0", + "cookie-parser": "^1.4.7", + "express": "^4.21.2", + "fastify": "^5.2.2", + "libp2p": "^2.2.1", + "p-defer": "^4.0.1", + "p-event": "^6.0.1", + "sinon": "^20.0.0", + "ws": "^8.18.1" + }, + "browser": { + "./dist/src/auth/agent.js": "./dist/src/auth/agent.browser.js", + "./dist/src/http.js": "./dist/src/http.browser.js", + "./dist/src/http/index.js": "./dist/src/http/index.browser.js", + "./dist/test/index.spec.js": "./dist/test/index.browser.spec.js", + "node:stream": "readable-stream", + "node:http": false, + "undici": false + }, + "sideEffects": false, + "private": true +} diff --git a/packages/interop/src/index.ts b/packages/interop/src/index.ts new file mode 100644 index 0000000..336ce12 --- /dev/null +++ b/packages/interop/src/index.ts @@ -0,0 +1 @@ +export {} diff --git a/test/cookies.spec.ts b/packages/interop/test/cookies.spec.ts similarity index 91% rename from test/cookies.spec.ts rename to packages/interop/test/cookies.spec.ts index aa575d0..e4cc04a 100644 --- a/test/cookies.spec.ts +++ b/packages/interop/test/cookies.spec.ts @@ -1,11 +1,11 @@ +import { nodeServer } from '@libp2p/http-server' +import { createServer } from '@libp2p/http-server/node' import { stop } from '@libp2p/interface' import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' -import { createServer } from '../src/http/index.js' -import { nodeServer } from '../src/servers/node.js' import { createHttp } from './fixtures/create-http.js' import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' -import type { HTTP } from '../src/index.js' +import type { HTTP } from '@libp2p/http' import type { Libp2p } from 'libp2p' interface Test { @@ -90,7 +90,7 @@ const tests: Test[] = [{ }] for (const test of tests) { - describe(`cookies - ${test.name}`, () => { + describe.only(`cookies - ${test.name}`, () => { let client: Libp2p<{ http: HTTP }> let listenerMultiaddrs: Multiaddr[] @@ -108,7 +108,8 @@ for (const test of tests) { const setResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/set-cookies')), { headers: { host: 'test-with-cookies.com' - } + }, + credentials: 'include' }) expect(setResponse.status).to.equal(201) expect(setResponse.headers.get('set-cookie')).to.not.be.ok() @@ -116,7 +117,8 @@ for (const test of tests) { const getResponse = await client.services.http.fetch(listenerMultiaddrs.map(ma => ma.encapsulate('/http-path/get-cookies')), { headers: { host: 'test-with-cookies.com' - } + }, + credentials: 'include' }) expect(getResponse.status).to.equal(200) await expect(getResponse.json()).to.eventually.deep.equal([ @@ -130,7 +132,7 @@ for (const test of tests) { headers: { host: 'test-without-cookies.com' }, - ignoreCookies: true + credentials: 'omit' }) expect(setResponse.status).to.equal(201) expect(setResponse.headers.get('set-cookie')).to.not.be.ok() @@ -139,7 +141,7 @@ for (const test of tests) { headers: { host: 'test-without-cookies.com' }, - ignoreCookies: true + credentials: 'omit' }) expect(getResponse.status).to.equal(200) await expect(getResponse.json()).to.eventually.deep.equal([]) diff --git a/test/fetch.spec.ts b/packages/interop/test/fetch.spec.ts similarity index 97% rename from test/fetch.spec.ts rename to packages/interop/test/fetch.spec.ts index 0ebeae7..9b76dd5 100644 --- a/test/fetch.spec.ts +++ b/packages/interop/test/fetch.spec.ts @@ -1,11 +1,11 @@ +import { nodeServer } from '@libp2p/http-server' +import { createServer } from '@libp2p/http-server/node' import { stop } from '@libp2p/interface' import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' -import { createServer } from '../src/http/index.js' -import { nodeServer } from '../src/servers/node.js' import { createHttp } from './fixtures/create-http.js' import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' -import type { HTTP } from '../src/index.js' +import type { HTTP } from '@libp2p/http' import type { Libp2p } from 'libp2p' interface Test { diff --git a/test/fixtures/create-express.ts b/packages/interop/test/fixtures/create-express.ts similarity index 88% rename from test/fixtures/create-express.ts rename to packages/interop/test/fixtures/create-express.ts index 2ce54bc..8851aab 100644 --- a/test/fixtures/create-express.ts +++ b/packages/interop/test/fixtures/create-express.ts @@ -1,13 +1,13 @@ import cookieParser from 'cookie-parser' import express from 'express' -import type { DidHandle } from '../../src/servers/node.js' +import type { CanHandle } from '@libp2p/http-server/node' import type { Server } from 'node:http' /** * Creates an Express server that optionally delegates request handling to a * Libp2p Over HTTP handler */ -export function createExpress (server: Server, handler?: DidHandle): Server { +export function createExpress (server: Server, handled?: CanHandle): Server { const app = express() app.use(cookieParser()) app.get('/', (req, res) => { @@ -35,7 +35,7 @@ export function createExpress (server: Server, handler?: DidHandle): Server { }) server.on('request', (req, res) => { - if (handler?.(req, res) !== true) { + if (handled?.(req, res) !== true) { res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Request-Method', '*') res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') diff --git a/test/fixtures/create-fastify-http.ts b/packages/interop/test/fixtures/create-fastify-http.ts similarity index 89% rename from test/fixtures/create-fastify-http.ts rename to packages/interop/test/fixtures/create-fastify-http.ts index 3c258d8..7daf350 100644 --- a/test/fixtures/create-fastify-http.ts +++ b/packages/interop/test/fixtures/create-fastify-http.ts @@ -1,14 +1,14 @@ import cookies from '@fastify/cookie' import { fastify } from 'fastify' -import type { DidHandle } from '../../src/servers/node.js' +import type { CanHandle } from '@libp2p/http-server/node' import type { FastifyRequest } from 'fastify' import type { Server, IncomingMessage } from 'node:http' -export async function createFastifyHTTP (server: Server, handler?: DidHandle): Promise { +export async function createFastifyHTTP (server: Server, handled?: CanHandle): Promise { const app = fastify({ serverFactory: (app, opts) => { server.addListener('request', (req, res) => { - if (handler?.(req, res) !== true) { + if (handled?.(req, res) !== true) { res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Request-Method', '*') res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') diff --git a/test/fixtures/create-fastify-websocket.ts b/packages/interop/test/fixtures/create-fastify-websocket.ts similarity index 81% rename from test/fixtures/create-fastify-websocket.ts rename to packages/interop/test/fixtures/create-fastify-websocket.ts index a8547c1..4f87e96 100644 --- a/test/fixtures/create-fastify-websocket.ts +++ b/packages/interop/test/fixtures/create-fastify-websocket.ts @@ -1,14 +1,14 @@ import fastifyWebSocket from '@fastify/websocket' +import { toWebSocket } from '@libp2p/http-server/node' import { fastify } from 'fastify' -import { toWebSocket } from './to-websocket.js' -import type { DidHandle } from '../../src/servers/node.js' +import type { CanHandle } from '@libp2p/http-server/node' import type { Server } from 'node:http' -export async function createFastifyWebSocket (server: Server, handler?: DidHandle): Promise { +export async function createFastifyWebSocket (server: Server, handled?: CanHandle): Promise { const app = fastify({ serverFactory: (app, opts) => { server.addListener('request', (req, res) => { - if (handler?.(req, res) !== true) { + if (handled?.(req, res) !== true) { res.setHeader('Access-Control-Allow-Origin', '*') res.setHeader('Access-Control-Request-Method', '*') res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') @@ -29,7 +29,7 @@ export async function createFastifyWebSocket (server: Server, handler?: DidHandl }) }) fastify.get('/*', { websocket: true }, (socket, req) => { - if (handler?.(toWebSocket(socket, req.raw)) === true) { + if (handled?.(toWebSocket(socket, req.raw)) === true) { return } diff --git a/test/fixtures/create-http.ts b/packages/interop/test/fixtures/create-http.ts similarity index 86% rename from test/fixtures/create-http.ts rename to packages/interop/test/fixtures/create-http.ts index d5ba4ea..836847b 100644 --- a/test/fixtures/create-http.ts +++ b/packages/interop/test/fixtures/create-http.ts @@ -1,7 +1,7 @@ -import type { DidHandle } from '../../src/servers/node.js' +import type { CanHandle } from '@libp2p/http-server/node' import type { Server, RequestListener } from 'node:http' -export function createHttp (server: Server, handler?: DidHandle): Server { +export function createHttp (server: Server, handled?: CanHandle): Server { const app: RequestListener = (req, res) => { if (req.url === '/echo') { req.pipe(res) @@ -28,7 +28,7 @@ export function createHttp (server: Server, handler?: DidHandle): Server { } server.on('request', (req, res) => { - if (handler?.(req, res) !== true) { + if (handled?.(req, res) !== true) { res.setHeader('Access-Control-Allow-Origin', req.headers.origin ?? '*') res.setHeader('Access-Control-Allow-Methods', ['OPTIONS', req.headers['access-control-request-method'] ?? '']) res.setHeader('Access-Control-Allow-Headers', req.headers['access-control-request-headers'] ?? '*') diff --git a/test/fixtures/create-websocket-server.ts b/packages/interop/test/fixtures/create-websocket-server.ts similarity index 72% rename from test/fixtures/create-websocket-server.ts rename to packages/interop/test/fixtures/create-websocket-server.ts index e0d9bd3..a523b4e 100644 --- a/test/fixtures/create-websocket-server.ts +++ b/packages/interop/test/fixtures/create-websocket-server.ts @@ -1,13 +1,13 @@ -import { createWebSocketServer as createWss } from '../../src/websocket/index.js' -import type { DidHandle } from '../../src/servers/node.js' +import { createWebSocketServer as createWss } from '@libp2p/http-server/node' +import type { CanHandle } from '@libp2p/http-server/node' import type { Server } from 'node:http' -export function createWebSocketServer (server: Server, handler?: DidHandle): Server { +export function createWebSocketServer (server: Server, handled?: CanHandle): Server { const wss = createWss() wss.addEventListener('connection', (evt) => { const ws = evt.webSocket - if (handler?.(ws) === true) { + if (handled?.(ws) === true) { return } @@ -22,7 +22,7 @@ export function createWebSocketServer (server: Server, handler?: DidHandle): Ser }) server.on('request', (req, res) => { - if (handler?.(req, res) === true) { + if (handled?.(req, res) === true) { return } diff --git a/test/fixtures/create-wss.ts b/packages/interop/test/fixtures/create-wss.ts similarity index 76% rename from test/fixtures/create-wss.ts rename to packages/interop/test/fixtures/create-wss.ts index 6708cd7..b99310d 100644 --- a/test/fixtures/create-wss.ts +++ b/packages/interop/test/fixtures/create-wss.ts @@ -1,12 +1,12 @@ +import { toWebSocket } from '@libp2p/http-server/node' import { WebSocketServer } from 'ws' -import { toWebSocket } from './to-websocket.js' -import type { DidHandle } from '../../src/servers/node.js' +import type { CanHandle } from '@libp2p/http-server/node' import type { Server } from 'node:http' -export function createWss (server: Server, handler?: DidHandle): Server { +export function createWss (server: Server, handled?: CanHandle): Server { const wss = new WebSocketServer({ noServer: true }) wss.on('connection', (ws, req) => { - if (handler?.(toWebSocket(ws, req)) === true) { + if (handled?.(toWebSocket(ws, req)) === true) { return } @@ -21,7 +21,7 @@ export function createWss (server: Server, handler?: DidHandle): Server { }) server.on('request', (req, res) => { - if (handler?.(req, res) === true) { + if (handled?.(req, res) === true) { return } diff --git a/test/fixtures/get-libp2p.ts b/packages/interop/test/fixtures/get-libp2p.ts similarity index 89% rename from test/fixtures/get-libp2p.ts rename to packages/interop/test/fixtures/get-libp2p.ts index 4b8852f..f9d8c83 100644 --- a/test/fixtures/get-libp2p.ts +++ b/packages/interop/test/fixtures/get-libp2p.ts @@ -1,13 +1,13 @@ import { noise } from '@chainsafe/libp2p-noise' import { yamux } from '@chainsafe/libp2p-yamux' +import { http, authenticatedRoute, authenticatedWebSocketRoute } from '@libp2p/http' +import { pingHTTP } from '@libp2p/http-ping' import { memory } from '@libp2p/memory' import { ping } from '@libp2p/ping' import { webSockets } from '@libp2p/websockets' import { createLibp2p } from 'libp2p' -import { http } from '../../src/index.js' -import { pingHTTP, type PingHTTP } from '../../src/ping/index.js' -import { authenticatedRoute, authenticatedWebSocketRoute } from '../../src/routes/peer-id-auth.js' -import type { Endpoint, HTTP } from '../../src/index.js' +import type { WebServer, HTTP } from '@libp2p/http' +import type { PingHTTP } from '@libp2p/http-ping' import type { Libp2p } from '@libp2p/interface' function addEndpoints (libp2p: Libp2p<{ http: HTTP }>): void { @@ -83,7 +83,7 @@ function addEndpoints (libp2p: Libp2p<{ http: HTTP }>): void { /** * A node that listens for incoming HTTP over libp2p requests */ -export async function getHTTPOverLibp2pHandler (server: Endpoint, listen: string = '/memory/address-1'): Promise> { +export async function getHTTPOverLibp2pHandler (server: WebServer, listen: string = '/memory/address-1'): Promise> { const libp2p = await createLibp2p({ addresses: { listen: [ diff --git a/test/peer-id-auth.spec.ts b/packages/interop/test/peer-id-auth.spec.ts similarity index 77% rename from test/peer-id-auth.spec.ts rename to packages/interop/test/peer-id-auth.spec.ts index 136450f..4fe5918 100644 --- a/test/peer-id-auth.spec.ts +++ b/packages/interop/test/peer-id-auth.spec.ts @@ -1,14 +1,14 @@ +import { peerIdAuth } from '@libp2p/http/middleware' +import { nodeServer } from '@libp2p/http-server' +import { createServer } from '@libp2p/http-server/node' import { stop } from '@libp2p/interface' import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import pDefer from 'p-defer' import { pEvent } from 'p-event' -import { createServer } from '../src/http/index.js' -import { peerIdAuth } from '../src/middleware/peer-id-auth.js' -import { nodeServer } from '../src/servers/node.js' import { createHttp } from './fixtures/create-http.js' import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' -import type { HTTP } from '../src/index.js' +import type { HTTP } from '@libp2p/http' import type { Multiaddr } from '@multiformats/multiaddr' import type { Libp2p } from 'libp2p' @@ -23,8 +23,7 @@ let listener: Libp2p<{ http: HTTP }> const tests: Test[] = [{ name: 'in-process server', startServer: async () => { - const server = createHttp(createServer()) - listener = await getHTTPOverLibp2pHandler(nodeServer(server)) + listener = await getHTTPOverLibp2pHandler(nodeServer(createHttp(createServer()))) return listener.getMultiaddrs() }, @@ -260,5 +259,56 @@ for (const test of tests) { expect(response.status).to.equal(200) await expect(response.text()).to.eventually.equal('no-peer-id') }) + + /* + it('should mutually authenticate with a custom port', async () => { + const clientAuth = new ClientAuth(clientKey) + const serverAuth = new ServerAuth(serverKey, h => h === 'foobar:12345') + + const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { + const req = new Request(input, init) + const resp = await serverAuth.httpHandler(req) + return resp + } + + const observedServerPeerId = await clientAuth.authenticateServer('https://foobar:12345/auth', { + fetch + }) + expect(observedServerPeerId.equals(server)).to.be.true() + }) + + it('should time out when authenticating', async () => { + const clientAuth = new ClientAuth(clientKey) + + const controller = new AbortController() + controller.abort() + + await expect(clientAuth.authenticateServer('https://example.com/auth', { + signal: controller.signal + })).to.eventually.be.rejected + .with.property('name', 'AbortError') + }) + + it('should sent request body to authenticated server', async () => { + const clientAuth = new ClientAuth(clientKey) + const serverAuth = new ServerAuth(serverKey, h => h === 'example.com') + + const echoHandler = async (req: Request): Promise => { + return new Response(await req.text()) + } + const httpHandler = serverAuth.withAuth(async (clientId, req) => { return echoHandler(req) }) + + const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { + const req = new Request(input, init) + return httpHandler(req) + } + + const expectedBody = 'Only for authenticated servers!' + const response = await clientAuth.authenticatedFetch('https://example.com/auth', { method: 'POST', body: expectedBody, verifyPeer: (observedId) => observedId.equals(server), fetch }) + + expect((await response.text())).to.be.equal(expectedBody) + expect(response.peer.equals(server)).to.be.true() + }) + */ }) } diff --git a/test/ping.spec.ts b/packages/interop/test/ping.spec.ts similarity index 96% rename from test/ping.spec.ts rename to packages/interop/test/ping.spec.ts index 495b050..b0bac19 100644 --- a/test/ping.spec.ts +++ b/packages/interop/test/ping.spec.ts @@ -3,6 +3,9 @@ import { noise } from '@chainsafe/libp2p-noise' import { yamux } from '@chainsafe/libp2p-yamux' import { generateKeyPair } from '@libp2p/crypto/keys' +import { http } from '@libp2p/http' +import { peerIdAuth } from '@libp2p/http/middleware' +import { pingHTTP } from '@libp2p/http-ping' import { stop } from '@libp2p/interface' import { peerIdFromPrivateKey } from '@libp2p/peer-id' import { webSockets } from '@libp2p/websockets' @@ -10,11 +13,8 @@ import { multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import { createLibp2p } from 'libp2p' import sinon from 'sinon' -import { http } from '../src/index.js' -import { peerIdAuth } from '../src/middleware/peer-id-auth.js' -import { pingHTTP } from '../src/ping/index.js' -import type { HTTP } from '../src/index.js' -import type { PingHTTP } from '../src/ping/index.js' +import type { HTTP } from '@libp2p/http' +import type { PingHTTP } from '@libp2p/http-ping' import type { Libp2p } from '@libp2p/interface' const LIBP2P_SERVERS = [{ diff --git a/test/websockets.spec.ts b/packages/interop/test/websockets.spec.ts similarity index 96% rename from test/websockets.spec.ts rename to packages/interop/test/websockets.spec.ts index 2ea8361..7a39720 100644 --- a/test/websockets.spec.ts +++ b/packages/interop/test/websockets.spec.ts @@ -1,12 +1,12 @@ +import { nodeServer } from '@libp2p/http-server' +import { createServer } from '@libp2p/http-server/node' import { stop } from '@libp2p/interface' import { multiaddr, type Multiaddr } from '@multiformats/multiaddr' import { expect } from 'aegir/chai' import pDefer from 'p-defer' -import { createServer } from '../src/http/index.js' -import { nodeServer } from '../src/servers/node.js' import { createWebSocketServer } from './fixtures/create-websocket-server.js' import { getClient, getHTTPOverLibp2pHandler } from './fixtures/get-libp2p.js' -import type { HTTP } from '../src/index.js' +import type { HTTP } from '@libp2p/http' import type { Libp2p } from 'libp2p' interface Test { diff --git a/packages/interop/tsconfig.json b/packages/interop/tsconfig.json new file mode 100644 index 0000000..13a3599 --- /dev/null +++ b/packages/interop/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ] +} diff --git a/packages/interop/typedoc.json b/packages/interop/typedoc.json new file mode 100644 index 0000000..da5f31c --- /dev/null +++ b/packages/interop/typedoc.json @@ -0,0 +1,5 @@ +{ + "entryPoints": [ + "./src/index.ts" + ] +} \ No newline at end of file diff --git a/src/auth/agent.browser.ts b/src/auth/agent.browser.ts deleted file mode 100644 index 89b03bc..0000000 --- a/src/auth/agent.browser.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Returns nothing as browsers handle cookies for us - */ -export function getAgent (): any { - return { - agent: undefined, - jar: { - getCookies: () => [] - } - } -} diff --git a/src/auth/agent.ts b/src/auth/agent.ts deleted file mode 100644 index 3dde110..0000000 --- a/src/auth/agent.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CookieAgent } from 'http-cookie-agent/undici' -import { CookieJar } from 'tough-cookie' - -/** - * Returns an HTTP Agent that handles cookies over multiple requests - */ -export function getAgent (): { agent: CookieAgent, jar: CookieJar } { - const jar = new CookieJar() - - return { - agent: new CookieAgent({ - cookies: { - jar - } - }), - jar - } -} diff --git a/src/auth/client.ts b/src/auth/client.ts deleted file mode 100644 index 2e72dd9..0000000 --- a/src/auth/client.ts +++ /dev/null @@ -1,253 +0,0 @@ -import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' -import { peerIdFromPublicKey } from '@libp2p/peer-id' -import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' -import { getAgent } from './agent.js' -import { parseHeader, PeerIDAuthScheme, sign, verify } from './common.js' -import { BadResponseError, InvalidPeerError, InvalidSignatureError, MissingAuthHeaderError } from './errors.js' -import type { PeerId, PrivateKey } from '@libp2p/interface' -import type { AbortOptions } from '@multiformats/multiaddr' -import type { CookieAgent } from 'http-cookie-agent/undici' -import type { CookieJar } from 'tough-cookie' - -export interface TokenInfo { - creationTime: Date - bearer: string - peer: PeerId - agent: CookieAgent - jar: CookieJar -} - -export interface AuthenticatedFetchOptions extends RequestInit { - /** - * The Fetch implementation to use - * - * @default globalThis.fetch - */ - fetch?: typeof globalThis.fetch - - /** - * The hostname to use - by default this will be extracted from the `.host` - * property of `authEndpointURI` - */ - hostname?: string - - /** - * A function to verify the peer ID of the server. This function - * will be called after the server has authenticated itself. - * If the function returns false, the request will be aborted. - */ - verifyPeer?(peerId: PeerId, options: AbortOptions): boolean | Promise -} - -export interface AuthenticateServerOptions extends AbortOptions { - /** - * The Fetch implementation to use - * - * @default globalThis.fetch - */ - fetch?: AuthenticatedFetchOptions['fetch'] - - /** - * The hostname to use - by default this will be extracted from the `.host` - * property of `authEndpointURI` - */ - hostname?: AuthenticatedFetchOptions['hostname'] -} - -export interface DoAuthenticatedFetchOptions { - fetch?: AuthenticatedFetchOptions['fetch'] - hostname?: AuthenticatedFetchOptions['hostname'] -} - -export class ClientAuth { - key: PrivateKey - tokens = new Map() // A map from hostname to token - tokenTTL = 60 * 60 * 1000 // 1 hour - - constructor (key: PrivateKey, opts?: { tokenTTL?: number }) { - this.key = key - if (opts?.tokenTTL !== undefined) { - this.tokenTTL = opts.tokenTTL - } - } - - private generateChallenge (): string { - const randomBytes = new Uint8Array(32) - crypto.getRandomValues(randomBytes) - return uint8ArrayToString(randomBytes, 'base64urlpad') - } - - private encodeAuthParams (params: Record): string { - const encodedParams = Object.entries(params) - .map(([key, value]) => `${key}="${value}"`) - .join(', ') - return `${PeerIDAuthScheme} ${encodedParams}` - } - - public bearerAuthHeaderWithPeer (hostname: string): { 'authorization': string, peer: PeerId, agent: CookieAgent, jar: CookieJar } | undefined { - const token = this.tokens.get(hostname) - - if (token == null) { - return undefined - } - - if (Date.now() - token.creationTime.getTime() > this.tokenTTL) { - this.tokens.delete(hostname) - return undefined - } - - return { - authorization: `${PeerIDAuthScheme} bearer="${token.bearer}"`, - peer: token.peer, - agent: token.agent, - jar: token.jar - } - } - - public bearerAuthHeader (hostname: string): string | undefined { - return this.bearerAuthHeaderWithPeer(hostname)?.authorization - } - - /** - * authenticatedFetch is like `fetch`, but it also handles HTTP Peer ID - * authentication with the server. - * - * If we have not seen the server before, verifyPeer will be called to check - * if we want to make the request to the server with the given peer id. This - * happens after we've authenticated the server. - */ - public async authenticatedFetch (request: string | URL | Request, options?: AuthenticatedFetchOptions): Promise { - const { fetch, hostname, verifyPeer, ...requestOpts } = options ?? {} - let req: Request - if (request instanceof Request && Object.keys(requestOpts).length === 0) { - req = request - } else { - req = new Request(request, requestOpts) - } - const verifyPeerWithDefault = verifyPeer ?? (() => true) - - const { response, peer } = await this.doAuthenticatedFetch(req, verifyPeerWithDefault, { fetch, hostname }) - - const responseWithPeer: Response & { peer: PeerId } = response as Response & { peer: PeerId } - responseWithPeer.peer = peer - return responseWithPeer - } - - private async doAuthenticatedFetch (request: Request, verifyPeer: (server: PeerId, options: AbortOptions) => boolean | Promise, options?: DoAuthenticatedFetchOptions): Promise<{ peer: PeerId, response: Response }> { - const authEndpointURI = new URL(request.url) - const hostname = options?.hostname ?? authEndpointURI.host - const fetch = options?.fetch ?? globalThis.fetch - - if (this.tokens.has(hostname)) { - const token = this.bearerAuthHeaderWithPeer(hostname) - if (token !== undefined) { - // @ts-expect-error not in types - request.dispatcher = token.agent - request.headers.set('Authorization', token.authorization) - - await addCookiesToRequest(request, token.jar) - - return { peer: token.peer, response: await fetch(request) } - } else { - this.tokens.delete(hostname) - } - } - - // Client initiated handshake (server initiated is not implemented yet) - const marshaledClientPubKey = publicKeyToProtobuf(this.key.publicKey) - const publicKeyStr = uint8ArrayToString(marshaledClientPubKey, 'base64urlpad') - const challengeServer = this.generateChallenge() - const headers = { - Authorization: this.encodeAuthParams({ - 'challenge-server': challengeServer, - 'public-key': publicKeyStr - }) - } - - const { agent, jar } = getAgent() - - const resp = await fetch(authEndpointURI, { - method: 'OPTIONS', - headers, - signal: request.signal, - - // @ts-expect-error not in types - dispatcher: agent - }) - - // Verify the server's challenge - const authHeader = resp.headers.get('www-authenticate') - if (authHeader == null) { - throw new MissingAuthHeaderError('No auth header') - } - const authFields = parseHeader(authHeader) - const serverPubKeyBytes = uint8ArrayFromString(authFields['public-key'], 'base64urlpad') - const serverPubKey = publicKeyFromProtobuf(serverPubKeyBytes) - - const valid = await verify(serverPubKey, PeerIDAuthScheme, [ - ['hostname', hostname], - ['client-public-key', marshaledClientPubKey], - ['challenge-server', challengeServer]], uint8ArrayFromString(authFields.sig, 'base64urlpad')) - if (!valid) { - throw new InvalidSignatureError('Invalid signature') - } - - const serverPublicKey = publicKeyFromProtobuf(serverPubKeyBytes) - const serverID = peerIdFromPublicKey(serverPublicKey) - - if (!await verifyPeer(serverID, { signal: request.signal })) { - throw new InvalidPeerError('Id check failed') - } - - const sig = await sign(this.key, PeerIDAuthScheme, [ - ['hostname', hostname], - ['server-public-key', serverPubKeyBytes], - ['challenge-client', authFields['challenge-client']]]) - - const authenticateSelfHeaders = this.encodeAuthParams({ - opaque: authFields.opaque, - sig: uint8ArrayToString(sig, 'base64urlpad') - }) - - // @ts-expect-error not in types - request.dispatcher = agent - request.headers.set('Authorization', authenticateSelfHeaders) - - await addCookiesToRequest(request, jar) - - const resp2 = await fetch(request) - - if (!resp2.ok) { - throw new BadResponseError(`Unexpected status code ${resp2.status}`) - } - - const serverAuthHeader = resp2.headers.get('Authentication-Info') - if (serverAuthHeader == null) { - throw new MissingAuthHeaderError('No server auth header') - } - - const serverAuthFields = parseHeader(serverAuthHeader) - this.tokens.set(hostname, { - peer: serverID, - creationTime: new Date(), - bearer: serverAuthFields.bearer, - agent, - jar - }) - - return { peer: serverID, response: resp2 } - } - - public async authenticateServer (authEndpointURI: string | URL, options?: AuthenticateServerOptions): Promise { - const req = new Request(authEndpointURI, { signal: options?.signal }) - return (await this.authenticatedFetch(req, options)).peer - } -} - -async function addCookiesToRequest (request: Request, jar: CookieJar): Promise { - const cookies = await jar.getCookies(request.url.toString()) - - cookies.forEach(cookie => { - request.headers.append('Cookie', cookie.cookieString()) - }) -} diff --git a/src/auth/common.ts b/src/auth/common.ts deleted file mode 100644 index a2637ee..0000000 --- a/src/auth/common.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as varint from 'uint8-varint' -import type { PrivateKey, PublicKey } from '@libp2p/interface' - -export const PeerIDAuthScheme = 'libp2p-PeerID' -export const HTTPPeerIDAuthProto = '/http-peer-id-auth/1.0.0' - -export async function sign (key: PrivateKey, prefix: string, partsToSign: Array<[string, string | Uint8Array]>): Promise { - const dataToSign = genDataToSign(prefix, partsToSign) - return key.sign(dataToSign) -} - -export async function verify (key: PublicKey, prefix: string, partsToSign: Array<[string, string | Uint8Array]>, sig: Uint8Array): Promise { - const dataToSign = genDataToSign(prefix, partsToSign) - return key.verify(dataToSign, sig) -} - -export function encodeAuthParams (params: Record): string { - const encodedParams = Object.entries(params) - .map(([key, value]) => `${key}="${value}"`) - .join(', ') - return `${PeerIDAuthScheme} ${encodedParams}` -} - -const textEncoder = new TextEncoder() - -function sizeOfPart ([k, v]: [string, string | Uint8Array]): number { - return k.length + 1 + v.length // key + '=' + value -} - -function genDataToSign (prefix: string, partsToSign: Array<[string, string | Uint8Array]>): Uint8Array { - // Sort the parts - partsToSign.sort((a, b) => a[0].localeCompare(b[0])) - const size = partsToSign.reduce((acc, p) => acc + varint.encodingLength(sizeOfPart(p)) + sizeOfPart(p), prefix.length) - const out = new Uint8Array(size) - let offset = 0 - const res = textEncoder.encodeInto(prefix, out) - offset += res.written - for (const [k, v] of partsToSign) { - const len = sizeOfPart([k, v]) - varint.encodeUint8Array(len, out, offset) - offset += varint.encodingLength(len) - let res = textEncoder.encodeInto(k, out.subarray(offset)) - offset += res.written - res = textEncoder.encodeInto('=', out.subarray(offset)) - offset += res.written - if (typeof v === 'string') { - res = textEncoder.encodeInto(v, out.subarray(offset)) - offset += res.written - } else { - out.set(v, offset) - offset += v.length - } - } - return out -} - -const maxAuthHeaderSize = 2048 - -export function parseHeader (headerVal: string): Record { - if (headerVal.length > maxAuthHeaderSize) { - throw new Error('header too long') - } - - if (!headerVal.includes(PeerIDAuthScheme)) { - throw new Error('no peer id auth scheme found') - } - - const rest = headerVal.substring(PeerIDAuthScheme.length).trim() - const params: Record = {} - const regex = /(\w[^=]+)="([^"]+)"/g - - let match - while ((match = regex.exec(rest)) !== null) { - params[match[1]] = match[2] - } - - return params -} diff --git a/src/auth/index.ts b/src/auth/index.ts deleted file mode 100644 index c9888f3..0000000 --- a/src/auth/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { PeerIDAuthScheme, HTTPPeerIDAuthProto } from './common.js' -export { ClientAuth } from './client.js' -export { ServerAuth } from './server.js' - -export type { AuthenticatedFetchOptions, AuthenticateServerOptions, TokenInfo } from './client.js' -export type { ServerAuthOps, HttpHandler } from './server.js' diff --git a/src/auth/server.ts b/src/auth/server.ts deleted file mode 100644 index cf49222..0000000 --- a/src/auth/server.ts +++ /dev/null @@ -1,291 +0,0 @@ -import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys' -import { peerIdFromPublicKey, peerIdFromString } from '@libp2p/peer-id' -import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' -import { encodeAuthParams, parseHeader, PeerIDAuthScheme, sign, verify } from './common.js' -import type { PeerId, PrivateKey, PublicKey, Logger } from '@libp2p/interface' -import type http from 'node:http' - -export interface HttpHandler { (req: Request): Promise } - -export interface ServerAuthOps { - logger?: Logger - tokenTTL?: number -} - -export class ServerAuth { - private readonly key: PrivateKey - private readonly validHostname: (hostname: string) => boolean - private readonly tokenTTL = 60 * 60 * 1000 // 1 hour - private readonly logger?: Logger - - constructor (key: PrivateKey, validHostnames: (hostname: string) => boolean, opts?: ServerAuthOps) { - this.key = key - this.validHostname = validHostnames - this.logger = opts?.logger - if (opts?.tokenTTL !== undefined) { - this.tokenTTL = opts.tokenTTL - } - } - - httpHandler = this.withAuth.bind(this)(async (_peer, _req) => { - return new Response('', { status: 200 }) - }) - - withAuth (httpAuthedHandler: (peer: PeerId, req: Request) => Promise): HttpHandler { - return async (req: Request): Promise => { - const authResp = await this.authenticateRequest(this.readHostname(req), req.headers.get('Authorization') ?? undefined) - if (authResp.status !== 200 || authResp.peer === undefined) { - return new Response('', { status: authResp.status, headers: authResp.headers }) - } - - const innerHandlerResp = await httpAuthedHandler(authResp.peer, req) - - const mergedHeaders: Record = {} - // Merge using for of to only bring in actual fields from the headers (no - // inner symbols) - for (const [key, value] of innerHandlerResp.headers) { - mergedHeaders[key] = value - } - if (authResp.headers !== undefined) { - for (const [key, value] of Object.entries(authResp.headers)) { - mergedHeaders[key] = value - } - } - - return new Response(innerHandlerResp.body, { status: innerHandlerResp.status, headers: mergedHeaders }) - } - } - - requestListener (httpAuthedHandler: (peer: PeerId, req: http.IncomingMessage, res: http.ServerResponse) => void): http.RequestListener { - return (req: http.IncomingMessage, res: http.ServerResponse): void => { - Promise.resolve() - .then(async () => { - const authResp = await this.authenticateRequest(req.headers.host ?? '', req.headers.authorization) - - for (const [key, value] of Object.entries(authResp.headers ?? {})) { - res.setHeader(key, value) - } - - if (authResp.status !== 200 || authResp.peer === undefined) { - res.statusCode = authResp.status - res.end() - - return - } - - httpAuthedHandler(authResp.peer, req, res) - }) - .catch(err => { - this.logger?.error('error handling request - %e', err) - }) - } - } - - /* eslint-disable-next-line complexity */ - private async authenticateRequest (hostname: string, authHeader?: string): Promise { - if (!this.validHostname(hostname)) { - return { status: 400 } - } - - if (authHeader === null || authHeader === undefined || authHeader === '') { - return this.returnChallenge(hostname, null, {}) - } - - const authFields = parseHeader(authHeader) - if (authFields.bearer !== undefined && authFields.bearer !== '') { - const peer = await this.unwrapBearerToken(hostname, authFields.bearer) - return { status: 200, peer } - } - - let opaqueState: OpaqueUnwrapped | null = null - if (authFields.opaque !== undefined) { - try { - const opaque = await this.unwrapOpaque(authFields.opaque) - if (opaque.hostname !== hostname) { - this.logger?.error('Invalid hostname') - return { status: 400 } - } - if (Date.now() - opaque.creationTime > this.tokenTTL) { - this.logger?.error('Token expired') - return { status: 400 } - } - - opaqueState = opaque - } catch (e) { - this.logger?.error('Invalid opaque') - return { status: 400 } - } - } - - let clientPublicKey: PublicKey | null = null - if (opaqueState?.clientPublicKey !== undefined) { - clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(opaqueState.clientPublicKey, 'base64urlpad')) - } else if (authFields['public-key'] !== undefined) { - clientPublicKey = publicKeyFromProtobuf(uint8ArrayFromString(authFields['public-key'], 'base64urlpad')) - } - - const returnParams: Record = {} - let clientPeerId: PeerId | undefined - if (authFields.sig !== undefined) { - // Verify signature - if (clientPublicKey === null) { - this.logger?.error('Missing public-key') - return { status: 400 } - } - if (opaqueState?.challengeClient === null) { - this.logger?.error('Missing challenge-client') - return { status: 400 } - } - - const valid = await verify(clientPublicKey, PeerIDAuthScheme, [ - ['challenge-client', opaqueState?.challengeClient ?? ''], - ['hostname', hostname], - ['server-public-key', publicKeyToProtobuf(this.key.publicKey)] - ], uint8ArrayFromString(authFields.sig, 'base64urlpad')) - if (!valid) { - this.logger?.error('Invalid signature') - return { status: 400 } - } - - // Return a bearer token - clientPeerId = peerIdFromPublicKey(clientPublicKey) - returnParams.bearer = this.genBearerToken(clientPeerId, hostname) - } - - if (authFields['challenge-server'] !== undefined) { - if (clientPublicKey === null) { - this.logger?.error('Missing public-key') - return { status: 400 } - } - - // Sign and return challenge - const sig = await sign(this.key, PeerIDAuthScheme, [ - ['hostname', hostname], - ['client-public-key', publicKeyToProtobuf(clientPublicKey)], - ['challenge-server', authFields['challenge-server']] - ]) - returnParams['public-key'] = uint8ArrayToString(publicKeyToProtobuf(this.key.publicKey), 'base64urlpad') - returnParams.sig = uint8ArrayToString(sig, 'base64urlpad') - } - - if (returnParams.bearer !== undefined) { - return { status: 200, peer: clientPeerId, headers: { 'Authentication-info': encodeAuthParams(returnParams) } } - } else { - // Not authenticated - return this.returnChallenge(hostname, clientPublicKey, returnParams) - } - } - - private readHostname (req: Request): string { - const url = new URL(req.url) - let hostname = url.hostname - if (url.port === '' || url.port === undefined) { - return hostname - } - if (url.protocol === 'http:' && url.port !== '80') { - hostname += ':' + url.port - } - if (url.protocol === 'https:' && url.port !== '443') { - hostname += ':' + url.port - } - if (hostname === '') { - throw new Error('No hostname') - } - return hostname - } - - private async returnChallenge (hostname: string, clientPublicKey: PublicKey | null, returnParams: Record): Promise { - const challenge = this.generateChallenge() - returnParams['challenge-client'] = challenge - - returnParams.opaque = this.genOpaque({ - challengeClient: challenge, - clientPublicKey: clientPublicKey !== null ? uint8ArrayToString(publicKeyToProtobuf(clientPublicKey), 'base64urlpad') : undefined, - hostname, - creationTime: Date.now() - }) - return { status: 401, headers: { 'WWW-Authenticate': encodeAuthParams(returnParams) } } - } - - private genBearerToken (clientPeerId: PeerId, hostname: string): string { - return this.signBox(this.key, { - peer: clientPeerId.toString(), - h: hostname, - t: Date.now() - }) - } - - private async unwrapBearerToken (expectedHostname: string, token: string): Promise { - if (token.length < PeerIDAuthScheme.length + 1) { - throw new Error('Invalid bearer token') - } - const bearer = parseHeader(token).bearer - const unwrapped = await this.verifyBox(this.key.publicKey, bearer) as any - if (typeof unwrapped.peer !== 'string' || typeof unwrapped.h !== 'string' || typeof unwrapped.t !== 'number') { - throw new Error('Invalid bearer token') - } - if (unwrapped.h !== expectedHostname) { - throw new Error('Invalid hostname') - } - if (Date.now() - unwrapped.t > this.tokenTTL) { - throw new Error('Token expired') - } - return peerIdFromString(unwrapped.peer) - } - - private genOpaque (unwrapped: OpaqueUnwrapped): string { - return this.signBox(this.key, unwrapped) - } - - private async unwrapOpaque (opaque: string): Promise { - const unwrapped = await this.verifyBox(this.key.publicKey, opaque) as any - if (typeof unwrapped.challengeClient !== 'string' || typeof unwrapped.hostname !== 'string' || typeof unwrapped.creationTime !== 'number') { - throw new Error('Invalid opaque') - } - return unwrapped - } - - private signBox (key: PrivateKey, data: unknown): string { - const dataSerialized = JSON.stringify(data) - const dataBytes = textEncoder.encode(dataSerialized) - const sig = key.sign(dataBytes) - const jsonStr = JSON.stringify({ - val: uint8ArrayToString(dataBytes, 'base64urlpad'), - sig: uint8ArrayToString(sig, 'base64urlpad') - }) - return uint8ArrayToString(textEncoder.encode(jsonStr), 'base64urlpad') - } - - private async verifyBox (key: PublicKey, data: string): Promise { - const { sig, val } = JSON.parse(textDecoder.decode(uint8ArrayFromString(data, 'base64urlpad'))) - const valBytes = uint8ArrayFromString(val, 'base64urlpad') - const sigValid = await key.verify(valBytes, uint8ArrayFromString(sig, 'base64urlpad')) - if (!sigValid) { - throw new Error('Invalid signature') - } - const valStr = textDecoder.decode(valBytes) - return JSON.parse(valStr) - } - - private generateChallenge (): string { - const randomBytes = new Uint8Array(32) - crypto.getRandomValues(randomBytes) - return uint8ArrayToString(randomBytes, 'base64urlpad') - } -} - -interface OpaqueUnwrapped { - challengeClient: string - clientPublicKey?: string - hostname: string - creationTime: number -} - -const textEncoder = new TextEncoder() -const textDecoder = new TextDecoder() - -interface AuthenticationResponse { - status: number - headers?: Record - peer?: PeerId | undefined -} diff --git a/src/fetch.ts b/src/fetch.ts deleted file mode 100644 index 3204c3e..0000000 --- a/src/fetch.ts +++ /dev/null @@ -1,375 +0,0 @@ -/* eslint-disable max-depth */ -/* eslint-disable complexity */ - -import { HTTPParser } from '@achingbrain/http-parser-js' -import { multiaddr, protocols } from '@multiformats/multiaddr' -import { multiaddrToUri } from '@multiformats/multiaddr-to-uri' -import defer from 'p-defer' -import { type Uint8ArrayList } from 'uint8arraylist' - -interface Fetch { (req: Request): Promise } - -function getStringMethod (method: number): string { - return HTTPParser.methods[method] ?? 'UNKNOWN' -} - -interface Duplex> { - source: AsyncIterable | Iterable - sink(source: AsyncIterable | Iterable): RSink -} - -let ranDetectionForBrokenReqBody = false -let brokenRequestBody = false - -/** - * Detects if the request body can not be a ReadableStream and should be read in - * full before returning the request This is only an issue in the current version of Firefox. - * - * @returns true if the request body can not be a ReadableStream and should be read in full before returning the request - */ -async function detectBrokenRequestBody (): Promise { - if (ranDetectionForBrokenReqBody) { - return brokenRequestBody - } - ranDetectionForBrokenReqBody = true - const rs = new ReadableStream({ - start (controller) { - controller.enqueue(new Uint8Array([0])) - controller.close() - } - }) - - const req = new Request('https://example.com', { - method: 'POST', - body: rs, - // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit - duplex: 'half' - }) - - const ab = await req.arrayBuffer() - brokenRequestBody = ab.byteLength !== 1 - return brokenRequestBody -} - -/** - * Create a fetch function that can be used to fetch requests via a duplex stream - * - * @returns a function that can be used to fetch requests via a duplex stream - */ -export function fetchViaDuplex (s: Duplex): Fetch { - return async (req) => { - await writeRequestToDuplex(s, req) - const [respP] = readHTTPMsg(false, s) - const resp = await respP - if (!(resp instanceof Response)) { - throw new Error('Expected a response') - } - return resp - } -} - -/** - * A function that can be used to handle HTTP requests - */ -export interface HTTPHandler { - (req: Request): Promise -} - -/** - * - * @param s - Duplex where the request will be read from and the response will be written to - * @param h - HTTP handler that will be called with the request - */ -export async function handleRequestViaDuplex (s: Duplex, h: HTTPHandler): Promise { - const [reqP] = readHTTPMsg(true, s) - const req = await reqP - if (!(req instanceof Request)) { - throw new Error('Expected a request') - } - - const resp = await h(req) - await writeResponseToDuplex(s, resp) -} - -/** - * Exported for testing. - * - * @param expectRequest - is this a Request or a Response - * @param r - where to read from - * @returns two promises. The first is the parsed Request or Response. The second is a promise that resolves when the parsing is done. - */ -export function readHTTPMsg (expectRequest: boolean, r: Duplex): [Promise, Promise] { - const msgPromise = defer() - - return [ - msgPromise.promise, - (async () => { - const body = new TransformStream() - const writer = body.writable.getWriter() - let messageComplete = false - let fulfilledMsgPromise = false - - const parser = new HTTPParser(expectRequest ? 'REQUEST' : 'RESPONSE') - parser[HTTPParser.kOnHeadersComplete] = (info) => { - fulfilledMsgPromise = true - - // Handle the headers - const headers = new Headers() - - for (let i = 0; i < info.headers.length; i += 2) { - headers.set(info.headers[i], info.headers[i + 1]) - } - - let reqBody: ReadableStream | null = body.readable - - // Headers are parsed. We can return the response - try { - if (expectRequest) { - if (getStringMethod(info.method) === 'GET') { - reqBody = null - } - - const urlWithHost = `https://${headers.get('Host') ?? 'unknown_host._libp2p'}${info.url}` - detectBrokenRequestBody().then(async (broken) => { - let req: Request - if (!broken) { - req = new Request(urlWithHost, { - method: getStringMethod(info.method), - body: reqBody, - headers, - // @ts-expect-error this is required by NodeJS despite being the only reasonable option https://fetch.spec.whatwg.org/#requestinit - duplex: 'half' - }) - } else { - if (reqBody === null) { - req = new Request(urlWithHost, { - method: getStringMethod(info.method), - headers - }) - } else { - // Unfortunate workaround for a bug in Firefox's Request implementation. - // They don't support ReadableStream bodies, so we need to read the whole body. - const rdr = reqBody.getReader() - const parts = [] - while (true) { - const { done, value } = await rdr.read() - if (done) { - break - } - if (value !== undefined) { - parts.push(value) - } - } - const totalSize = parts.reduce((acc, part) => acc + part.byteLength, 0) - const body = new Uint8Array(totalSize) - for (let i = 0, offset = 0; i < parts.length; i++) { - body.set(parts[i], offset) - offset += parts[i].byteLength - } - req = new Request(urlWithHost, { - method: getStringMethod(info.method), - body, - headers - }) - } - } - msgPromise.resolve(req) - fulfilledMsgPromise = true - }).catch(err => { - msgPromise.reject(err) - }) - } else { - let respBody: ReadableStream | null = body.readable - if (info.statusCode === 204) { - respBody = null - } - const resp = new Response(respBody, { - headers, - status: info.statusCode, - statusText: info.statusMessage - }) - msgPromise.resolve(resp) - fulfilledMsgPromise = true - } - } catch (error) { - msgPromise.reject(error) - } - } - parser[HTTPParser.kOnBody] = (buf) => { - writer.write(buf) - .catch((err: Error) => { - msgPromise.reject(err) - }) - } - parser[HTTPParser.kOnMessageComplete] = () => { - messageComplete = true - writer.close() - .catch((err: Error) => { - msgPromise.reject(err) - }) - } - - // Consume data - for await (const chunks of r.source) { - const chunk = chunks.subarray() - parser.execute(chunk) - } - - parser.finish() - - if (!messageComplete) { - await writer.abort(new Error('Incomplete HTTP message')) - - if (!fulfilledMsgPromise) { - msgPromise.reject(new Error('Incomplete HTTP message')) - } - } - })() - ] -} - -const multiaddrURIPrefix = 'multiaddr:' -const CRLF = '\r\n' -const encodedCRLF = new TextEncoder().encode(CRLF) -const encodedFinalChunk = new TextEncoder().encode(`0${CRLF}${CRLF}`) -async function writeRequestToDuplex (s: Duplex, request: Request): Promise { - const method = request.method - - let reqUrl = request.url - let path = '' - let urlHost = '' - if (reqUrl.startsWith(multiaddrURIPrefix)) { - reqUrl = reqUrl.substring(multiaddrURIPrefix.length) - const ma = multiaddr(reqUrl) - // Find the http-path component - const [, httpPathVal] = ma.stringTuples().find(([code, value]) => - code === protocols('http-path').code - - ) ?? ['', ''] - path = decodeURIComponent(httpPathVal ?? '') - - try { - const maWithoutPath = ma.decapsulateCode(protocols('http-path').code) - const url = new URL(multiaddrToUri(maWithoutPath)) - urlHost = url.host - } catch {} - } else { - const url = new URL(reqUrl) - urlHost = url.host - path = (url.pathname ?? '') + (url.search ?? '') - } - const headers = request.headers - - if (!path.startsWith('/')) { - path = `/${path}` - } - let httpRequest = `${method} ${path} HTTP/1.1${CRLF}` - - // Add Host header if not present - if (!headers.has('Host') && urlHost !== '') { - httpRequest += `Host: ${urlHost}${CRLF}` - } - // Add connection close - if (!headers.has('Connection')) { - httpRequest += `Connection: close${CRLF}` - } - - headers.forEach((value, name) => { - httpRequest += `${name}: ${value}${CRLF}` - }) - - let reqBody = request.body - if (request.body === undefined && typeof request.arrayBuffer === 'function') { - const body = await request.arrayBuffer() - if (body.byteLength > 0) { - reqBody = new ReadableStream({ - start (controller) { - controller.enqueue(new Uint8Array(body)) - controller.close() - } - }) - } else { - reqBody = null - } - } - - const requestIncludesContentAndNeedsContentLength = reqBody !== null && !headers.has('Content-Length') && (method === 'POST' || method === 'PUT' || method === 'PATCH') - - if (requestIncludesContentAndNeedsContentLength) { - // If we don't have the content length, we need to use chunked encoding - httpRequest += `Transfer-Encoding: chunked${CRLF}` - } - httpRequest += CRLF - - void s.sink((async function * () { - const httpRequestBuffer = new TextEncoder().encode(httpRequest) - yield httpRequestBuffer - - if (reqBody === null || reqBody === undefined) { - return - } - - const reader = reqBody.getReader() - try { - while (true) { - const { done, value } = await reader.read() - // If the stream is done, break the loop - if (done) { - if (requestIncludesContentAndNeedsContentLength) { - yield encodedFinalChunk - } - break - } - - // add the chunk length - if (requestIncludesContentAndNeedsContentLength) { - const chunkLength = value.byteLength.toString(16) - const chunkLengthBuffer = new TextEncoder().encode(`${chunkLength}${CRLF}`) - yield chunkLengthBuffer - } - - yield value - - if (requestIncludesContentAndNeedsContentLength) { - yield encodedCRLF - } - } - } finally { - reader.releaseLock() - } - })()) -} - -async function writeResponseToDuplex (s: Duplex, resp: Response): Promise { - await s.sink((async function * () { - const textEncoder = new TextEncoder() - const status = resp.status - const reason = resp.statusText - const headers = resp.headers - - let httpRequest = `HTTP/1.1 ${status} ${reason}${CRLF}` - - // Add connection close - if (!headers.has('Connection')) { - httpRequest += `Connection: close${CRLF}` - } - - headers.forEach((value, name) => { - httpRequest += `${name}: ${value}${CRLF}` - }) - httpRequest += CRLF - - yield textEncoder.encode(httpRequest) - - if (resp.body !== null && resp.body !== undefined) { - const reader = resp.body.getReader() - while (true) { - const { done, value } = await reader.read() - if (done) { - break - } - yield value - } - } - })()) -} diff --git a/test/auth/index.spec.ts b/test/auth/index.spec.ts deleted file mode 100644 index 37ab4f6..0000000 --- a/test/auth/index.spec.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* eslint-env mocha */ -import { generateKeyPair, privateKeyFromProtobuf } from '@libp2p/crypto/keys' -import { peerIdFromPrivateKey } from '@libp2p/peer-id' -import { expect } from 'aegir/chai' -import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays' -import { ClientAuth } from '../../src/auth/client.js' -import { PeerIDAuthScheme, sign } from '../../src/auth/common.js' -import { ServerAuth } from '../../src/auth/server.js' -import type { PeerId, PrivateKey } from '@libp2p/interface' - -describe('HTTP Peer ID Authentication', () => { - let init = false - let clientKey: PrivateKey - let serverKey: PrivateKey - let server: PeerId - beforeEach(async () => { - if (!init) { - init = true - clientKey = await generateKeyPair('Ed25519') - serverKey = await generateKeyPair('Ed25519') - server = peerIdFromPrivateKey(serverKey) - } - }) - - it('Should mutually authenticate', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h === 'example.com') - - const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { - const req = new Request(input, init) - const resp = await serverAuth.httpHandler(req) - return resp - } - - const observedServerPeerId = await clientAuth.authenticateServer('https://example.com/auth', { - fetch - }) - expect(observedServerPeerId.equals(server)).to.be.true() - }) - - it('Should mutually authenticate with a custom port', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h === 'foobar:12345') - - const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { - const req = new Request(input, init) - const resp = await serverAuth.httpHandler(req) - return resp - } - - const observedServerPeerId = await clientAuth.authenticateServer('https://foobar:12345/auth', { - fetch - }) - expect(observedServerPeerId.equals(server)).to.be.true() - }) - - it('Should time out when authenticating', async () => { - const clientAuth = new ClientAuth(clientKey) - - const controller = new AbortController() - controller.abort() - - await expect(clientAuth.authenticateServer('https://example.com/auth', { - signal: controller.signal - })).to.eventually.be.rejected - .with.property('name', 'AbortError') - }) - - it('Should sent request body to authenticated server', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h === 'example.com') - - const echoHandler = async (req: Request): Promise => { - return new Response(await req.text()) - } - const httpHandler = serverAuth.withAuth(async (clientId, req) => { return echoHandler(req) }) - - const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { - const req = new Request(input, init) - return httpHandler(req) - } - - const expectedBody = 'Only for authenticated servers!' - const response = await clientAuth.authenticatedFetch('https://example.com/auth', { method: 'POST', body: expectedBody, verifyPeer: (observedId) => observedId.equals(server), fetch }) - - expect((await response.text())).to.be.equal(expectedBody) - expect(response.peer.equals(server)).to.be.true() - }) - - it('Should match the test vectors', async () => { - const clientKeyHex = '080112208139770ea87d175f56a35466c34c7ecccb8d8a91b4ee37a25df60f5b8fc9b394' - const serverKeyHex = '0801124001010101010101010101010101010101010101010101010101010101010101018a88e3dd7409f195fd52db2d3cba5d72ca6709bf1d94121bf3748801b40f6f5c' - const clientPubKeyEncoded = uint8ArrayFromString(clientKeyHex, 'base16') - const serverKey = privateKeyFromProtobuf(uint8ArrayFromString(serverKeyHex, 'base16')) - - const serverSig = await sign(serverKey, PeerIDAuthScheme, [ - ['challenge-server', 'ERERERERERERERERERERERERERERERERERERERERERE='], - ['client-public-key', clientPubKeyEncoded], - ['hostname', 'example.com'] - ]) - expect(uint8ArrayToString(serverSig, 'base64urlpad')).to.equal('UA88qZbLUzmAxrD9KECbDCgSKAUBAvBHrOCF2X0uPLR1uUCF7qGfLPc7dw3Olo-LaFCDpk5sXN7TkLWPVvuXAA==') - }) -}) diff --git a/test/fixtures/to-websocket.ts b/test/fixtures/to-websocket.ts deleted file mode 100644 index 5dc6b3e..0000000 --- a/test/fixtures/to-websocket.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { normalizeUrl } from '../../src/utils.js' -import type { IncomingMessage } from '../../src/http/incoming-message.js' -import type { WebSocket as WSSWebSocket } from 'ws' - -export function toWebSocket (ws: WSSWebSocket, req: IncomingMessage): WebSocket { - const url = normalizeUrl(req) - - Object.defineProperty(ws, 'url', { - value: url.toString(), - writable: false - }) - - // @ts-expect-error not a WS/WebSocket method - ws.dispatchEvent = (evt: Event) => { - if (evt.type === 'close') { - ws.emit('close') - } - - if (evt.type === 'open') { - ws.emit('open') - } - - if (evt.type === 'message') { - const m = evt as MessageEvent - ws.emit('data', m.data) - } - - if (evt.type === 'error') { - ws.emit('error', new Error('An error occurred')) - } - ws.emit(evt.type, evt) - } - - // @ts-expect-error ws is now WebSocket - return ws -} From cf5169642152c46860ec792e468e24c6c8410fb6 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 29 Apr 2025 09:30:33 +0100 Subject: [PATCH 09/22] chore: update deps, tests passing --- packages/http-fetch/package.json | 8 +- packages/http-fetch/src/errors.ts | 4 + packages/http-fetch/src/read-response.ts | 7 +- .../http-fetch/test/fixtures/cases.ts | 0 packages/http-fetch/test/index.spec.ts | 170 +++++++++++++- packages/http-utils/package.json | 1 + packages/http-utils/src/index.ts | 57 ++++- packages/http/package.json | 3 - packages/http/src/registrar.ts | 62 +----- packages/interop/test/cookies.spec.ts | 2 +- packages/interop/test/peer-id-auth.spec.ts | 98 ++++---- test/auth.spec.ts | 107 --------- test/fetch/index.spec.ts | 209 ------------------ 13 files changed, 298 insertions(+), 430 deletions(-) create mode 100644 packages/http-fetch/src/errors.ts rename test/fetch/cases/cases.js => packages/http-fetch/test/fixtures/cases.ts (100%) delete mode 100644 test/auth.spec.ts delete mode 100644 test/fetch/index.spec.ts diff --git a/packages/http-fetch/package.json b/packages/http-fetch/package.json index 3f725fb..1f5c5ac 100644 --- a/packages/http-fetch/package.json +++ b/packages/http-fetch/package.json @@ -140,13 +140,17 @@ }, "dependencies": { "@achingbrain/http-parser-js": "^0.5.9", - "@libp2p/interface": "^2.2.0", "@libp2p/http-utils": "^0.0.0", + "@libp2p/interface": "^2.2.0", "it-byte-stream": "^2.0.1", "uint8arrays": "^5.1.0" }, "devDependencies": { - "aegir": "^45.0.0" + "@libp2p/logger": "^5.1.15", + "aegir": "^45.0.0", + "it-drain": "^3.0.8", + "it-pair": "^2.0.6", + "sinon-ts": "^2.0.0" }, "sideEffects": false } diff --git a/packages/http-fetch/src/errors.ts b/packages/http-fetch/src/errors.ts new file mode 100644 index 0000000..0587eec --- /dev/null +++ b/packages/http-fetch/src/errors.ts @@ -0,0 +1,4 @@ +export class InvalidResponseError extends Error { + static name = 'InvalidResponseError' + name = 'InvalidResponseError' +} diff --git a/packages/http-fetch/src/read-response.ts b/packages/http-fetch/src/read-response.ts index 3682a80..a162831 100644 --- a/packages/http-fetch/src/read-response.ts +++ b/packages/http-fetch/src/read-response.ts @@ -1,5 +1,6 @@ import { HTTPParser } from '@achingbrain/http-parser-js' import { Response } from '@libp2p/http-utils' +import { InvalidResponseError } from './errors.js' import type { SendRequestInit } from './index.js' import type { Stream } from '@libp2p/interface' import type { ByteStream } from 'it-byte-stream' @@ -64,6 +65,7 @@ export async function readResponse (bytes: ByteStream, resource: URL, in .then(async () => { let read = 0 while (true) { + init.log('reading response') const chunk = await bytes.read({ signal: init.signal ?? undefined }) @@ -78,15 +80,14 @@ export async function readResponse (bytes: ByteStream, resource: URL, in } if (!headersComplete) { - reject(new Error(`Response ended before headers were received, read ${read} bytes`)) + reject(new InvalidResponseError(`Response ended before headers were received, read ${read} bytes`)) } break } - read += chunk.byteLength - init.log('response stream read %d bytes', chunk.byteLength) + read += chunk.byteLength parser.execute(chunk.subarray(), 0, chunk.byteLength) } }) diff --git a/test/fetch/cases/cases.js b/packages/http-fetch/test/fixtures/cases.ts similarity index 100% rename from test/fetch/cases/cases.js rename to packages/http-fetch/test/fixtures/cases.ts diff --git a/packages/http-fetch/test/index.spec.ts b/packages/http-fetch/test/index.spec.ts index b3ed8f6..824f03a 100644 --- a/packages/http-fetch/test/index.spec.ts +++ b/packages/http-fetch/test/index.spec.ts @@ -1,5 +1,173 @@ +/* eslint-disable no-console */ +/* eslint-env mocha */ + +import { readHeaders, responseToStream, streamToRequest } from '@libp2p/http-utils' +import { defaultLogger } from '@libp2p/logger' +import { expect } from 'aegir/chai' +import drain from 'it-drain' +import { duplexPair } from 'it-pair/duplex' +import { stubInterface } from 'sinon-ts' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' +import { fetch } from '../src/index.js' +import { cases } from './fixtures/cases.js' +import type { Stream } from '@libp2p/interface' + +function serve (server: any, handler: (req: Request) => Response | Promise): void { + const stream = stubInterface({ + ...server, + closeWrite: async () => {} + }) + + void Promise.resolve().then(async () => { + const info = await readHeaders(stream) + const res = await handler(streamToRequest(info, stream)) + await responseToStream(res, stream) + }) +} + +function echo (server: any): void { + serve(server, (req) => { + return new Response(req.body, { + headers: req.headers + }) + }) +} + describe('@libp2p/http-fetch', () => { - it('should run a test', () => { + it('should make a simple GET request', async () => { + const [client, server] = duplexPair() + + serve(server, (req) => { + return new Response('Hello World') + }) + + const res = await fetch(stubInterface(client), 'https://example.com', { + logger: defaultLogger() + }) + + expect(await res.text()).to.equal('Hello World') + }) + + it('should GET with headers', async () => { + const [client, server] = duplexPair() + + echo(server) + + const res = await fetch(stubInterface(client), 'https://example.com', { + logger: defaultLogger(), + headers: { + 'X-Test': 'foo' + } + }) + + expect(res.headers.get('X-Test')).to.equal('foo') + }) + + it('should POST some data', async () => { + const [client, server] = duplexPair() + + echo(server) + + const res = await fetch(stubInterface(client), 'https://example.com', { + logger: defaultLogger(), + method: 'POST', + body: 'Hello World' + }) + + expect(await res.text()).to.equal('Hello World') + }) + + it('should handle trash', async () => { + const [client, server] = duplexPair() + + void server.sink([uint8ArrayFromString('FOOOOOOOOOOOOOOOOo')]) + void drain(server.source) + + await expect(fetch(stubInterface(client), 'https://example.com', { + logger: defaultLogger() + })).to.eventually.be.rejected() + .with.property('name', 'InvalidResponseError') + }) + + it('should handle messages that arrive in a trickle', async () => { + for (const httpCase of cases.filter(c => c.type === 'RESPONSE' && c.mayFail !== true)) { + const expectedStatusCode = httpCase.statusCode + + if (expectedStatusCode === undefined || expectedStatusCode === null) { + continue + } + + if (expectedStatusCode < 200 || expectedStatusCode >= 600) { + // Response object doesn't parse these + continue + } + + if (httpCase?.httpMajor !== 1 || httpCase?.httpMinor !== 1) { + // We don't use anything but HTTP/1.1 + continue + } + + const [client, server] = duplexPair() + + void server.sink((async function * () { + const rawHttp = new TextEncoder().encode(httpCase.raw) + // Trickle the response 1 byte at a time + for (let i = 0; i < rawHttp.length; i++) { + yield rawHttp.subarray(i, i + 1) + } + })()) + void drain(server.source) + + // Request doesn't matter + const resp = await fetch(stubInterface(client), 'https://example.com', { + logger: defaultLogger() + }) + + expect(resp.status).to.equal(expectedStatusCode) + const chunk = (arr: T[], size: number): T[][] => arr.reduce((chunks, el, i) => i % size === 0 ? [...chunks, [el]] : (chunks[chunks.length - 1].push(el), chunks), []) + for (const [key, value] of chunk(httpCase.headers, 2)) { + expect(resp.headers.get(key)).to.equal(value) + } + + expect(await resp.text()).to.equal(httpCase.body ?? '') + } + }) + + it('Parses all responses', async () => { + for (const httpCase of cases.filter(c => c.type === 'RESPONSE' && c.mayFail !== true)) { + const expectedStatusCode = httpCase.statusCode + + if (expectedStatusCode === undefined || expectedStatusCode === null) { + continue + } + + if (expectedStatusCode < 200 || expectedStatusCode >= 600) { + // Response object doesn't parse these + continue + } + + if (httpCase?.httpMajor !== 1 || httpCase?.httpMinor !== 1) { + // We don't use anything but HTTP/1.1 + continue + } + + const [client, server] = duplexPair() + + void server.sink([uint8ArrayFromString(httpCase.raw)]) + void drain(server.source) + + // Request doesn't matter + const resp = await fetch(stubInterface(client), 'https://example.com', { + logger: defaultLogger() + }) + + expect(resp.status).to.equal(expectedStatusCode) + const chunk = (arr: T[], size: number): T[][] => arr.reduce((chunks, el, i) => i % size === 0 ? [...chunks, [el]] : (chunks[chunks.length - 1].push(el), chunks), []) + for (const [key, value] of chunk(httpCase.headers, 2)) { + expect(resp.headers.get(key)).to.equal(value) + } + expect(await resp.text()).to.equal(httpCase.body ?? '') + } }) }) diff --git a/packages/http-utils/package.json b/packages/http-utils/package.json index 5663482..67b020b 100644 --- a/packages/http-utils/package.json +++ b/packages/http-utils/package.json @@ -139,6 +139,7 @@ "release": "aegir release" }, "dependencies": { + "@achingbrain/http-parser-js": "^0.5.9", "@libp2p/interface": "^2.2.0", "@libp2p/peer-id": "^5.0.7", "@multiformats/multiaddr": "^12.3.0", diff --git a/packages/http-utils/src/index.ts b/packages/http-utils/src/index.ts index a1820f0..268801a 100644 --- a/packages/http-utils/src/index.ts +++ b/packages/http-utils/src/index.ts @@ -4,6 +4,7 @@ * Contains shared code and utilities used by `@libp2p/http-*` modules. */ +import { HTTPParser } from '@achingbrain/http-parser-js' import { InvalidParametersError, isPeerId, ProtocolError } from '@libp2p/interface' import { peerIdFromString } from '@libp2p/peer-id' import { fromStringTuples, isMultiaddr, multiaddr } from '@multiformats/multiaddr' @@ -14,12 +15,12 @@ import itToBrowserReadableStream from 'it-to-browser-readablestream' import { base36 } from 'multiformats/bases/base36' import { base64pad } from 'multiformats/bases/base64' import { sha1 } from 'multiformats/hashes/sha1' +import { Uint8ArrayList } from 'uint8arraylist' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { DNS_CODECS, HTTP_CODEC, HTTP_PATH_CODEC } from './constants.js' import { Request } from './request.js' import type { AbortOptions, PeerId, Stream } from '@libp2p/interface' import type { Multiaddr } from '@multiformats/multiaddr' -import type { Uint8ArrayList } from 'uint8arraylist' /** * A subset of options passed to middleware @@ -485,6 +486,60 @@ export async function getServerUpgradeHeaders (headers: Headers | Record { + return new Promise((resolve, reject) => { + const parser = new HTTPParser('REQUEST') + const source = queuelessPushable() + const earlyData = new Uint8ArrayList() + let headersComplete = false + + parser[HTTPParser.kOnHeadersComplete] = (info) => { + headersComplete = true + const headers = new Headers() + + // set incoming headers + for (let i = 0; i < info.headers.length; i += 2) { + headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) + } + + resolve({ + ...info, + headers, + raw: earlyData, + method: HTTPParser.methods[info.method] + }) + } + + // replace source with request body + const streamSource = stream.source + stream.source = source + + Promise.resolve().then(async () => { + for await (const chunk of streamSource) { + // only use the message parser until the headers have been read + if (!headersComplete) { + earlyData.append(chunk) + parser.execute(chunk.subarray()) + } else { + await source.push(new Uint8ArrayList(chunk)) + } + } + + await source.end() + }) + .catch((err: Error) => { + stream.abort(err) + reject(err) + }) + .finally(() => { + parser.finish() + }) + }) +} + /** * Parsed from the incoming HTTP message */ diff --git a/packages/http/package.json b/packages/http/package.json index d7116cc..7b516a2 100644 --- a/packages/http/package.json +++ b/packages/http/package.json @@ -163,14 +163,11 @@ "release": "aegir release" }, "dependencies": { - "@achingbrain/http-parser-js": "^0.5.9", "@libp2p/http-peer-id-auth": "^0.0.0", "@libp2p/interface": "^2.2.0", "@libp2p/interface-internal": "^2.0.10", "@multiformats/multiaddr": "^12.3.0", "cookie": "^1.0.2", - "it-queueless-pushable": "^2.0.0", - "uint8arraylist": "^2.4.8", "undici": "^6.21.2", "@libp2p/http-fetch": "^0.0.0", "@libp2p/http-websocket": "^0.0.0", diff --git a/packages/http/src/registrar.ts b/packages/http/src/registrar.ts index 51557f6..a0a28fd 100644 --- a/packages/http/src/registrar.ts +++ b/packages/http/src/registrar.ts @@ -1,15 +1,11 @@ -import { HTTPParser } from '@achingbrain/http-parser-js' -import { NOT_FOUND_RESPONSE, normalizeMethod, normalizeUrl, responseToStream, streamToRequest } from '@libp2p/http-utils' +import { NOT_FOUND_RESPONSE, normalizeMethod, normalizeUrl, readHeaders, responseToStream, streamToRequest } from '@libp2p/http-utils' import { CLOSE_MESSAGES } from '@libp2p/http-websocket' import { InvalidParametersError } from '@libp2p/interface' -import { queuelessPushable } from 'it-queueless-pushable' -import { Uint8ArrayList } from 'uint8arraylist' import { HTTP_PROTOCOL, WEBSOCKET_HANDLER } from './constants.js' import { initializeRoute } from './routes/utils.js' import { wellKnownRoute } from './routes/well-known.js' import type { WebServer, HTTPRequestHandler, ProtocolMap, WebSocketHandler, HTTPRoute, HandlerRoute } from './index.js' -import type { HeaderInfo } from '@libp2p/http-utils' -import type { ComponentLogger, IncomingStreamData, Logger, Stream } from '@libp2p/interface' +import type { ComponentLogger, IncomingStreamData, Logger } from '@libp2p/interface' import type { Registrar } from '@libp2p/interface-internal' export interface HTTPRegistrarComponents { @@ -201,60 +197,6 @@ export class HTTPRegistrar { } } -/** - * Reads HTTP headers from an incoming stream - */ -async function readHeaders (stream: Stream): Promise { - return new Promise((resolve, reject) => { - const parser = new HTTPParser('REQUEST') - const source = queuelessPushable() - const earlyData = new Uint8ArrayList() - let headersComplete = false - - parser[HTTPParser.kOnHeadersComplete] = (info) => { - headersComplete = true - const headers = new Headers() - - // set incoming headers - for (let i = 0; i < info.headers.length; i += 2) { - headers.set(info.headers[i].toLowerCase(), info.headers[i + 1]) - } - - resolve({ - ...info, - headers, - raw: earlyData, - method: HTTPParser.methods[info.method] - }) - } - - // replace source with request body - const streamSource = stream.source - stream.source = source - - Promise.resolve().then(async () => { - for await (const chunk of streamSource) { - // only use the message parser until the headers have been read - if (!headersComplete) { - earlyData.append(chunk) - parser.execute(chunk.subarray()) - } else { - await source.push(new Uint8ArrayList(chunk)) - } - } - - await source.end() - }) - .catch((err: Error) => { - stream.abort(err) - reject(err) - }) - .finally(() => { - parser.finish() - }) - }) -} - function addHeaders (response: Response, request: Request, handler: ProtocolHandler): void { const allow = [...new Set(['OPTIONS', ...handler.route.method])].join(', ') diff --git a/packages/interop/test/cookies.spec.ts b/packages/interop/test/cookies.spec.ts index e4cc04a..47c39a7 100644 --- a/packages/interop/test/cookies.spec.ts +++ b/packages/interop/test/cookies.spec.ts @@ -90,7 +90,7 @@ const tests: Test[] = [{ }] for (const test of tests) { - describe.only(`cookies - ${test.name}`, () => { + describe(`cookies - ${test.name}`, () => { let client: Libp2p<{ http: HTTP }> let listenerMultiaddrs: Multiaddr[] diff --git a/packages/interop/test/peer-id-auth.spec.ts b/packages/interop/test/peer-id-auth.spec.ts index 4fe5918..95d6b23 100644 --- a/packages/interop/test/peer-id-auth.spec.ts +++ b/packages/interop/test/peer-id-auth.spec.ts @@ -93,7 +93,7 @@ const tests: Test[] = [{ }] for (const test of tests) { - describe(`peer id auth - ${test.name}`, () => { + describe(`peer id auth - HTTP over libp2p - ${test.name}`, () => { let client: Libp2p<{ http: HTTP }> let listenerMultiaddrs: Multiaddr[] @@ -259,56 +259,68 @@ for (const test of tests) { expect(response.status).to.equal(200) await expect(response.text()).to.eventually.equal('no-peer-id') }) + }) +} - /* - it('should mutually authenticate with a custom port', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h === 'foobar:12345') +const HTTP_SERVERS = [{ + name: 'node:http', + address: multiaddr(process.env.HTTP_NODE_HTTP_MULTIADDR) +}, { + name: 'express', + address: multiaddr(process.env.HTTP_EXPRESS_MULTIADDR) +}, { + name: 'fastify', + address: multiaddr(process.env.HTTP_FASTIFY_MULTIADDR) +}] - const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { - const req = new Request(input, init) - const resp = await serverAuth.httpHandler(req) - return resp - } +HTTP_SERVERS.forEach(test => { + describe(`peer id auth - libp2p over HTTP - ${test.name}`, () => { + let client: Libp2p<{ http: HTTP }> + let httpAddr: Multiaddr - const observedServerPeerId = await clientAuth.authenticateServer('https://foobar:12345/auth', { - fetch - }) - expect(observedServerPeerId.equals(server)).to.be.true() + beforeEach(async () => { + client = await getClient() + httpAddr = multiaddr(test.address) }) - it('should time out when authenticating', async () => { - const clientAuth = new ClientAuth(clientKey) - - const controller = new AbortController() - controller.abort() - - await expect(clientAuth.authenticateServer('https://example.com/auth', { - signal: controller.signal - })).to.eventually.be.rejected - .with.property('name', 'AbortError') + afterEach(async () => { + await stop(client) }) - it('should sent request body to authenticated server', async () => { - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h === 'example.com') - - const echoHandler = async (req: Request): Promise => { - return new Response(await req.text()) - } - const httpHandler = serverAuth.withAuth(async (clientId, req) => { return echoHandler(req) }) - - const fetch = async (input: string | URL | Request, init?: RequestInit): Promise => { - const req = new Request(input, init) - return httpHandler(req) - } + it('should support peer id auth', async () => { + const response = await client.services.http.fetch(httpAddr.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/peer-id')}`), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(client.peerId.toString()) + }) - const expectedBody = 'Only for authenticated servers!' - const response = await clientAuth.authenticatedFetch('https://example.com/auth', { method: 'POST', body: expectedBody, verifyPeer: (observedId) => observedId.equals(server), fetch }) + it('should support optional peer id auth', async () => { + const response = await client.services.http.fetch(httpAddr.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/optional-peer-id')}`), { + headers: { + host: 'test-with-auth.com' + }, + middleware: [ + peerIdAuth() + ] + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal(client.peerId.toString()) + }) - expect((await response.text())).to.be.equal(expectedBody) - expect(response.peer.equals(server)).to.be.true() + it('should support optional peer id auth without auth', async () => { + const response = await client.services.http.fetch(httpAddr.encapsulate(`/http-path/${encodeURIComponent('libp2p/http/optional-peer-id')}`), { + headers: { + host: 'test-with-auth.com' + } + }) + expect(response.status).to.equal(200) + await expect(response.text()).to.eventually.equal('no-peer-id') }) - */ }) -} +}) diff --git a/test/auth.spec.ts b/test/auth.spec.ts deleted file mode 100644 index 78a5d6a..0000000 --- a/test/auth.spec.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* eslint-disable max-nested-callbacks */ -import http from 'node:http' -import { generateKeyPair } from '@libp2p/crypto/keys' -import { peerIdFromPrivateKey } from '@libp2p/peer-id' -import { expect } from 'aegir/chai' -import pDefer from 'p-defer' -import { isNode, isElectronMain } from 'wherearewe' -import { ClientAuth, ServerAuth } from '../src/auth/index.js' -import type { PeerId, PrivateKey } from '@libp2p/interface' - -describe('client auth', () => { - let clientKey: PrivateKey - let serverKey: PrivateKey - let server: http.Server - - beforeEach(async () => { - clientKey = await generateKeyPair('Ed25519') - serverKey = await generateKeyPair('Ed25519') - }) - - afterEach(async () => { - server?.close() - server?.closeAllConnections() - }) - - it('should perform auth from client', async () => { - if (!isNode && !isElectronMain) { - return - } - - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h.startsWith('127.0.0.1')) - const clientPeer = pDefer() - const echoListener = serverAuth.requestListener((clientId, req, res) => { - clientPeer.resolve(clientId) - req.pipe(res) - }) - - server = http.createServer(echoListener) - - const port = await new Promise((resolve, reject) => { - const listener = server.listen(0, () => { - const address = listener.address() - - if (address == null || typeof address === 'string') { - reject(new Error('Could not listen on port')) - return - } - - resolve(address.port) - }) - }) - - await expect(clientAuth.authenticateServer(`http://127.0.0.1:${port}`)).to.eventually.deep.equal(peerIdFromPrivateKey(serverKey)) - await expect(clientPeer.promise).to.eventually.deep.equal(peerIdFromPrivateKey(clientKey)) - }) - - it('should respect cookies during auth', async () => { - if (!isNode && !isElectronMain) { - return - } - - const clientAuth = new ClientAuth(clientKey) - const serverAuth = new ServerAuth(serverKey, h => h.startsWith('127.0.0.1')) - const cookie = pDefer() - const echoListener = serverAuth.requestListener((clientId, req, res) => { - req.pipe(res) - }) - const cookieName = 'test-cookie-name' - const cookieValue = 'test-cookie-value' - let requests = 0 - - server = http.createServer((req, res) => { - requests++ - - const cookieHeader = req.headers.cookie - - if (cookieHeader == null) { - if (requests === 2) { - cookie.reject(new Error('No cookie header found on second request')) - } - - res.setHeader('set-cookie', `${cookieName}=${cookieValue}; Expires=${new Date(Date.now() + 86_400_000).toString()}; HttpOnly`) - } else { - cookie.resolve(cookieHeader) - } - - echoListener(req, res) - }) - - const port = await new Promise((resolve, reject) => { - const listener = server.listen(0, () => { - const address = listener.address() - - if (address == null || typeof address === 'string') { - reject(new Error('Could not listen on port')) - return - } - - resolve(address.port) - }) - }) - - await expect(clientAuth.authenticateServer(`http://127.0.0.1:${port}`)).to.eventually.deep.equal(peerIdFromPrivateKey(serverKey)) - await expect(cookie.promise).to.eventually.equal(`${cookieName}=${cookieValue}`) - }) -}) diff --git a/test/fetch/index.spec.ts b/test/fetch/index.spec.ts deleted file mode 100644 index 432cc19..0000000 --- a/test/fetch/index.spec.ts +++ /dev/null @@ -1,209 +0,0 @@ -/* eslint-disable no-console */ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import { duplexPair } from 'it-pair/duplex' -import { type Uint8ArrayList, isUint8ArrayList } from 'uint8arraylist' -import { fetchViaDuplex, handleRequestViaDuplex } from '../../src/fetch.js' -import { cases } from './cases/cases.js' - -describe('Roundtrips', () => { - it('handles a simple GET request', async () => { - const [client, server] = duplexPair() - - const serverHandler = handleRequestViaDuplex(server, async (req) => { - return new Response('Hello World') - }).catch((err) => { - console.error('Error handling request', err) - throw err - }) - - const resp = await fetchViaDuplex(client)(new Request('https://example.com/')) - expect(await resp.text()).to.equal('Hello World') - - // Assert we didn't fail here - await serverHandler - }) -}) - -describe('Make a fetch request via duplex', () => { - it('A simple GET request', async () => { - const [client, server] = duplexPair() - const respPromise = fetchViaDuplex(client)(new Request('http://example.com/')) - - let reqToServer = '' - const decoder = new TextDecoder() - for await (const chunk of server.source) { - if (isUint8ArrayList(chunk)) { - throw new Error('Should not be a Uint8ArrayList') - } - reqToServer += decoder.decode(chunk) - } - - expect(reqToServer).to.equal('GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n') - - void server.sink((async function * () { - yield new TextEncoder().encode('HTTP/1.1 200 OK\r\n\r\n') - })()) - const resp = await respPromise - expect(resp.status).to.equal(200) - }) - - it('A simple GET request with headers', async () => { - const [client, server] = duplexPair() - const respPromise = fetchViaDuplex(client)(new Request('http://example.com/', { headers: { 'X-Test': 'foo' } })) - - let reqToServer = '' - const decoder = new TextDecoder() - for await (const chunk of server.source) { - if (isUint8ArrayList(chunk)) { - throw new Error('Should not be a Uint8ArrayList') - } - reqToServer += decoder.decode(chunk) - } - - expect(reqToServer).to.equal('GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\nx-test: foo\r\n\r\n') - - void server.sink((async function * () { - yield new TextEncoder().encode('HTTP/1.1 200 OK\r\nX-test: bar\r\n\r\n') - })()) - const resp = await respPromise - expect(resp.status).to.equal(200) - expect(resp.headers.get('x-test')).to.equal('bar') - }) - - it('Post some data', async () => { - const [client, server] = duplexPair() - const respPromise = fetchViaDuplex(client)(new Request('http://example.com/?foo=bar', { method: 'POST', headers: { 'X-Test': 'foo' }, body: 'hello world' })) - - let reqToServer = '' - const decoder = new TextDecoder() - for await (const chunk of server.source) { - if (isUint8ArrayList(chunk)) { - throw new Error('Should not be a Uint8ArrayList') - } - reqToServer += decoder.decode(chunk) - } - - expect(reqToServer).to.equal('POST /?foo=bar HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\ncontent-type: text/plain;charset=UTF-8\r\nx-test: foo\r\nTransfer-Encoding: chunked\r\n\r\nb\r\nhello world\r\n0\r\n\r\n') - - void server.sink((async function * () { - yield new TextEncoder().encode('HTTP/1.1 200 OK\r\nX-test: bar\r\n\r\nbaz') - })()) - const resp = await respPromise - expect(resp.status).to.equal(200) - expect(resp.headers.get('x-test')).to.equal('bar') - expect(await resp.text()).to.equal('baz') - }) - - it('Handles trash', async () => { - const [client, server] = duplexPair() - const respPromise = fetchViaDuplex(client)(new Request('http://example.com/')) - - let reqToServer = '' - const decoder = new TextDecoder() - for await (const chunk of server.source) { - if (isUint8ArrayList(chunk)) { - throw new Error('Should not be a Uint8ArrayList') - } - reqToServer += decoder.decode(chunk) - } - - expect(reqToServer).to.equal('GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n') - - void server.sink((async function * () { - yield new TextEncoder().encode('FOOOOOOOOOOOOOOOOo') - })()) - await expect(respPromise).to.eventually.be.rejected() - }) - - it('Message comes in a trickle', async () => { - for (const httpCase of cases.filter(c => c.type === 'RESPONSE' && c.mayFail !== true)) { - const expectedStatusCode = httpCase.statusCode - if (expectedStatusCode === undefined || expectedStatusCode === null) { - continue - } - if (expectedStatusCode < 200 || expectedStatusCode >= 600) { - // Response object doesn't parse these - continue - } - if (httpCase?.httpMajor !== 1 || httpCase?.httpMinor !== 1) { - // We don't use anything but HTTP/1.1 - continue - } - const [client, server] = duplexPair() - // Request doesn't matter - const respPromise = fetchViaDuplex(client)(new Request('http://example.com/')) - - let reqToServer = '' - const decoder = new TextDecoder() - for await (const chunk of server.source) { - if (isUint8ArrayList(chunk)) { - throw new Error('Should not be a Uint8ArrayList') - } - reqToServer += decoder.decode(chunk) - } - expect(reqToServer).to.equal('GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n') - - void server.sink((async function * () { - const rawHttp = new TextEncoder().encode(httpCase.raw) - // Trickle the response 1 byte at a time - for (let i = 0; i < rawHttp.length; i++) { - yield rawHttp.subarray(i, i + 1) - } - })()) - const resp = await respPromise - - expect(resp.status).to.equal(expectedStatusCode) - const chunk = (arr: T[], size: number): T[][] => arr.reduce((chunks, el, i) => i % size === 0 ? [...chunks, [el]] : (chunks[chunks.length - 1].push(el), chunks), []) - for (const [key, value] of chunk(httpCase.headers, 2)) { - expect(resp.headers.get(key)).to.equal(value) - } - - expect(await resp.text()).to.equal(httpCase.body ?? '') - } - }) - - it('Parses all responses', async () => { - for (const httpCase of cases.filter(c => c.type === 'RESPONSE' && c.mayFail !== true)) { - const expectedStatusCode = httpCase.statusCode - if (expectedStatusCode === undefined || expectedStatusCode === null) { - continue - } - if (expectedStatusCode < 200 || expectedStatusCode >= 600) { - // Response object doesn't parse these - continue - } - if (httpCase?.httpMajor !== 1 || httpCase?.httpMinor !== 1) { - // We don't use anything but HTTP/1.1 - continue - } - const [client, server] = duplexPair() - // Request doesn't matter - const respPromise = fetchViaDuplex(client)(new Request('http://example.com/')) - - let reqToServer = '' - const decoder = new TextDecoder() - for await (const chunk of server.source) { - if (isUint8ArrayList(chunk)) { - throw new Error('Should not be a Uint8ArrayList') - } - reqToServer += decoder.decode(chunk) - } - expect(reqToServer).to.equal('GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n') - - void server.sink((async function * () { - yield new TextEncoder().encode(httpCase.raw) - })()) - const resp = await respPromise - - expect(resp.status).to.equal(expectedStatusCode) - const chunk = (arr: T[], size: number): T[][] => arr.reduce((chunks, el, i) => i % size === 0 ? [...chunks, [el]] : (chunks[chunks.length - 1].push(el), chunks), []) - for (const [key, value] of chunk(httpCase.headers, 2)) { - expect(resp.headers.get(key)).to.equal(value) - } - - expect(await resp.text()).to.equal(httpCase.body ?? '') - } - }) -}) From 81b6e381eda637f39689d5936228e7a4871221cf Mon Sep 17 00:00:00 2001 From: achingbrain Date: Tue, 29 Apr 2025 19:09:28 +0100 Subject: [PATCH 10/22] chore: updated examples --- examples/README.md | 27 +- examples/express-server-over-libp2p/README.md | 55 ++ .../express-server-over-libp2p/package.json | 24 + .../express-server-over-libp2p/src/client.js | 40 ++ .../express-server-over-libp2p/src/server.js | 52 ++ .../test/index.spec.js | 29 + examples/go-libp2p-http-proxy/client.js | 58 -- examples/go-libp2p-http-proxy/proxy/go.mod | 114 ---- examples/go-libp2p-http-proxy/proxy/go.sum | 553 ------------------ examples/go-libp2p-http-proxy/proxy/main.go | 55 -- examples/go-libp2p-http-proxy/proxy/proxy | Bin 29409618 -> 0 bytes examples/go-libp2p-http-proxy/server.js | 18 - examples/hono-server-over-libp2p/README.md | 54 ++ examples/hono-server-over-libp2p/client.js | 61 -- examples/hono-server-over-libp2p/package.json | 24 + examples/hono-server-over-libp2p/server.js | 65 -- .../hono-server-over-libp2p/src/client.js | 39 ++ .../hono-server-over-libp2p/src/server.js | 43 ++ .../test/index.spec.js | 29 + .../client.js | 57 -- .../server.js | 18 - examples/libp2p-over-http-server/README.md | 64 ++ examples/libp2p-over-http-server/package.json | 20 + .../src/client-http.js | 43 ++ .../src/client-libp2p.js | 33 ++ .../libp2p-over-http-server/src/common.js | 1 + .../libp2p-over-http-server/src/server.js | 44 ++ .../test/index.spec.js | 39 ++ examples/peer-id-auth/README.md | 40 +- examples/peer-id-auth/go-peer/main.go | 3 + examples/peer-id-auth/node.js | 79 --- examples/peer-id-auth/package.json | 20 + examples/peer-id-auth/runTest.sh | 59 -- examples/peer-id-auth/src/client.js | 28 + examples/peer-id-auth/src/server.js | 54 ++ examples/peer-id-auth/test/index.spec.js | 51 ++ .../README.md | 14 - .../client.js | 54 -- .../package.json | 17 - .../server.js | 46 -- .../test.js | 0 .../README.md | 87 +++ .../index.html | 46 ++ .../index.js | 116 ++++ .../package.json | 29 + .../src/proxy.js | 83 +++ .../src/relay.js | 35 ++ .../test-results/.last-run.json | 4 + .../test/index.spec.js | 95 +++ .../vite.config.js | 11 + examples/test-runner/README.md | 7 - examples/test-runner/main.go | 139 ----- examples/two-js-peers/client.js | 69 --- examples/two-js-peers/server.js | 38 -- examples/websockets-over-libp2p/README.md | 55 ++ examples/websockets-over-libp2p/package.json | 23 + examples/websockets-over-libp2p/src/client.js | 58 ++ examples/websockets-over-libp2p/src/server.js | 61 ++ .../websockets-over-libp2p/test/index.spec.js | 29 + packages/http-peer-id-auth/src/client.ts | 2 +- packages/http-peer-id-auth/src/index.ts | 5 +- packages/http-peer-id-auth/src/server.ts | 8 +- packages/http-peer-id-auth/src/utils.ts | 4 +- packages/http-ping/package.json | 1 - packages/http-ping/src/index.ts | 20 +- packages/http-ping/src/ping.ts | 40 +- packages/http-server/src/node-server.ts | 7 + .../http-server/src/node/websocket-server.ts | 4 +- packages/http-utils/src/index.ts | 59 +- packages/http/src/http.browser.ts | 35 +- packages/http/src/index.ts | 19 +- packages/http/src/registrar.ts | 4 + packages/http/src/routes/peer-id-auth.ts | 22 +- .../interop/test/fixtures/create-express.ts | 16 +- .../test/fixtures/create-fastify-http.ts | 16 +- .../test/fixtures/create-fastify-websocket.ts | 16 +- packages/interop/test/fixtures/create-http.ts | 14 +- 77 files changed, 1751 insertions(+), 1650 deletions(-) create mode 100644 examples/express-server-over-libp2p/README.md create mode 100644 examples/express-server-over-libp2p/package.json create mode 100644 examples/express-server-over-libp2p/src/client.js create mode 100644 examples/express-server-over-libp2p/src/server.js create mode 100644 examples/express-server-over-libp2p/test/index.spec.js delete mode 100644 examples/go-libp2p-http-proxy/client.js delete mode 100644 examples/go-libp2p-http-proxy/proxy/go.mod delete mode 100644 examples/go-libp2p-http-proxy/proxy/go.sum delete mode 100644 examples/go-libp2p-http-proxy/proxy/main.go delete mode 100755 examples/go-libp2p-http-proxy/proxy/proxy delete mode 100644 examples/go-libp2p-http-proxy/server.js create mode 100644 examples/hono-server-over-libp2p/README.md delete mode 100644 examples/hono-server-over-libp2p/client.js create mode 100644 examples/hono-server-over-libp2p/package.json delete mode 100644 examples/hono-server-over-libp2p/server.js create mode 100644 examples/hono-server-over-libp2p/src/client.js create mode 100644 examples/hono-server-over-libp2p/src/server.js create mode 100644 examples/hono-server-over-libp2p/test/index.spec.js delete mode 100644 examples/js-libp2p-client-and-node-server/client.js delete mode 100644 examples/js-libp2p-client-and-node-server/server.js create mode 100644 examples/libp2p-over-http-server/README.md create mode 100644 examples/libp2p-over-http-server/package.json create mode 100644 examples/libp2p-over-http-server/src/client-http.js create mode 100644 examples/libp2p-over-http-server/src/client-libp2p.js create mode 100644 examples/libp2p-over-http-server/src/common.js create mode 100644 examples/libp2p-over-http-server/src/server.js create mode 100644 examples/libp2p-over-http-server/test/index.spec.js delete mode 100644 examples/peer-id-auth/node.js create mode 100644 examples/peer-id-auth/package.json delete mode 100755 examples/peer-id-auth/runTest.sh create mode 100644 examples/peer-id-auth/src/client.js create mode 100644 examples/peer-id-auth/src/server.js create mode 100644 examples/peer-id-auth/test/index.spec.js delete mode 100644 examples/serving-http-resources-over-libp2p-streams/README.md delete mode 100644 examples/serving-http-resources-over-libp2p-streams/client.js delete mode 100644 examples/serving-http-resources-over-libp2p-streams/package.json delete mode 100644 examples/serving-http-resources-over-libp2p-streams/server.js delete mode 100644 examples/serving-http-resources-over-libp2p-streams/test.js create mode 100644 examples/serving-websites-from-web-browsers/README.md create mode 100644 examples/serving-websites-from-web-browsers/index.html create mode 100644 examples/serving-websites-from-web-browsers/index.js create mode 100644 examples/serving-websites-from-web-browsers/package.json create mode 100644 examples/serving-websites-from-web-browsers/src/proxy.js create mode 100644 examples/serving-websites-from-web-browsers/src/relay.js create mode 100644 examples/serving-websites-from-web-browsers/test-results/.last-run.json create mode 100644 examples/serving-websites-from-web-browsers/test/index.spec.js create mode 100644 examples/serving-websites-from-web-browsers/vite.config.js delete mode 100644 examples/test-runner/README.md delete mode 100644 examples/test-runner/main.go delete mode 100644 examples/two-js-peers/client.js delete mode 100644 examples/two-js-peers/server.js create mode 100644 examples/websockets-over-libp2p/README.md create mode 100644 examples/websockets-over-libp2p/package.json create mode 100644 examples/websockets-over-libp2p/src/client.js create mode 100644 examples/websockets-over-libp2p/src/server.js create mode 100644 examples/websockets-over-libp2p/test/index.spec.js diff --git a/examples/README.md b/examples/README.md index a15a9ef..ac351bd 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,8 +1,25 @@ # Examples of using libp2p+http -TODO +## HTTP over libp2p -## two-js-peers -## hono-server-over-libp2p -## go-libp2p-http-proxy -## js-libp2p-client-and-node-server +These examples involve starting a libp2p node and having it provide the +networking layer for a HTTP server. + +With this configuration you can use libp2p for peer routing, NAT traversal and +other features, but define your own web application server in the framework you +are most familiar with. + +- [Express server over libp2p](./express-server-over-libp2p) +- [Hono server over libp2p](./hono-server-over-libp2p) +- [WebSockets over libp2p](./websockets-over-libp2p) + +## libp2p over HTTP + +These examples start a HTTP server and then pass incoming requests to libp2p. + +- [libp2p over http.Server]('./libp2p-over-http-server) + +## Other features + +- [PeerID authentication]('./peer-id-auth) +- [Serving websites from browsers]('./serving-websites-from-browsers) diff --git a/examples/express-server-over-libp2p/README.md b/examples/express-server-over-libp2p/README.md new file mode 100644 index 0000000..27ce2e3 --- /dev/null +++ b/examples/express-server-over-libp2p/README.md @@ -0,0 +1,55 @@ +# Serving an Express app over libp2p + +In this example we will start a libp2p node that listens for incoming streams +that use the `/http/1.1` protocol. + +It will convert the incoming stream to a [http.IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage) +and hand it off to a Node.js [http.Server](https://nodejs.org/api/http.html#class-httpserver), +then write data passed to the corresponding [http.ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse) +back into the stream for the client to read. + +## Step 1 - start the server + +The script at [./src/server.js](./src/server.js) creates a basic [express](https://expressjs.com/) +app that has a simple "Hello world" route mounted on `/`. + +It creates a `http.Server` to pass HTTP requests to the express app, and finally +a libp2p node to make incoming `Stream`s conform to the `net.Socket` API and +pass them to the `http.Server`. + +Run the server with the following command: + +```console +node src/server.js +Server listening on: +/ip4/127.0.0.1/tcp/1234/p2p/12D3KooWPUq3SjKGmVz4fhqMHZpZ185ZErfusp9x4QFgqwVCTxWt +/ip4/192.168.1.226/tcp/1234/p2p/12D3KooWPUq3SjKGmVz4fhqMHZpZ185ZErfusp9x4QFgqwVCTxWt +``` + +## Step 2 - run the client + +The script at [./src/client.js](./src/client.js) starts a libp2p node with the +TCP transport, accepts a command line argument of a multiaddr and makes a HTTP +request to it over a libp2p stream. + +Copy one of the multiaddrs the server is listening on and pass it as a CLI arg: + +```console +node ./src/client.js /ip4/127.0.0.1/tcp/1234/p2p/12D3KooWPUq3SjKGmVz4fhqMHZpZ185ZErfusp9x4QFgqwVCTxWt +GET /ip4/127.0.0.1/tcp/55265/p2p/12D3KooWPUq3SjKGmVz4fhqMHZpZ185ZErfusp9x4QFgqwVCTxWt 200 OK +Hello World! +``` + +## Next steps + +Experiment with the server - can you make it accept requests on other paths? + +What about query parameters or custom headers? + +> [!TIP] +> You can add `http-path` tuples to a multiaddr with: +> ``` +> addr.encapsulate(`/http-path/${encodeURIComponent(foo?bar=baz)}`) +> ``` + +How about making a request with a body such as a `POST` request? diff --git a/examples/express-server-over-libp2p/package.json b/examples/express-server-over-libp2p/package.json new file mode 100644 index 0000000..19914b7 --- /dev/null +++ b/examples/express-server-over-libp2p/package.json @@ -0,0 +1,24 @@ +{ + "name": "@libp2p/http-example-express-server-over-libp2p", + "version": "1.0.0", + "private": true, + "description": "How to serve an express app over libp2p streams", + "license": "Apache-2.0 OR MIT", + "type": "module", + "scripts": { + "test": "test-node-example test/*" + }, + "dependencies": { + "@chainsafe/libp2p-noise": "^16.1.3", + "@chainsafe/libp2p-yamux": "^7.0.1", + "@libp2p/http": "0.0.0", + "@libp2p/http-server": "0.0.0", + "@libp2p/tcp": "^10.1.10", + "@multiformats/multiaddr": "^12.4.0", + "express": "^5.1.0", + "libp2p": "^2.8.5" + }, + "devDependencies": { + "test-ipfs-example": "^1.0.0" + } +} diff --git a/examples/express-server-over-libp2p/src/client.js b/examples/express-server-over-libp2p/src/client.js new file mode 100644 index 0000000..f81c0f4 --- /dev/null +++ b/examples/express-server-over-libp2p/src/client.js @@ -0,0 +1,40 @@ +import { createLibp2p } from 'libp2p' +import { tcp } from '@libp2p/tcp' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { http } from '@libp2p/http' +import { multiaddr } from '@multiformats/multiaddr' + +// Take the first argument as the path of the folder to add +const args = process.argv.slice(2) + +// Example of how to use arguments +if (args.length === 0) { + console.error('No argument provided') + console.error('Usage: node client.js ') + process.exit(1) +} + +// turn the passed arg into a multiaddr +const addr = multiaddr(args[0]) + +const node = await createLibp2p({ + transports: [ + tcp() + ], + connectionEncrypters: [ + noise() + ], + streamMuxers: [ + yamux() + ], + services: { + http: http() + } +}) + +// make a HTTP request over libp2p +const res = await node.services.http.fetch(addr) + +console.info('GET', addr.toString(), res.status, res.statusText) +console.info(await res.text()) diff --git a/examples/express-server-over-libp2p/src/server.js b/examples/express-server-over-libp2p/src/server.js new file mode 100644 index 0000000..ade5298 --- /dev/null +++ b/examples/express-server-over-libp2p/src/server.js @@ -0,0 +1,52 @@ +import { createLibp2p } from 'libp2p' +import { tcp } from '@libp2p/tcp' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import express from 'express' +import { http } from '@libp2p/http' +import { nodeServer } from '@libp2p/http-server' +import { createServer } from 'node:http' + +// this express app is where any business logic necessary to server HTTP +// resources will take place +const app = express() +app.get('/', (req, res) => { + res.send('Hello World!') +}) + +// this Node.js http.Server will receive incoming socket connections and convert +// them to HTTP requests - note that we don't need to call `server.listen` - +// libp2p will provide the networking layer +const server = createServer() +server.on('request', (req, res) => { + app(req, res) +}) + +// create a libp2p node that listens on a TCP address +const node = await createLibp2p({ + addresses: { + listen: [ + '/ip4/0.0.0.0/tcp/0' + ] + }, + transports: [ + tcp() + ], + connectionEncrypters: [ + noise() + ], + streamMuxers: [ + yamux() + ], + services: { + http: http({ + // allow injecting requests into the Node.js http.Server + server: nodeServer(server) + }) + } +}) + +console.info('Server listening on:') +node.getMultiaddrs().forEach(ma => { + console.info(ma.toString()) +}) diff --git a/examples/express-server-over-libp2p/test/index.spec.js b/examples/express-server-over-libp2p/test/index.spec.js new file mode 100644 index 0000000..1280ab6 --- /dev/null +++ b/examples/express-server-over-libp2p/test/index.spec.js @@ -0,0 +1,29 @@ +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { matchOutput } from 'test-ipfs-example/node' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) + +// Step 1 start server +process.stdout.write('node server.js\n') + +const { + process: server, + matches: addresses +} = await matchOutput(/Server listening on:\n(.*)\n/, 'node', [path.resolve(__dirname, '../src/server.js')]) + +const address = addresses.slice(1).map(line => line.trim()).pop() + +process.stdout.write('==================================================================\n') + +// Step 2 start client +process.stdout.write(`node client.js ${address}\n`) + +const { + process: client +} = await matchOutput(/Hello World!/g, 'node', [path.resolve(__dirname, '../src/client.js'), address]) + +process.stdout.write('==================================================================\n') + +client.kill() +server.kill() diff --git a/examples/go-libp2p-http-proxy/client.js b/examples/go-libp2p-http-proxy/client.js deleted file mode 100644 index 8d25612..0000000 --- a/examples/go-libp2p-http-proxy/client.js +++ /dev/null @@ -1,58 +0,0 @@ -/* eslint-disable no-console */ - -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { http } from '@libp2p/http-fetch' -import { tcp } from '@libp2p/tcp' -import { multiaddr } from '@multiformats/multiaddr' -import { createLibp2p } from 'libp2p' - -const node = await createLibp2p({ - // libp2p nodes are started by default, pass false to override this - start: false, - addresses: { - listen: [] - }, - transports: [tcp()], - connectionEncrypters: [noise()], - streamMuxers: [yamux()], - services: { http: http() } -}) - -// start libp2p -await node.start() -console.error('libp2p has started') - -// Read server multiaddr from the command line -const serverAddr = process.argv[2] -if (!serverAddr) { - console.error('Please provide the server multiaddr as an argument') - process.exit(1) -} - -let serverMA = multiaddr(serverAddr) - -// check if this is an http transport multiaddr -const isHTTPTransport = serverMA.protos().find(p => p.name === 'http') -if (!isHTTPTransport && serverMA.getPeerId() === null) { - // Learn the peer id of the server. This lets us reuse the connection for all our HTTP requests. - // Otherwise js-libp2p will open a new connection for each request. - const conn = await node.dial(serverMA) - serverMA = serverMA.encapsulate(`/p2p/${conn.remotePeer.toString()}`) -} - -console.error(`Making request to ${serverMA.toString()}`) -try { - const resp = await node.services.http.fetch(new Request(`multiaddr:${serverMA}`)) - const respBody = await resp.text() - if (resp.status !== 200) { - throw new Error(`Unexpected status code: ${resp.status}`) - } - if (respBody !== 'Hello, World!') { - throw new Error(`Unexpected response body: ${respBody}`) - } - console.error('Got response:', respBody) -} finally { - // stop libp2p - await node.stop() -} diff --git a/examples/go-libp2p-http-proxy/proxy/go.mod b/examples/go-libp2p-http-proxy/proxy/go.mod deleted file mode 100644 index f840d7a..0000000 --- a/examples/go-libp2p-http-proxy/proxy/go.mod +++ /dev/null @@ -1,114 +0,0 @@ -module github.com/libp2p/js-libp2p-http-fetch/examples/proxy - -go 1.22.1 -toolchain go1.24.1 - -require ( - github.com/libp2p/go-libp2p v0.35.0 - github.com/multiformats/go-multiaddr v0.12.4 -) - -require ( - github.com/benbjohnson/clock v1.3.5 // indirect - github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/containerd/cgroups v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect - github.com/docker/go-units v0.5.0 // indirect - github.com/elastic/gosigar v0.14.2 // indirect - github.com/flynn/noise v1.1.0 // indirect - github.com/francoispqt/gojay v1.2.13 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/google/gopacket v1.1.19 // indirect - github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect - github.com/google/uuid v1.4.0 // indirect - github.com/gorilla/websocket v1.5.1 // indirect - github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/huin/goupnp v1.3.0 // indirect - github.com/ipfs/go-cid v0.4.1 // indirect - github.com/ipfs/go-log/v2 v2.5.1 // indirect - github.com/jackpal/go-nat-pmp v1.0.2 // indirect - github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect - github.com/klauspost/compress v1.17.8 // indirect - github.com/klauspost/cpuid/v2 v2.2.7 // indirect - github.com/koron/go-ssdp v0.0.4 // indirect - github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/libp2p/go-flow-metrics v0.1.0 // indirect - github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect - github.com/libp2p/go-msgio v0.3.0 // indirect - github.com/libp2p/go-nat v0.2.0 // indirect - github.com/libp2p/go-netroute v0.2.1 // indirect - github.com/libp2p/go-reuseport v0.4.0 // indirect - github.com/libp2p/go-yamux/v4 v4.0.1 // indirect - github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/miekg/dns v1.1.58 // indirect - github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect - github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect - github.com/minio/sha256-simd v1.0.1 // indirect - github.com/mr-tron/base58 v1.2.0 // indirect - github.com/multiformats/go-base32 v0.1.0 // indirect - github.com/multiformats/go-base36 v0.2.0 // indirect - github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect - github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect - github.com/multiformats/go-multibase v0.2.0 // indirect - github.com/multiformats/go-multicodec v0.9.0 // indirect - github.com/multiformats/go-multihash v0.2.3 // indirect - github.com/multiformats/go-multistream v0.5.0 // indirect - github.com/multiformats/go-varint v0.0.7 // indirect - github.com/onsi/ginkgo/v2 v2.15.0 // indirect - github.com/opencontainers/runtime-spec v1.2.0 // indirect - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pion/datachannel v1.5.6 // indirect - github.com/pion/dtls/v2 v2.2.11 // indirect - github.com/pion/ice/v2 v2.3.24 // indirect - github.com/pion/interceptor v0.1.29 // indirect - github.com/pion/logging v0.2.2 // indirect - github.com/pion/mdns v0.0.12 // indirect - github.com/pion/randutil v0.1.0 // indirect - github.com/pion/rtcp v1.2.14 // indirect - github.com/pion/rtp v1.8.6 // indirect - github.com/pion/sctp v1.8.16 // indirect - github.com/pion/sdp/v3 v3.0.9 // indirect - github.com/pion/srtp/v2 v2.0.18 // indirect - github.com/pion/stun v0.6.1 // indirect - github.com/pion/transport/v2 v2.2.5 // indirect - github.com/pion/turn/v2 v2.1.6 // indirect - github.com/pion/webrtc/v3 v3.2.40 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.48.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/quic-go v0.44.0 // indirect - github.com/quic-go/webtransport-go v0.8.0 // indirect - github.com/raulk/go-watchdog v1.3.0 // indirect - github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/stretchr/testify v1.9.0 // indirect - go.uber.org/dig v1.17.1 // indirect - go.uber.org/fx v1.22.0 // indirect - go.uber.org/mock v0.4.0 // indirect - go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.35.0 // indirect - golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.36.0 // indirect - golang.org/x/sync v0.11.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - google.golang.org/protobuf v1.34.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.2.1 // indirect -) - -// Get this fix in: https://github.com/libp2p/go-libp2p/pull/2821 -replace github.com/libp2p/go-libp2p => github.com/libp2p/go-libp2p v0.35.1-0.20240605000535-f11a9c3c7cbb diff --git a/examples/go-libp2p-http-proxy/proxy/go.sum b/examples/go-libp2p-http-proxy/proxy/go.sum deleted file mode 100644 index 9efb8bd..0000000 --- a/examples/go-libp2p-http-proxy/proxy/go.sum +++ /dev/null @@ -1,553 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo= -dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= -dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= -dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= -dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= -git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= -github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= -github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= -github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= -github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= -github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= -github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4= -github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/flynn/noise v1.1.0 h1:KjPQoQCEFdZDiP03phOvGi11+SVVhBG2wOWAorLsstg= -github.com/flynn/noise v1.1.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= -github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= -github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= -github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo= -github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= -github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= -github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= -github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= -github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= -github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= -github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= -github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= -github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= -github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= -github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= -github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= -github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= -github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= -github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM= -github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro= -github.com/libp2p/go-libp2p v0.35.1-0.20240605000535-f11a9c3c7cbb h1:jpsKowOxM3bJACYYiP3J8S5Ls+3B/V6uGedmjmxkbNU= -github.com/libp2p/go-libp2p v0.35.1-0.20240605000535-f11a9c3c7cbb/go.mod h1:yvTaBR9foLKTyfJlpEtHu5SNtyHnw15i7/mQqTSa4dY= -github.com/libp2p/go-libp2p-asn-util v0.4.1 h1:xqL7++IKD9TBFMgnLPZR6/6iYhawHKHl950SO9L6n94= -github.com/libp2p/go-libp2p-asn-util v0.4.1/go.mod h1:d/NI6XZ9qxw67b4e+NgpQexCIiFYJjErASrYW4PFDN8= -github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= -github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= -github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= -github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= -github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= -github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= -github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= -github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQscQm2s= -github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= -github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ= -github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= -github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= -github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= -github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= -github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc= -github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s= -github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= -github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= -github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= -github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= -github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= -github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= -github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= -github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= -github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.12.4 h1:rrKqpY9h+n80EwhhC/kkcunCZZ7URIF8yN1WEUt2Hvc= -github.com/multiformats/go-multiaddr v0.12.4/go.mod h1:sBXrNzucqkFJhvKOiwwLyqamGa/P5EIXNPLovyhQCII= -github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= -github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= -github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= -github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= -github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= -github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= -github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= -github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= -github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= -github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= -github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= -github.com/multiformats/go-multistream v0.5.0 h1:5htLSLl7lvJk3xx3qT/8Zm9J4K8vEOf/QGkvOGQAyiE= -github.com/multiformats/go-multistream v0.5.0/go.mod h1:n6tMZiwiP2wUsR8DgfDWw1dydlEqV3l6N3/GBsX6ILA= -github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= -github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= -github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= -github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= -github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= -github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= -github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/runtime-spec v1.2.0 h1:z97+pHb3uELt/yiAWD691HNHQIF07bE7dzrbT927iTk= -github.com/opencontainers/runtime-spec v1.2.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= -github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= -github.com/pion/datachannel v1.5.6 h1:1IxKJntfSlYkpUj8LlYRSWpYiTTC02nUrOE8T3DqGeg= -github.com/pion/datachannel v1.5.6/go.mod h1:1eKT6Q85pRnr2mHiWHxJwO50SfZRtWHTsNIVb/NfGW4= -github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= -github.com/pion/dtls/v2 v2.2.11 h1:9U/dpCYl1ySttROPWJgqWKEylUdT0fXp/xst6JwY5Ks= -github.com/pion/dtls/v2 v2.2.11/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= -github.com/pion/ice/v2 v2.3.24 h1:RYgzhH/u5lH0XO+ABatVKCtRd+4U1GEaCXSMjNr13tI= -github.com/pion/ice/v2 v2.3.24/go.mod h1:KXJJcZK7E8WzrBEYnV4UtqEZsGeWfHxsNqhVcVvgjxw= -github.com/pion/interceptor v0.1.29 h1:39fsnlP1U8gw2JzOFWdfCU82vHvhW9o0rZnZF56wF+M= -github.com/pion/interceptor v0.1.29/go.mod h1:ri+LGNjRUc5xUNtDEPzfdkmSqISixVTBF/z/Zms/6T4= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/mdns v0.0.12 h1:CiMYlY+O0azojWDmxdNr7ADGrnZ+V6Ilfner+6mSVK8= -github.com/pion/mdns v0.0.12/go.mod h1:VExJjv8to/6Wqm1FXK+Ii/Z9tsVk/F5sD/N70cnYFbk= -github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= -github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= -github.com/pion/rtcp v1.2.12/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= -github.com/pion/rtcp v1.2.14 h1:KCkGV3vJ+4DAJmvP0vaQShsb0xkRfWkO540Gy102KyE= -github.com/pion/rtcp v1.2.14/go.mod h1:sn6qjxvnwyAkkPzPULIbVqSKI5Dv54Rv7VG0kNxh9L4= -github.com/pion/rtp v1.8.3/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= -github.com/pion/rtp v1.8.6 h1:MTmn/b0aWWsAzux2AmP8WGllusBVw4NPYPVFFd7jUPw= -github.com/pion/rtp v1.8.6/go.mod h1:pBGHaFt/yW7bf1jjWAoUjpSNoDnw98KTMg+jWWvziqU= -github.com/pion/sctp v1.8.13/go.mod h1:YKSgO/bO/6aOMP9LCie1DuD7m+GamiK2yIiPM6vH+GA= -github.com/pion/sctp v1.8.16 h1:PKrMs+o9EMLRvFfXq59WFsC+V8mN1wnKzqrv+3D/gYY= -github.com/pion/sctp v1.8.16/go.mod h1:P6PbDVA++OJMrVNg2AL3XtYHV4uD6dvfyOovCgMs0PE= -github.com/pion/sdp/v3 v3.0.9 h1:pX++dCHoHUwq43kuwf3PyJfHlwIj4hXA7Vrifiq0IJY= -github.com/pion/sdp/v3 v3.0.9/go.mod h1:B5xmvENq5IXJimIO4zfp6LAe1fD9N+kFv+V/1lOdz8M= -github.com/pion/srtp/v2 v2.0.18 h1:vKpAXfawO9RtTRKZJbG4y0v1b11NZxQnxRl85kGuUlo= -github.com/pion/srtp/v2 v2.0.18/go.mod h1:0KJQjA99A6/a0DOVTu1PhDSw0CXF2jTkqOoMg3ODqdA= -github.com/pion/stun v0.6.1 h1:8lp6YejULeHBF8NmV8e2787BogQhduZugh5PdhDyyN4= -github.com/pion/stun v0.6.1/go.mod h1:/hO7APkX4hZKu/D0f2lHzNyvdkTGtIy3NDmLR7kSz/8= -github.com/pion/transport/v2 v2.2.1/go.mod h1:cXXWavvCnFF6McHTft3DWS9iic2Mftcz1Aq29pGcU5g= -github.com/pion/transport/v2 v2.2.2/go.mod h1:OJg3ojoBJopjEeECq2yJdXH9YVrUJ1uQ++NjXLOUorc= -github.com/pion/transport/v2 v2.2.3/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= -github.com/pion/transport/v2 v2.2.4/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= -github.com/pion/transport/v2 v2.2.5 h1:iyi25i/21gQck4hfRhomF6SktmUQjRsRW4WJdhfc3Kc= -github.com/pion/transport/v2 v2.2.5/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= -github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= -github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= -github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= -github.com/pion/turn/v2 v2.1.3/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= -github.com/pion/turn/v2 v2.1.6 h1:Xr2niVsiPTB0FPtt+yAWKFUkU1eotQbGgpTIld4x1Gc= -github.com/pion/turn/v2 v2.1.6/go.mod h1:huEpByKKHix2/b9kmTAM3YoX6MKP+/D//0ClgUYR2fY= -github.com/pion/webrtc/v3 v3.2.40 h1:Wtfi6AZMQg+624cvCXUuSmrKWepSB7zfgYDOYqsSOVU= -github.com/pion/webrtc/v3 v3.2.40/go.mod h1:M1RAe3TNTD1tzyvqHrbVODfwdPGSXOUo/OgpoGGJqFY= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= -github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= -github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0= -github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek= -github.com/quic-go/webtransport-go v0.8.0 h1:HxSrwun11U+LlmwpgM1kEqIqH90IT4N8auv/cD7QFJg= -github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YVSlwHohQsuac9WaM= -github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= -github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= -github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= -github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= -github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= -github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= -github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= -github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= -github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= -github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= -github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= -github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= -github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= -github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= -github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= -github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= -github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= -github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= -github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= -github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= -github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= -github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= -github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= -github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= -github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/dig v1.17.1 h1:Tga8Lz8PcYNsWsyHMZ1Vm0OQOUaJNDyvPImgbAu9YSc= -go.uber.org/dig v1.17.1/go.mod h1:Us0rSJiThwCv2GteUN0Q7OKvU7n5J4dxZ9JKUXozFdE= -go.uber.org/fx v1.22.0 h1:pApUK7yL0OUHMd8vkunWSlLxZVFFk70jR2nKde8X2NM= -go.uber.org/fx v1.22.0/go.mod h1:HT2M7d7RHo+ebKGh9NRcrsrHHfpZ60nW3QRubMRfv48= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= -golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= -golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs= -golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= -golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= -golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA= -golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= -golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= -google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= -lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= -sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= -sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/examples/go-libp2p-http-proxy/proxy/main.go b/examples/go-libp2p-http-proxy/proxy/main.go deleted file mode 100644 index b88b88a..0000000 --- a/examples/go-libp2p-http-proxy/proxy/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "log" - "net/http/httputil" - "net/url" - "os" - "os/signal" - - "github.com/libp2p/go-libp2p" - libp2phttp "github.com/libp2p/go-libp2p/p2p/http" - "github.com/multiformats/go-multiaddr" -) - -func main() { - proxyTarget := flag.String("proxy-target", "", "target http server to proxy to") - flag.Parse() - if *proxyTarget == "" { - log.Fatal("proxy-target must be set") - } - - h, err := libp2p.New(libp2p.ListenAddrStrings( - "/ip4/127.0.0.1/tcp/0", - )) - if err != nil { - log.Fatal(err) - } - defer h.Close() - - log.Println("Listening on:") - for _, a := range h.Addrs() { - fmt.Println(a.Encapsulate(multiaddr.StringCast("/p2p/" + h.ID().String()))) - } - - targetUrl, err := url.Parse(*proxyTarget) - if err != nil { - log.Fatal(err) - } - - // reverse proxy - proxy := httputil.NewSingleHostReverseProxy(targetUrl) - - httpHost := libp2phttp.Host{StreamHost: h} - - httpHost.SetHTTPHandlerAtPath("/http-proxy/0.0.1", "/", proxy) - go httpHost.Serve() - - // Wait for interrupt signal to stop - intSig := make(chan os.Signal, 1) - signal.Notify(intSig, os.Interrupt) - <-intSig - log.Println("Interrupt signal received, closing host") -} diff --git a/examples/go-libp2p-http-proxy/proxy/proxy b/examples/go-libp2p-http-proxy/proxy/proxy deleted file mode 100755 index ecb46277ed5f24769bd8f4d7d1ca5fd6040c64ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29409618 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

-gEdLYPTUY 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 z

yM-*v#ev~>B!1Y=FxIaWbcJx&7 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 z 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

    <&jy= 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%0A-yrp~Q8u;ovQt@b%-{-SX}k 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�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 EHGr@)W%FZysG{cycE_L0c%aN#R4 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

    sBr>ADK`nlxv!H6%X|jInJJv*&~? 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

    -MuOqo2=Y(I@u&;OYI< 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

    %`E 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�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�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�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⁡kU-GJOTM>jPGKmWQmP0;m3=w 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