├── .changeset ├── README.md └── config.json ├── .github ├── actions │ └── cache-node-modules │ │ └── action.yml └── workflows │ ├── ci.yml │ ├── package-size.yml │ ├── pre-release.yml │ └── release.yml ├── .gitignore ├── .mise.toml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── biome.json ├── package.json ├── pnpm-lock.yaml ├── src ├── broadcast-message.do.e2e.test.ts ├── broadcast-message.do │ ├── app │ │ ├── app.e2e.test.ts │ │ └── index.ts │ ├── index.ts │ ├── internal.ts │ └── types.ts ├── client │ ├── index.ts │ └── ping-websocket │ │ ├── index.ts │ │ └── ping-websocket.unit.test.ts ├── index.ts └── middleware │ └── upgrade │ ├── index.ts │ └── upgrade.unit.test.ts ├── tsconfig.json ├── tsup.config.ts ├── types └── index.d.ts ├── vitest.workspace.ts └── wrangler.toml /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": true, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /.github/actions/cache-node-modules/action.yml: -------------------------------------------------------------------------------- 1 | name: "Cache Node Modules" 2 | description: "Caches node_modules using actions/cache" 3 | inputs: 4 | path: 5 | description: "Path to the node_modules to cache" 6 | required: true 7 | runs: 8 | using: "composite" 9 | steps: 10 | - name: Cache node_modules 11 | uses: actions/cache@v4 12 | with: 13 | path: ${{ inputs.path }} 14 | key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json', '**/yarn.lock', '**/pnpm-lock.yaml', '**/bun.lockb') }} 15 | restore-keys: | 16 | ${{ runner.os }}-node_modules- 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | pull_request: 4 | branches: 5 | - "**" 6 | workflow_dispatch: 7 | inputs: 8 | branch: 9 | description: "Branch to run the CI on" 10 | required: true 11 | default: "main" 12 | 13 | env: 14 | PNPM_VERSION: 9.12.1 15 | 16 | jobs: 17 | setup: 18 | runs-on: ubuntu-latest 19 | concurrency: 20 | group: ${{ github.workflow }}-${{ github.head_ref || github.event.inputs.branch }} 21 | cancel-in-progress: true 22 | steps: 23 | - uses: actions/checkout@v4 24 | with: 25 | ref: ${{ github.head_ref || github.event.inputs.branch }} 26 | 27 | - uses: actions/setup-node@v4 28 | with: 29 | node-version-file: package.json 30 | 31 | - uses: pnpm/action-setup@v4 32 | with: 33 | version: ${{ env.PNPM_VERSION }} 34 | 35 | - name: Cache node_modules 36 | uses: ./.github/actions/cache-node-modules 37 | with: 38 | path: "**/node_modules" 39 | 40 | - name: Install dependencies 41 | run: pnpm install 42 | 43 | test: 44 | runs-on: ubuntu-latest 45 | needs: setup 46 | steps: 47 | - uses: actions/checkout@v4 48 | with: 49 | ref: ${{ github.head_ref || github.event.inputs.branch }} 50 | 51 | - uses: actions/setup-node@v4 52 | with: 53 | node-version-file: package.json 54 | 55 | - uses: pnpm/action-setup@v4 56 | with: 57 | version: ${{ env.PNPM_VERSION }} 58 | 59 | - name: Cache node_modules 60 | uses: ./.github/actions/cache-node-modules 61 | with: 62 | path: "**/node_modules" 63 | 64 | - name: Install dependencies 65 | run: pnpm install 66 | 67 | - name: Run tests 68 | run: pnpm run test 69 | 70 | lint: 71 | runs-on: ubuntu-latest 72 | needs: setup 73 | steps: 74 | - uses: actions/checkout@v4 75 | with: 76 | ref: ${{ github.head_ref || github.event.inputs.branch }} 77 | 78 | - uses: actions/setup-node@v4 79 | with: 80 | node-version-file: package.json 81 | 82 | - uses: pnpm/action-setup@v4 83 | with: 84 | version: ${{ env.PNPM_VERSION }} 85 | 86 | - name: Cache node_modules 87 | uses: ./.github/actions/cache-node-modules 88 | with: 89 | path: "**/node_modules" 90 | 91 | - name: Install dependencies 92 | run: pnpm install 93 | 94 | - name: Run linter 95 | run: pnpm run lint 96 | 97 | typecheck: 98 | runs-on: ubuntu-latest 99 | needs: setup 100 | steps: 101 | - uses: actions/checkout@v4 102 | with: 103 | ref: ${{ github.head_ref || github.event.inputs.branch }} 104 | 105 | - uses: actions/setup-node@v4 106 | with: 107 | node-version-file: package.json 108 | 109 | - uses: pnpm/action-setup@v4 110 | with: 111 | version: ${{ env.PNPM_VERSION }} 112 | 113 | - name: Cache node_modules 114 | uses: ./.github/actions/cache-node-modules 115 | with: 116 | path: "**/node_modules" 117 | 118 | - name: Install dependencies 119 | run: pnpm install 120 | 121 | - name: Run typecheck 122 | run: pnpm run typecheck 123 | 124 | build: 125 | runs-on: ubuntu-latest 126 | needs: [setup, test, lint, typecheck] 127 | steps: 128 | - uses: actions/checkout@v4 129 | with: 130 | ref: ${{ github.head_ref || github.event.inputs.branch }} 131 | 132 | - uses: actions/setup-node@v4 133 | with: 134 | node-version-file: package.json 135 | 136 | - uses: pnpm/action-setup@v4 137 | with: 138 | version: ${{ env.PNPM_VERSION }} 139 | 140 | - name: Cache node_modules 141 | uses: ./.github/actions/cache-node-modules 142 | with: 143 | path: "**/node_modules" 144 | 145 | - name: Install dependencies 146 | run: pnpm install 147 | 148 | - name: Build 149 | run: | 150 | pnpm run build 151 | pnpx publint 152 | -------------------------------------------------------------------------------- /.github/workflows/package-size.yml: -------------------------------------------------------------------------------- 1 | name: Package Size Report 2 | 3 | on: 4 | pull_request: 5 | 6 | concurrency: 7 | group: ${{ github.workflow }}-${{ github.ref }} 8 | cancel-in-progress: true 9 | 10 | env: 11 | PNPM_VERSION: 9.12.1 12 | 13 | jobs: 14 | pkg-size-report: 15 | name: Package Size Report 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version-file: package.json 25 | 26 | - uses: pnpm/action-setup@v4 27 | with: 28 | version: ${{ env.PNPM_VERSION }} 29 | 30 | - name: Set up Bun 31 | uses: oven-sh/setup-bun@v2 32 | 33 | - name: Cache node_modules 34 | uses: ./.github/actions/cache-node-modules 35 | with: 36 | path: "**/node_modules" 37 | 38 | - name: Package size report 39 | uses: preactjs/compressed-size-action@v2 40 | with: 41 | install-script: "pnpm install" 42 | build-script: "build" 43 | pattern: "./dist/**/*.{js}" 44 | exclude: "{**/*.map,**/node_modules/**}" 45 | -------------------------------------------------------------------------------- /.github/workflows/pre-release.yml: -------------------------------------------------------------------------------- 1 | name: PR PreRelease 2 | on: 3 | pull_request: 4 | 5 | concurrency: 6 | group: ${{ github.workflow }}-${{ github.ref }} 7 | cancel-in-progress: true 8 | 9 | env: 10 | PNPM_VERSION: 9.12.1 11 | 12 | jobs: 13 | pre-release: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v4 19 | 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version-file: package.json 23 | 24 | - uses: pnpm/action-setup@v4 25 | with: 26 | version: ${{ env.PNPM_VERSION }} 27 | 28 | - name: Cache node_modules 29 | uses: ./.github/actions/cache-node-modules 30 | with: 31 | path: "**/node_modules" 32 | 33 | - name: Install dependencies 34 | run: pnpm install 35 | 36 | - name: Build 37 | run: pnpm run build 38 | 39 | - run: pnpx pkg-pr-new publish 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }} 11 | cancel-in-progress: true 12 | 13 | env: 14 | PNPM_VERSION: 9.12.1 15 | 16 | jobs: 17 | release: 18 | name: Release 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Checkout Repo 22 | uses: actions/checkout@v4 23 | 24 | - uses: actions/setup-node@v4 25 | with: 26 | node-version-file: package.json 27 | 28 | - uses: pnpm/action-setup@v4 29 | with: 30 | version: ${{ env.PNPM_VERSION }} 31 | 32 | - name: Cache node_modules 33 | uses: ./.github/actions/cache-node-modules 34 | with: 35 | path: "**/node_modules" 36 | 37 | - name: Install dependencies 38 | run: pnpm install 39 | 40 | - name: Build 41 | run: | 42 | pnpm run build 43 | pnpx publint 44 | 45 | - name: Create Release Pull Request 46 | id: changesets 47 | uses: changesets/action@v1 48 | with: 49 | publish: pnpm run release 50 | env: 51 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 52 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # prod 2 | dist/ 3 | 4 | # dev 5 | .yarn/ 6 | !.yarn/releases 7 | .vscode/* 8 | !.vscode/launch.json 9 | !.vscode/*.code-snippets 10 | .idea/workspace.xml 11 | .idea/usage.statistics.xml 12 | .idea/shelf 13 | 14 | # deps 15 | node_modules/ 16 | .wrangler 17 | 18 | # env 19 | .env 20 | .env.production 21 | .dev.vars 22 | 23 | # logs 24 | logs/ 25 | *.log 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | pnpm-debug.log* 30 | lerna-debug.log* 31 | 32 | # misc 33 | .DS_Store 34 | -------------------------------------------------------------------------------- /.mise.toml: -------------------------------------------------------------------------------- 1 | [tools] 2 | pnpm = "9.12.1" 3 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # durabcast 2 | 3 | ## 0.2.2 4 | 5 | ### Patch Changes 6 | 7 | - 6344d5f: upgrade pacakges 8 | 9 | ## 0.2.1 10 | 11 | ### Patch Changes 12 | 13 | - a6ef72c: sideeffect false 14 | 15 | ## 0.2.0 16 | 17 | ### Minor Changes 18 | 19 | - e5bc04f: add client helper function(pingWebSocket) to send ping message to server 20 | 21 | ## 0.1.2 22 | 23 | ### Patch Changes 24 | 25 | - 746d866: refactor testing 26 | 27 | ## 0.1.1 28 | 29 | ### Patch Changes 30 | 31 | - 8260a24: add typesVersion 32 | - 8260a24: fix package.json field 33 | 34 | ## 0.1.0 35 | 36 | ### Minor Changes 37 | 38 | - 420d9c3: durabcast first release 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 GitHub, Inc. and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DurabCast 2 | 3 | `DurabCast` is a library for easily handling WebSockets with Cloudflare Durable Objects. It simplifies the setup and management of WebSocket connections by implementing complex configurations out of the box. 4 | 5 | ## Features 6 | 7 | - **Connection Monitoring and Auto-Close** 8 | 9 | - Monitor and close idle connections automatically. 10 | - `interval` and `timeout` can be configured through options. 11 | - Opt-out of auto-closing by setting `autoClose` to `false`. 12 | 13 | - **Client-Side Keep-Alive with `pingWebSocket`** 14 | 15 | - Use the `pingWebSocket` function on the client side to send periodic ping messages. 16 | - Ensures the connection remains active when `autoClose` is enabled on the server. 17 | 18 | - **Message Broadcasting** 19 | 20 | - Broadcast messages to other connected clients. 21 | - Override `webSocketMessage` to customize message handling. 22 | 23 | - **Connection Alive Check** 24 | 25 | - Use `isAliveSocket` to check if a connection is still alive. 26 | 27 | ## Installation 28 | 29 | ```sh 30 | npm install -D @cloudflare/workers-types 31 | npm install durabcast 32 | ``` 33 | 34 | ## Basic Usage 35 | 36 | Here is a simple example to get started with `DurabCast`. 37 | 38 | ### `wrangler.toml` 39 | 40 | ```toml 41 | name = "sample" 42 | main = "src/index.ts" 43 | compatibility_date = "2024-07-18" 44 | 45 | [[durable_objects.bindings]] 46 | class_name = "BroadcastMessage" 47 | name = "BROADCAST_MESSAGE" 48 | 49 | [[migrations]] 50 | tag = "v1" 51 | new_classes = ["BroadcastMessage"] 52 | ``` 53 | 54 | ### `index.ts` 55 | 56 | ```ts 57 | import { BroadcastMessage, type BroadcastMessageAppType } from "durabcast"; 58 | import { zValidator } from "@hono/zod-validator"; 59 | import { Hono } from "hono"; 60 | import { hc } from "hono/client"; 61 | import { z } from "zod"; 62 | import { upgrade } from "durabcast/helpers/upgrade"; 63 | 64 | type Env = { 65 | Bindings: { 66 | BROADCAST_MESSAGE: DurableObjectNamespace; 67 | }; 68 | }; 69 | 70 | const app = new Hono(); 71 | 72 | const route = app 73 | .get( 74 | "/rooms/:roomId", 75 | upgrade(), 76 | zValidator("query", z.object({ uid: z.string() })), 77 | async (c) => { 78 | const roomId = c.req.param("roomId"); 79 | const uid = c.req.valid("query").uid; 80 | const id = c.env.BROADCAST_MESSAGE.idFromName(roomId); 81 | const stub = c.env.BROADCAST_MESSAGE.get(id); 82 | 83 | const baseURL = new URL("/", c.req.url); 84 | const client = hc(baseURL.toString(), { 85 | fetch: stub.fetch.bind(stub), 86 | }); 87 | 88 | const res = await client.rooms[":roomId"].$get( 89 | { query: { uid }, param: { roomId } }, 90 | { init: { headers: c.req.raw.headers } }, 91 | ); 92 | 93 | return new Response(null, { 94 | webSocket: res.webSocket, 95 | status: res.status, 96 | headers: res.headers, 97 | statusText: res.statusText, 98 | }); 99 | }, 100 | ) 101 | .post( 102 | "/rooms/:roomId/broadcast", 103 | zValidator("json", z.object({ message: z.string() })), 104 | async (c) => { 105 | const roomId = c.req.param("roomId"); 106 | const id = c.env.BROADCAST_MESSAGE.idFromName(roomId); 107 | const stub = c.env.BROADCAST_MESSAGE.get(id); 108 | 109 | await stub.broadcast(c.req.valid("json").message); 110 | return c.json(null, 200); 111 | }, 112 | ); 113 | 114 | export { BroadcastMessage }; 115 | ``` 116 | 117 | ## Client-Side Keep-Alive with `pingWebSocket` 118 | 119 | When the `autoClose` feature is enabled on the server side, the server automatically closes idle connections after a specified timeout. To ensure that the client connection remains active, you can use the `pingWebSocket` function on the client side to send periodic ping messages. 120 | 121 | ### `pingWebSocket` Function 122 | 123 | The `pingWebSocket` function sends a ping message to the server at regular intervals. This keeps the connection alive by resetting the idle timeout on the server side. 124 | 125 | #### Usage 126 | 127 | ```typescript 128 | import { pingWebSocket } from "durabcast/helpers/client"; 129 | 130 | const ws = new WebSocket("wss://your-server.com/rooms/room123"); 131 | 132 | // Start sending ping messages every 30 seconds 133 | const unsubscribe = pingWebSocket(ws, { interval: 30000, ping: "ping" }); 134 | 135 | // To stop sending pings, call the unsubscribe function 136 | // unsubscribe(); 137 | ``` 138 | 139 | #### Parameters 140 | 141 | - **`ws`**: The WebSocket instance to send ping messages through. 142 | - **`options`** (optional): An object to configure the ping behavior. 143 | - **`interval`**: The interval (in milliseconds) at which to send ping messages. Defaults to `10000` (10 seconds). 144 | - **`ping`**: The ping message to send. Defaults to `'ping'`. 145 | 146 | ### Benefits 147 | 148 | - **Keeps Connection Alive**: Ensures that the server recognizes the connection as active. 149 | - **Prevents Unintentional Disconnections**: Avoids the connection being closed by the server's auto-close mechanism due to inactivity. 150 | - **Configurable**: Allows customization of the ping interval and message. 151 | 152 | ### Example 153 | 154 | ```typescript 155 | import { pingWebSocket } from "durabcast/helpers/client"; 156 | 157 | const ws = new WebSocket("wss://your-server.com/rooms/room123"); 158 | 159 | ws.onopen = () => { 160 | // Start sending pings every 30 seconds 161 | const unsubscribe = pingWebSocket(ws, { 162 | interval: 30000, 163 | ping: "keep-alive", 164 | }); 165 | 166 | // Handle incoming messages 167 | ws.onmessage = (event) => { 168 | console.log("Received:", event.data); 169 | }; 170 | 171 | // Optionally, stop sending pings when needed 172 | // unsubscribe(); 173 | }; 174 | ``` 175 | 176 | ## Advanced Usage 177 | 178 | ### Extending the `BroadcastMessage` Class 179 | 180 | You can extend the `BroadcastMessage` class to customize the behavior of your WebSocket connections. 181 | 182 | ```ts 183 | import { BroadcastMessage, type BroadcastMessageOptions } from "durabcast"; 184 | 185 | class CustomBroadcastMessage extends BroadcastMessage { 186 | protected options: BroadcastMessageOptions = { 187 | interval: 30000, // Check every 30 seconds 188 | timeout: 60000, // Close connection if idle for 60 seconds 189 | autoClose: true, // Enable auto-close 190 | requestResponsePair: { 191 | request: "ping", 192 | response: "pong", 193 | }, 194 | }; 195 | 196 | webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { 197 | // Broadcast message to other clients 198 | this.broadcast(message, { 199 | excludes: [ws], 200 | }); 201 | } 202 | } 203 | 204 | // Use CustomBroadcastMessage in your Durable Object binding 205 | ``` 206 | 207 | ### Combining with `pingWebSocket` 208 | 209 | When `autoClose` is enabled, it's important to ensure that the client sends periodic messages to keep the connection alive. By using `pingWebSocket` on the client side, you can automatically send these keep-alive messages. 210 | 211 | #### Server-Side Configuration 212 | 213 | ```ts 214 | class CustomBroadcastMessage extends BroadcastMessage { 215 | protected options: BroadcastMessageOptions = { 216 | autoClose: true, // Enable auto-close 217 | interval: 30000, // Check every 30 seconds 218 | timeout: 60000, // Close if idle for 60 seconds 219 | requestResponsePair: { 220 | request: "ping", 221 | response: "pong", 222 | }, 223 | }; 224 | 225 | webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { 226 | // Handle ping-pong messages internally 227 | if (message === this.REQUEST_RESPONSE_PAIR.request) { 228 | ws.send(this.REQUEST_RESPONSE_PAIR.response); 229 | return; 230 | } 231 | 232 | // Broadcast other messages 233 | this.broadcast(message, { excludes: [ws] }); 234 | } 235 | } 236 | ``` 237 | 238 | #### Client-Side Usage 239 | 240 | ```typescript 241 | import { pingWebSocket } from "durabcast/helpers/client"; 242 | 243 | const ws = new WebSocket("wss://your-server.com/rooms/room123"); 244 | 245 | ws.onopen = () => { 246 | // Start sending pings to keep the connection alive 247 | const unsubscribe = pingWebSocket(ws, { 248 | interval: 30000, // Every 30 seconds 249 | ping: "ping", // Must match server's expected request 250 | }); 251 | 252 | ws.onmessage = (event) => { 253 | // Handle incoming messages 254 | console.log("Received:", event.data); 255 | }; 256 | }; 257 | ``` 258 | 259 | ### Why Use `pingWebSocket` with `autoClose` 260 | 261 | - **Seamless Integration**: `pingWebSocket` is designed to work with the server's `autoClose` feature, ensuring connections remain active as needed. 262 | - **Resource Optimization**: By automatically closing idle connections, the server conserves resources, and `pingWebSocket` ensures that active clients are not disconnected. 263 | - **Consistency**: Using standardized ping messages simplifies the client-server communication protocol. 264 | 265 | ## API 266 | 267 | ### Connection Monitoring and Auto-Close 268 | 269 | The library monitors connections and can automatically close idle ones based on the configured `interval` and `timeout`. This behavior can be turned off by setting `autoClose` to `false` in the options. 270 | 271 | #### Example 272 | 273 | ```ts 274 | import { BroadcastMessage, type BroadcastMessageOptions } from "durabcast"; 275 | 276 | class CustomBroadcastMessage extends BroadcastMessage { 277 | protected options: BroadcastMessageOptions = { 278 | interval: 30000, // Check every 30 seconds 279 | timeout: 60000, // Close connection if idle for 60 seconds 280 | autoClose: true, // Enable auto-close 281 | requestResponsePair: { 282 | request: "ping", 283 | response: "pong", 284 | }, 285 | }; 286 | 287 | webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { 288 | // Handle ping-pong messages internally 289 | if (message === this.REQUEST_RESPONSE_PAIR.request) { 290 | ws.send(this.REQUEST_RESPONSE_PAIR.response); 291 | return; 292 | } 293 | 294 | // Broadcast other messages 295 | this.broadcast(message, { 296 | excludes: [ws], 297 | }); 298 | } 299 | } 300 | 301 | // In your Durable Object binding, use CustomBroadcastMessage 302 | export { CustomBroadcastMessage as BroadcastMessage }; 303 | ``` 304 | 305 | ### Message Broadcasting 306 | 307 | Messages can be broadcasted to other connected clients. You can override the `webSocketMessage` method to customize how messages are handled. 308 | 309 | ```ts 310 | class CustomBroadcastMessage extends BroadcastMessage { 311 | webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { 312 | // Custom message handling logic 313 | this.broadcast(message, { 314 | excludes: [ws], 315 | }); 316 | } 317 | } 318 | ``` 319 | 320 | ### Connection Alive Check 321 | 322 | The `isAliveSocket` method checks if a connection is still alive. 323 | 324 | ```ts 325 | const isAlive = this.isAliveSocket(ws); 326 | if (!isAlive) { 327 | ws.close(); 328 | } 329 | ``` 330 | 331 | ## Extending the `BroadcastMessage` Class 332 | 333 | When extending the `BroadcastMessage` class, you can access and modify the `options` field to customize the behavior of your WebSocket connections. 334 | 335 | ### `options` 336 | 337 | The `options` field allows you to configure the behavior of your WebSocket connections. It is a protected field, meaning it can be accessed and modified within any class that extends `BroadcastMessage`. 338 | 339 | #### Fields 340 | 341 | - **`interval`**: The interval (in milliseconds) at which to check for idle connections. 342 | - **`timeout`**: The timeout (in milliseconds) after which idle connections are closed. 343 | - **`autoClose`**: A boolean indicating whether to automatically close idle connections. Set to `false` to opt out of this behavior. 344 | - **`requestResponsePair`**: An object containing `request` and `response` strings used for ping-pong style connection checks. 345 | 346 | ### Protected Methods and Fields 347 | 348 | These protected methods and fields are available within any class that extends `BroadcastMessage`: 349 | 350 | - **`AUTO_CLOSE`**: Returns the value of `options.autoClose`, defaulting to `true` if not set. 351 | - **`INTERVAL`**: Returns the value of `options.interval`, defaulting to `30000` (30 seconds) if not set. 352 | - **`TIMEOUT`**: Returns the value of `options.timeout`, defaulting to `60000` (60 seconds) if not set. 353 | - **`REQUEST_RESPONSE_PAIR`**: Returns a `WebSocketRequestResponsePair` object using the `options.requestResponsePair` values, defaulting to `'ping'` and `'pong'` if not set. 354 | - **`sessions`**: A set of active WebSocket sessions. 355 | 356 | ### Example 357 | 358 | ```ts 359 | class CustomBroadcastMessage extends BroadcastMessage { 360 | protected options: BroadcastMessageOptions = { 361 | interval: 30000, // Check every 30 seconds 362 | timeout: 60000, // Close connection if idle for 60 seconds 363 | autoClose: true, // Enable auto-close 364 | requestResponsePair: { 365 | request: "ping", 366 | response: "pong", 367 | }, 368 | }; 369 | 370 | protected get AUTO_CLOSE() { 371 | return this.options.autoClose ?? true; 372 | } 373 | 374 | protected get INTERVAL() { 375 | return this.options.interval ?? 30000; 376 | } 377 | 378 | protected get TIMEOUT() { 379 | return this.options.timeout ?? 60000; 380 | } 381 | 382 | protected get REQUEST_RESPONSE_PAIR() { 383 | return new WebSocketRequestResponsePair( 384 | this.options.requestResponsePair?.request ?? "ping", 385 | this.options.requestResponsePair?.response ?? "pong", 386 | ); 387 | } 388 | 389 | protected sessions = new Set(); 390 | 391 | webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { 392 | // Handle ping-pong messages 393 | if (message === this.REQUEST_RESPONSE_PAIR.request) { 394 | ws.send(this.REQUEST_RESPONSE_PAIR.response); 395 | return; 396 | } 397 | 398 | // Custom message handling logic 399 | this.broadcast(message, { 400 | excludes: [ws], 401 | }); 402 | } 403 | } 404 | ``` 405 | 406 | ## License 407 | 408 | MIT License. See [LICENSE](./LICENSE) for more information. 409 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", 3 | "organizeImports": { 4 | "enabled": true, 5 | "ignore": [".wrangler", "dist"] 6 | }, 7 | "linter": { 8 | "enabled": true, 9 | "rules": { 10 | "recommended": true 11 | }, 12 | "ignore": [".wrangler", "dist"] 13 | }, 14 | "formatter": { 15 | "indentStyle": "space", 16 | "indentWidth": 2, 17 | "lineWidth": 120, 18 | "ignore": [".wrangler", "dist"] 19 | }, 20 | "javascript": { 21 | "formatter": { 22 | "trailingCommas": "all", 23 | "semicolons": "always", 24 | "quoteStyle": "single" 25 | } 26 | }, 27 | "overrides": [ 28 | { 29 | "include": ["src/**/*.test.*"], 30 | "linter": { 31 | "rules": { 32 | "style": { 33 | "noNonNullAssertion": "off" 34 | } 35 | } 36 | } 37 | } 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "durabcast", 3 | "version": "0.2.2", 4 | "type": "module", 5 | "main": "dist/index.cjs", 6 | "module": "dist/index.js", 7 | "types": "dist/index.d.cts", 8 | "sideEffects": false, 9 | "exports": { 10 | ".": { 11 | "import": { 12 | "types": "./dist/index.d.ts", 13 | "default": "./dist/index.js" 14 | }, 15 | "require": { 16 | "types": "./dist/index.d.cts", 17 | "default": "./dist/index.cjs" 18 | } 19 | }, 20 | "./helpers/upgrade": { 21 | "import": { 22 | "types": "./dist/helpers/upgrade.d.ts", 23 | "default": "./dist/helpers/upgrade.js" 24 | }, 25 | "require": { 26 | "types": "./dist/helpers/upgrade.d.cts", 27 | "default": "./dist/helpers/upgrade.cjs" 28 | } 29 | }, 30 | "./helpers/client": { 31 | "import": { 32 | "types": "./dist/helpers/client.d.ts", 33 | "default": "./dist/helpers/client.js" 34 | }, 35 | "require": { 36 | "types": "./dist/helpers/client.d.cts", 37 | "default": "./dist/helpers/client.cjs" 38 | } 39 | } 40 | }, 41 | "files": [ 42 | "dist", 43 | "README.md", 44 | "package.json" 45 | ], 46 | "private": false, 47 | "license": "MIT", 48 | "publishConfig": { 49 | "access": "public" 50 | }, 51 | "repository": { 52 | "type": "git", 53 | "url": "git+https://github.com/napolab/durabcast.git" 54 | }, 55 | "bugs": { 56 | "url": "https://github.com/napolab/durabcast/issues" 57 | }, 58 | "devDependencies": { 59 | "@biomejs/biome": "^1.8.3", 60 | "@changesets/cli": "^2.27.7", 61 | "@cloudflare/vitest-pool-workers": "^0.5.18", 62 | "@cloudflare/workers-types": "^4.20240529.0", 63 | "hono": "^4.6.8", 64 | "tsup": "^8.2.3", 65 | "typescript": "^5.5.4", 66 | "vitest": "2.1.3", 67 | "wrangler": "^3.67.1" 68 | }, 69 | "scripts": { 70 | "dev": "wrangler dev", 71 | "deploy": "wrangler deploy", 72 | "lint": "biome check", 73 | "fmt": "biome check --write", 74 | "typecheck": "tsc --noEmit", 75 | "build": "tsup", 76 | "test": "vitest --passWithNoTests", 77 | "release": "changeset publish" 78 | }, 79 | "peerDependencies": { 80 | "hono": ">=4.3.0" 81 | }, 82 | "dependencies": { 83 | "@hono/zod-validator": "^0.4.1", 84 | "zod": "^3.23.8" 85 | }, 86 | "packageManager": "pnpm@9.12.1" 87 | } 88 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | '@hono/zod-validator': 12 | specifier: ^0.4.1 13 | version: 0.4.1(hono@4.6.8)(zod@3.23.8) 14 | zod: 15 | specifier: ^3.23.8 16 | version: 3.23.8 17 | devDependencies: 18 | '@biomejs/biome': 19 | specifier: ^1.8.3 20 | version: 1.9.3 21 | '@changesets/cli': 22 | specifier: ^2.27.7 23 | version: 2.27.9 24 | '@cloudflare/vitest-pool-workers': 25 | specifier: ^0.5.18 26 | version: 0.5.18(@cloudflare/workers-types@4.20241011.0)(@vitest/runner@2.1.3)(@vitest/snapshot@2.1.3)(vitest@2.1.3(@edge-runtime/vm@4.0.3)(@types/node@22.7.5)) 27 | '@cloudflare/workers-types': 28 | specifier: ^4.20240529.0 29 | version: 4.20241011.0 30 | hono: 31 | specifier: ^4.6.8 32 | version: 4.6.8 33 | tsup: 34 | specifier: ^8.2.3 35 | version: 8.3.0(postcss@8.4.47)(typescript@5.6.3) 36 | typescript: 37 | specifier: ^5.5.4 38 | version: 5.6.3 39 | vitest: 40 | specifier: 2.1.3 41 | version: 2.1.3(@edge-runtime/vm@4.0.3)(@types/node@22.7.5) 42 | wrangler: 43 | specifier: ^3.67.1 44 | version: 3.80.4(@cloudflare/workers-types@4.20241011.0) 45 | 46 | packages: 47 | 48 | '@babel/runtime@7.25.7': 49 | resolution: {integrity: sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==} 50 | engines: {node: '>=6.9.0'} 51 | 52 | '@biomejs/biome@1.9.3': 53 | resolution: {integrity: sha512-POjAPz0APAmX33WOQFGQrwLvlu7WLV4CFJMlB12b6ZSg+2q6fYu9kZwLCOA+x83zXfcPd1RpuWOKJW0GbBwLIQ==} 54 | engines: {node: '>=14.21.3'} 55 | hasBin: true 56 | 57 | '@biomejs/cli-darwin-arm64@1.9.3': 58 | resolution: {integrity: sha512-QZzD2XrjJDUyIZK+aR2i5DDxCJfdwiYbUKu9GzkCUJpL78uSelAHAPy7m0GuPMVtF/Uo+OKv97W3P9nuWZangQ==} 59 | engines: {node: '>=14.21.3'} 60 | cpu: [arm64] 61 | os: [darwin] 62 | 63 | '@biomejs/cli-darwin-x64@1.9.3': 64 | resolution: {integrity: sha512-vSCoIBJE0BN3SWDFuAY/tRavpUtNoqiceJ5PrU3xDfsLcm/U6N93JSM0M9OAiC/X7mPPfejtr6Yc9vSgWlEgVw==} 65 | engines: {node: '>=14.21.3'} 66 | cpu: [x64] 67 | os: [darwin] 68 | 69 | '@biomejs/cli-linux-arm64-musl@1.9.3': 70 | resolution: {integrity: sha512-VBzyhaqqqwP3bAkkBrhVq50i3Uj9+RWuj+pYmXrMDgjS5+SKYGE56BwNw4l8hR3SmYbLSbEo15GcV043CDSk+Q==} 71 | engines: {node: '>=14.21.3'} 72 | cpu: [arm64] 73 | os: [linux] 74 | 75 | '@biomejs/cli-linux-arm64@1.9.3': 76 | resolution: {integrity: sha512-vJkAimD2+sVviNTbaWOGqEBy31cW0ZB52KtpVIbkuma7PlfII3tsLhFa+cwbRAcRBkobBBhqZ06hXoZAN8NODQ==} 77 | engines: {node: '>=14.21.3'} 78 | cpu: [arm64] 79 | os: [linux] 80 | 81 | '@biomejs/cli-linux-x64-musl@1.9.3': 82 | resolution: {integrity: sha512-TJmnOG2+NOGM72mlczEsNki9UT+XAsMFAOo8J0me/N47EJ/vkLXxf481evfHLlxMejTY6IN8SdRSiPVLv6AHlA==} 83 | engines: {node: '>=14.21.3'} 84 | cpu: [x64] 85 | os: [linux] 86 | 87 | '@biomejs/cli-linux-x64@1.9.3': 88 | resolution: {integrity: sha512-x220V4c+romd26Mu1ptU+EudMXVS4xmzKxPVb9mgnfYlN4Yx9vD5NZraSx/onJnd3Gh/y8iPUdU5CDZJKg9COA==} 89 | engines: {node: '>=14.21.3'} 90 | cpu: [x64] 91 | os: [linux] 92 | 93 | '@biomejs/cli-win32-arm64@1.9.3': 94 | resolution: {integrity: sha512-lg/yZis2HdQGsycUvHWSzo9kOvnGgvtrYRgoCEwPBwwAL8/6crOp3+f47tPwI/LI1dZrhSji7PNsGKGHbwyAhw==} 95 | engines: {node: '>=14.21.3'} 96 | cpu: [arm64] 97 | os: [win32] 98 | 99 | '@biomejs/cli-win32-x64@1.9.3': 100 | resolution: {integrity: sha512-cQMy2zanBkVLpmmxXdK6YePzmZx0s5Z7KEnwmrW54rcXK3myCNbQa09SwGZ8i/8sLw0H9F3X7K4rxVNGU8/D4Q==} 101 | engines: {node: '>=14.21.3'} 102 | cpu: [x64] 103 | os: [win32] 104 | 105 | '@changesets/apply-release-plan@7.0.5': 106 | resolution: {integrity: sha512-1cWCk+ZshEkSVEZrm2fSj1Gz8sYvxgUL4Q78+1ZZqeqfuevPTPk033/yUZ3df8BKMohkqqHfzj0HOOrG0KtXTw==} 107 | 108 | '@changesets/assemble-release-plan@6.0.4': 109 | resolution: {integrity: sha512-nqICnvmrwWj4w2x0fOhVj2QEGdlUuwVAwESrUo5HLzWMI1rE5SWfsr9ln+rDqWB6RQ2ZyaMZHUcU7/IRaUJS+Q==} 110 | 111 | '@changesets/changelog-git@0.2.0': 112 | resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} 113 | 114 | '@changesets/cli@2.27.9': 115 | resolution: {integrity: sha512-q42a/ZbDnxPpCb5Wkm6tMVIxgeI9C/bexntzTeCFBrQEdpisQqk8kCHllYZMDjYtEc1ZzumbMJAG8H0Z4rdvjg==} 116 | hasBin: true 117 | 118 | '@changesets/config@3.0.3': 119 | resolution: {integrity: sha512-vqgQZMyIcuIpw9nqFIpTSNyc/wgm/Lu1zKN5vECy74u95Qx/Wa9g27HdgO4NkVAaq+BGA8wUc/qvbvVNs93n6A==} 120 | 121 | '@changesets/errors@0.2.0': 122 | resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} 123 | 124 | '@changesets/get-dependents-graph@2.1.2': 125 | resolution: {integrity: sha512-sgcHRkiBY9i4zWYBwlVyAjEM9sAzs4wYVwJUdnbDLnVG3QwAaia1Mk5P8M7kraTOZN+vBET7n8KyB0YXCbFRLQ==} 126 | 127 | '@changesets/get-release-plan@4.0.4': 128 | resolution: {integrity: sha512-SicG/S67JmPTrdcc9Vpu0wSQt7IiuN0dc8iR5VScnnTVPfIaLvKmEGRvIaF0kcn8u5ZqLbormZNTO77bCEvyWw==} 129 | 130 | '@changesets/get-version-range-type@0.4.0': 131 | resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} 132 | 133 | '@changesets/git@3.0.1': 134 | resolution: {integrity: sha512-pdgHcYBLCPcLd82aRcuO0kxCDbw/yISlOtkmwmE8Odo1L6hSiZrBOsRl84eYG7DRCab/iHnOkWqExqc4wxk2LQ==} 135 | 136 | '@changesets/logger@0.1.1': 137 | resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} 138 | 139 | '@changesets/parse@0.4.0': 140 | resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} 141 | 142 | '@changesets/pre@2.0.1': 143 | resolution: {integrity: sha512-vvBJ/If4jKM4tPz9JdY2kGOgWmCowUYOi5Ycv8dyLnEE8FgpYYUo1mgJZxcdtGGP3aG8rAQulGLyyXGSLkIMTQ==} 144 | 145 | '@changesets/read@0.6.1': 146 | resolution: {integrity: sha512-jYMbyXQk3nwP25nRzQQGa1nKLY0KfoOV7VLgwucI0bUO8t8ZLCr6LZmgjXsiKuRDc+5A6doKPr9w2d+FEJ55zQ==} 147 | 148 | '@changesets/should-skip-package@0.1.1': 149 | resolution: {integrity: sha512-H9LjLbF6mMHLtJIc/eHR9Na+MifJ3VxtgP/Y+XLn4BF7tDTEN1HNYtH6QMcjP1uxp9sjaFYmW8xqloaCi/ckTg==} 150 | 151 | '@changesets/types@4.1.0': 152 | resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} 153 | 154 | '@changesets/types@6.0.0': 155 | resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} 156 | 157 | '@changesets/write@0.3.2': 158 | resolution: {integrity: sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==} 159 | 160 | '@cloudflare/kv-asset-handler@0.3.4': 161 | resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} 162 | engines: {node: '>=16.13'} 163 | 164 | '@cloudflare/vitest-pool-workers@0.5.18': 165 | resolution: {integrity: sha512-V7KcsgS2CaTyNu16OuGki07u2j1ThhWCHM6EyqVkYm8ow6K+8jA8GQ0/ktBzjsqLYt7gimIHCOe8RaKfRcriRw==} 166 | peerDependencies: 167 | '@vitest/runner': 2.0.x - 2.1.x 168 | '@vitest/snapshot': 2.0.x - 2.1.x 169 | vitest: 2.0.x - 2.1.x 170 | 171 | '@cloudflare/workerd-darwin-64@1.20241004.0': 172 | resolution: {integrity: sha512-c2afR486NXDRcPm7RaTSRDnffFklPCXde/IeNVhEhBJ8O+pQhBOdDcGIy8zXPwMu0CYga0iHNZmpbsl+ZcHttA==} 173 | engines: {node: '>=16'} 174 | cpu: [x64] 175 | os: [darwin] 176 | 177 | '@cloudflare/workerd-darwin-arm64@1.20241004.0': 178 | resolution: {integrity: sha512-siD9fexv5lr2IpBczWV7OPgJvHj8/fJUrRAYCMcBURkfiwssK91coQeZlN1NdQ85aYELVgxDFoG+p86OS+ZzLw==} 179 | engines: {node: '>=16'} 180 | cpu: [arm64] 181 | os: [darwin] 182 | 183 | '@cloudflare/workerd-linux-64@1.20241004.0': 184 | resolution: {integrity: sha512-EtKGXO5fzRgX6UhDDLhjjEsB1QtliHb12zavZ/S0C8hKPz76II7MQ3Lls9kfB62fbdMP8L6vcqWPObEUcw6GSw==} 185 | engines: {node: '>=16'} 186 | cpu: [x64] 187 | os: [linux] 188 | 189 | '@cloudflare/workerd-linux-arm64@1.20241004.0': 190 | resolution: {integrity: sha512-XO7VBE1YaFf/o9tKO1PqDqaxkU2eAR2DLX7R0+R8p+q92sUDXyoxo48T3yJDfxWndnKJ6hSJfvKanw3Mq9Tisw==} 191 | engines: {node: '>=16'} 192 | cpu: [arm64] 193 | os: [linux] 194 | 195 | '@cloudflare/workerd-windows-64@1.20241004.0': 196 | resolution: {integrity: sha512-o+TmCYGq58jNUDbG73xOvd648XvJ2TicI++2BBoySklJXG6f4But5AwA8TxQgmeujR3vpBjPZKexEzcZSUOTtA==} 197 | engines: {node: '>=16'} 198 | cpu: [x64] 199 | os: [win32] 200 | 201 | '@cloudflare/workers-shared@0.6.0': 202 | resolution: {integrity: sha512-rfUCvb3hx4AsvdUZsxgk9lmgEnQehqV3jdtXLP/Xr0+P56n11T/0nXNMzmn7Nnv+IJFOV6X9NmFhuMz4sBPw7w==} 203 | engines: {node: '>=16.7.0'} 204 | 205 | '@cloudflare/workers-types@4.20241011.0': 206 | resolution: {integrity: sha512-emwBnuFB/2lS1z6NXAeBqrSL8Xwnr7YpgdLuchOmgu/igqBsLLNPBb4Qmgh3neFWUe9wbzQyx030836YF3c3Xw==} 207 | 208 | '@cspotcode/source-map-support@0.8.1': 209 | resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} 210 | engines: {node: '>=12'} 211 | 212 | '@edge-runtime/primitives@5.1.0': 213 | resolution: {integrity: sha512-bs379S/qL7b9B1fXM3xYe+g2orW7Uy0m8oIudiXLcHQyZLsdd0Gfw9STngFDnaAfAcRN5g+/YEMPSsDqiPm0TQ==} 214 | engines: {node: '>=16'} 215 | 216 | '@edge-runtime/vm@4.0.3': 217 | resolution: {integrity: sha512-2EKlqxSbZTV4D+XG8DTX+9P1SL+m48ahvNbDuxz+dZkmUZ+ju4hl/m28j7QMbC9kU5S+4HUJCYKCAfA+3gggLw==} 218 | engines: {node: '>=16'} 219 | 220 | '@esbuild-plugins/node-globals-polyfill@0.2.3': 221 | resolution: {integrity: sha512-r3MIryXDeXDOZh7ih1l/yE9ZLORCd5e8vWg02azWRGj5SPTuoh69A2AIyn0Z31V/kHBfZ4HgWJ+OK3GTTwLmnw==} 222 | peerDependencies: 223 | esbuild: '*' 224 | 225 | '@esbuild-plugins/node-modules-polyfill@0.2.2': 226 | resolution: {integrity: sha512-LXV7QsWJxRuMYvKbiznh+U1ilIop3g2TeKRzUxOG5X3YITc8JyyTa90BmLwqqv0YnX4v32CSlG+vsziZp9dMvA==} 227 | peerDependencies: 228 | esbuild: '*' 229 | 230 | '@esbuild/aix-ppc64@0.21.5': 231 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 232 | engines: {node: '>=12'} 233 | cpu: [ppc64] 234 | os: [aix] 235 | 236 | '@esbuild/aix-ppc64@0.23.1': 237 | resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} 238 | engines: {node: '>=18'} 239 | cpu: [ppc64] 240 | os: [aix] 241 | 242 | '@esbuild/android-arm64@0.17.19': 243 | resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} 244 | engines: {node: '>=12'} 245 | cpu: [arm64] 246 | os: [android] 247 | 248 | '@esbuild/android-arm64@0.21.5': 249 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 250 | engines: {node: '>=12'} 251 | cpu: [arm64] 252 | os: [android] 253 | 254 | '@esbuild/android-arm64@0.23.1': 255 | resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} 256 | engines: {node: '>=18'} 257 | cpu: [arm64] 258 | os: [android] 259 | 260 | '@esbuild/android-arm@0.17.19': 261 | resolution: {integrity: sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==} 262 | engines: {node: '>=12'} 263 | cpu: [arm] 264 | os: [android] 265 | 266 | '@esbuild/android-arm@0.21.5': 267 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 268 | engines: {node: '>=12'} 269 | cpu: [arm] 270 | os: [android] 271 | 272 | '@esbuild/android-arm@0.23.1': 273 | resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} 274 | engines: {node: '>=18'} 275 | cpu: [arm] 276 | os: [android] 277 | 278 | '@esbuild/android-x64@0.17.19': 279 | resolution: {integrity: sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==} 280 | engines: {node: '>=12'} 281 | cpu: [x64] 282 | os: [android] 283 | 284 | '@esbuild/android-x64@0.21.5': 285 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 286 | engines: {node: '>=12'} 287 | cpu: [x64] 288 | os: [android] 289 | 290 | '@esbuild/android-x64@0.23.1': 291 | resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} 292 | engines: {node: '>=18'} 293 | cpu: [x64] 294 | os: [android] 295 | 296 | '@esbuild/darwin-arm64@0.17.19': 297 | resolution: {integrity: sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==} 298 | engines: {node: '>=12'} 299 | cpu: [arm64] 300 | os: [darwin] 301 | 302 | '@esbuild/darwin-arm64@0.21.5': 303 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 304 | engines: {node: '>=12'} 305 | cpu: [arm64] 306 | os: [darwin] 307 | 308 | '@esbuild/darwin-arm64@0.23.1': 309 | resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} 310 | engines: {node: '>=18'} 311 | cpu: [arm64] 312 | os: [darwin] 313 | 314 | '@esbuild/darwin-x64@0.17.19': 315 | resolution: {integrity: sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==} 316 | engines: {node: '>=12'} 317 | cpu: [x64] 318 | os: [darwin] 319 | 320 | '@esbuild/darwin-x64@0.21.5': 321 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 322 | engines: {node: '>=12'} 323 | cpu: [x64] 324 | os: [darwin] 325 | 326 | '@esbuild/darwin-x64@0.23.1': 327 | resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} 328 | engines: {node: '>=18'} 329 | cpu: [x64] 330 | os: [darwin] 331 | 332 | '@esbuild/freebsd-arm64@0.17.19': 333 | resolution: {integrity: sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==} 334 | engines: {node: '>=12'} 335 | cpu: [arm64] 336 | os: [freebsd] 337 | 338 | '@esbuild/freebsd-arm64@0.21.5': 339 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 340 | engines: {node: '>=12'} 341 | cpu: [arm64] 342 | os: [freebsd] 343 | 344 | '@esbuild/freebsd-arm64@0.23.1': 345 | resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} 346 | engines: {node: '>=18'} 347 | cpu: [arm64] 348 | os: [freebsd] 349 | 350 | '@esbuild/freebsd-x64@0.17.19': 351 | resolution: {integrity: sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==} 352 | engines: {node: '>=12'} 353 | cpu: [x64] 354 | os: [freebsd] 355 | 356 | '@esbuild/freebsd-x64@0.21.5': 357 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 358 | engines: {node: '>=12'} 359 | cpu: [x64] 360 | os: [freebsd] 361 | 362 | '@esbuild/freebsd-x64@0.23.1': 363 | resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} 364 | engines: {node: '>=18'} 365 | cpu: [x64] 366 | os: [freebsd] 367 | 368 | '@esbuild/linux-arm64@0.17.19': 369 | resolution: {integrity: sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==} 370 | engines: {node: '>=12'} 371 | cpu: [arm64] 372 | os: [linux] 373 | 374 | '@esbuild/linux-arm64@0.21.5': 375 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 376 | engines: {node: '>=12'} 377 | cpu: [arm64] 378 | os: [linux] 379 | 380 | '@esbuild/linux-arm64@0.23.1': 381 | resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} 382 | engines: {node: '>=18'} 383 | cpu: [arm64] 384 | os: [linux] 385 | 386 | '@esbuild/linux-arm@0.17.19': 387 | resolution: {integrity: sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==} 388 | engines: {node: '>=12'} 389 | cpu: [arm] 390 | os: [linux] 391 | 392 | '@esbuild/linux-arm@0.21.5': 393 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 394 | engines: {node: '>=12'} 395 | cpu: [arm] 396 | os: [linux] 397 | 398 | '@esbuild/linux-arm@0.23.1': 399 | resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} 400 | engines: {node: '>=18'} 401 | cpu: [arm] 402 | os: [linux] 403 | 404 | '@esbuild/linux-ia32@0.17.19': 405 | resolution: {integrity: sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==} 406 | engines: {node: '>=12'} 407 | cpu: [ia32] 408 | os: [linux] 409 | 410 | '@esbuild/linux-ia32@0.21.5': 411 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 412 | engines: {node: '>=12'} 413 | cpu: [ia32] 414 | os: [linux] 415 | 416 | '@esbuild/linux-ia32@0.23.1': 417 | resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} 418 | engines: {node: '>=18'} 419 | cpu: [ia32] 420 | os: [linux] 421 | 422 | '@esbuild/linux-loong64@0.17.19': 423 | resolution: {integrity: sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==} 424 | engines: {node: '>=12'} 425 | cpu: [loong64] 426 | os: [linux] 427 | 428 | '@esbuild/linux-loong64@0.21.5': 429 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 430 | engines: {node: '>=12'} 431 | cpu: [loong64] 432 | os: [linux] 433 | 434 | '@esbuild/linux-loong64@0.23.1': 435 | resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} 436 | engines: {node: '>=18'} 437 | cpu: [loong64] 438 | os: [linux] 439 | 440 | '@esbuild/linux-mips64el@0.17.19': 441 | resolution: {integrity: sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==} 442 | engines: {node: '>=12'} 443 | cpu: [mips64el] 444 | os: [linux] 445 | 446 | '@esbuild/linux-mips64el@0.21.5': 447 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 448 | engines: {node: '>=12'} 449 | cpu: [mips64el] 450 | os: [linux] 451 | 452 | '@esbuild/linux-mips64el@0.23.1': 453 | resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} 454 | engines: {node: '>=18'} 455 | cpu: [mips64el] 456 | os: [linux] 457 | 458 | '@esbuild/linux-ppc64@0.17.19': 459 | resolution: {integrity: sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==} 460 | engines: {node: '>=12'} 461 | cpu: [ppc64] 462 | os: [linux] 463 | 464 | '@esbuild/linux-ppc64@0.21.5': 465 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 466 | engines: {node: '>=12'} 467 | cpu: [ppc64] 468 | os: [linux] 469 | 470 | '@esbuild/linux-ppc64@0.23.1': 471 | resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} 472 | engines: {node: '>=18'} 473 | cpu: [ppc64] 474 | os: [linux] 475 | 476 | '@esbuild/linux-riscv64@0.17.19': 477 | resolution: {integrity: sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==} 478 | engines: {node: '>=12'} 479 | cpu: [riscv64] 480 | os: [linux] 481 | 482 | '@esbuild/linux-riscv64@0.21.5': 483 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 484 | engines: {node: '>=12'} 485 | cpu: [riscv64] 486 | os: [linux] 487 | 488 | '@esbuild/linux-riscv64@0.23.1': 489 | resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} 490 | engines: {node: '>=18'} 491 | cpu: [riscv64] 492 | os: [linux] 493 | 494 | '@esbuild/linux-s390x@0.17.19': 495 | resolution: {integrity: sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==} 496 | engines: {node: '>=12'} 497 | cpu: [s390x] 498 | os: [linux] 499 | 500 | '@esbuild/linux-s390x@0.21.5': 501 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 502 | engines: {node: '>=12'} 503 | cpu: [s390x] 504 | os: [linux] 505 | 506 | '@esbuild/linux-s390x@0.23.1': 507 | resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} 508 | engines: {node: '>=18'} 509 | cpu: [s390x] 510 | os: [linux] 511 | 512 | '@esbuild/linux-x64@0.17.19': 513 | resolution: {integrity: sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==} 514 | engines: {node: '>=12'} 515 | cpu: [x64] 516 | os: [linux] 517 | 518 | '@esbuild/linux-x64@0.21.5': 519 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 520 | engines: {node: '>=12'} 521 | cpu: [x64] 522 | os: [linux] 523 | 524 | '@esbuild/linux-x64@0.23.1': 525 | resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} 526 | engines: {node: '>=18'} 527 | cpu: [x64] 528 | os: [linux] 529 | 530 | '@esbuild/netbsd-x64@0.17.19': 531 | resolution: {integrity: sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==} 532 | engines: {node: '>=12'} 533 | cpu: [x64] 534 | os: [netbsd] 535 | 536 | '@esbuild/netbsd-x64@0.21.5': 537 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 538 | engines: {node: '>=12'} 539 | cpu: [x64] 540 | os: [netbsd] 541 | 542 | '@esbuild/netbsd-x64@0.23.1': 543 | resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} 544 | engines: {node: '>=18'} 545 | cpu: [x64] 546 | os: [netbsd] 547 | 548 | '@esbuild/openbsd-arm64@0.23.1': 549 | resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} 550 | engines: {node: '>=18'} 551 | cpu: [arm64] 552 | os: [openbsd] 553 | 554 | '@esbuild/openbsd-x64@0.17.19': 555 | resolution: {integrity: sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==} 556 | engines: {node: '>=12'} 557 | cpu: [x64] 558 | os: [openbsd] 559 | 560 | '@esbuild/openbsd-x64@0.21.5': 561 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 562 | engines: {node: '>=12'} 563 | cpu: [x64] 564 | os: [openbsd] 565 | 566 | '@esbuild/openbsd-x64@0.23.1': 567 | resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} 568 | engines: {node: '>=18'} 569 | cpu: [x64] 570 | os: [openbsd] 571 | 572 | '@esbuild/sunos-x64@0.17.19': 573 | resolution: {integrity: sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==} 574 | engines: {node: '>=12'} 575 | cpu: [x64] 576 | os: [sunos] 577 | 578 | '@esbuild/sunos-x64@0.21.5': 579 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 580 | engines: {node: '>=12'} 581 | cpu: [x64] 582 | os: [sunos] 583 | 584 | '@esbuild/sunos-x64@0.23.1': 585 | resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} 586 | engines: {node: '>=18'} 587 | cpu: [x64] 588 | os: [sunos] 589 | 590 | '@esbuild/win32-arm64@0.17.19': 591 | resolution: {integrity: sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==} 592 | engines: {node: '>=12'} 593 | cpu: [arm64] 594 | os: [win32] 595 | 596 | '@esbuild/win32-arm64@0.21.5': 597 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 598 | engines: {node: '>=12'} 599 | cpu: [arm64] 600 | os: [win32] 601 | 602 | '@esbuild/win32-arm64@0.23.1': 603 | resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} 604 | engines: {node: '>=18'} 605 | cpu: [arm64] 606 | os: [win32] 607 | 608 | '@esbuild/win32-ia32@0.17.19': 609 | resolution: {integrity: sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==} 610 | engines: {node: '>=12'} 611 | cpu: [ia32] 612 | os: [win32] 613 | 614 | '@esbuild/win32-ia32@0.21.5': 615 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 616 | engines: {node: '>=12'} 617 | cpu: [ia32] 618 | os: [win32] 619 | 620 | '@esbuild/win32-ia32@0.23.1': 621 | resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} 622 | engines: {node: '>=18'} 623 | cpu: [ia32] 624 | os: [win32] 625 | 626 | '@esbuild/win32-x64@0.17.19': 627 | resolution: {integrity: sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==} 628 | engines: {node: '>=12'} 629 | cpu: [x64] 630 | os: [win32] 631 | 632 | '@esbuild/win32-x64@0.21.5': 633 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 634 | engines: {node: '>=12'} 635 | cpu: [x64] 636 | os: [win32] 637 | 638 | '@esbuild/win32-x64@0.23.1': 639 | resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} 640 | engines: {node: '>=18'} 641 | cpu: [x64] 642 | os: [win32] 643 | 644 | '@fastify/busboy@2.1.1': 645 | resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} 646 | engines: {node: '>=14'} 647 | 648 | '@hono/zod-validator@0.4.1': 649 | resolution: {integrity: sha512-I8LyfeJfvVmC5hPjZ2Iij7RjexlgSBT7QJudZ4JvNPLxn0JQ3sqclz2zydlwISAnw21D2n4LQ0nfZdoiv9fQQA==} 650 | peerDependencies: 651 | hono: '>=3.9.0' 652 | zod: ^3.19.1 653 | 654 | '@isaacs/cliui@8.0.2': 655 | resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} 656 | engines: {node: '>=12'} 657 | 658 | '@jridgewell/gen-mapping@0.3.5': 659 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 660 | engines: {node: '>=6.0.0'} 661 | 662 | '@jridgewell/resolve-uri@3.1.2': 663 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 664 | engines: {node: '>=6.0.0'} 665 | 666 | '@jridgewell/set-array@1.2.1': 667 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 668 | engines: {node: '>=6.0.0'} 669 | 670 | '@jridgewell/sourcemap-codec@1.5.0': 671 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 672 | 673 | '@jridgewell/trace-mapping@0.3.25': 674 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 675 | 676 | '@jridgewell/trace-mapping@0.3.9': 677 | resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} 678 | 679 | '@manypkg/find-root@1.1.0': 680 | resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} 681 | 682 | '@manypkg/get-packages@1.1.3': 683 | resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} 684 | 685 | '@nodelib/fs.scandir@2.1.5': 686 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 687 | engines: {node: '>= 8'} 688 | 689 | '@nodelib/fs.stat@2.0.5': 690 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 691 | engines: {node: '>= 8'} 692 | 693 | '@nodelib/fs.walk@1.2.8': 694 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 695 | engines: {node: '>= 8'} 696 | 697 | '@pkgjs/parseargs@0.11.0': 698 | resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} 699 | engines: {node: '>=14'} 700 | 701 | '@rollup/rollup-android-arm-eabi@4.24.0': 702 | resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} 703 | cpu: [arm] 704 | os: [android] 705 | 706 | '@rollup/rollup-android-arm64@4.24.0': 707 | resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} 708 | cpu: [arm64] 709 | os: [android] 710 | 711 | '@rollup/rollup-darwin-arm64@4.24.0': 712 | resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} 713 | cpu: [arm64] 714 | os: [darwin] 715 | 716 | '@rollup/rollup-darwin-x64@4.24.0': 717 | resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} 718 | cpu: [x64] 719 | os: [darwin] 720 | 721 | '@rollup/rollup-linux-arm-gnueabihf@4.24.0': 722 | resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} 723 | cpu: [arm] 724 | os: [linux] 725 | 726 | '@rollup/rollup-linux-arm-musleabihf@4.24.0': 727 | resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} 728 | cpu: [arm] 729 | os: [linux] 730 | 731 | '@rollup/rollup-linux-arm64-gnu@4.24.0': 732 | resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} 733 | cpu: [arm64] 734 | os: [linux] 735 | 736 | '@rollup/rollup-linux-arm64-musl@4.24.0': 737 | resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} 738 | cpu: [arm64] 739 | os: [linux] 740 | 741 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': 742 | resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} 743 | cpu: [ppc64] 744 | os: [linux] 745 | 746 | '@rollup/rollup-linux-riscv64-gnu@4.24.0': 747 | resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} 748 | cpu: [riscv64] 749 | os: [linux] 750 | 751 | '@rollup/rollup-linux-s390x-gnu@4.24.0': 752 | resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} 753 | cpu: [s390x] 754 | os: [linux] 755 | 756 | '@rollup/rollup-linux-x64-gnu@4.24.0': 757 | resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} 758 | cpu: [x64] 759 | os: [linux] 760 | 761 | '@rollup/rollup-linux-x64-musl@4.24.0': 762 | resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} 763 | cpu: [x64] 764 | os: [linux] 765 | 766 | '@rollup/rollup-win32-arm64-msvc@4.24.0': 767 | resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} 768 | cpu: [arm64] 769 | os: [win32] 770 | 771 | '@rollup/rollup-win32-ia32-msvc@4.24.0': 772 | resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} 773 | cpu: [ia32] 774 | os: [win32] 775 | 776 | '@rollup/rollup-win32-x64-msvc@4.24.0': 777 | resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} 778 | cpu: [x64] 779 | os: [win32] 780 | 781 | '@types/estree@1.0.6': 782 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 783 | 784 | '@types/node-forge@1.3.11': 785 | resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} 786 | 787 | '@types/node@12.20.55': 788 | resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} 789 | 790 | '@types/node@22.7.5': 791 | resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} 792 | 793 | '@vitest/expect@2.1.3': 794 | resolution: {integrity: sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==} 795 | 796 | '@vitest/mocker@2.1.3': 797 | resolution: {integrity: sha512-eSpdY/eJDuOvuTA3ASzCjdithHa+GIF1L4PqtEELl6Qa3XafdMLBpBlZCIUCX2J+Q6sNmjmxtosAG62fK4BlqQ==} 798 | peerDependencies: 799 | '@vitest/spy': 2.1.3 800 | msw: ^2.3.5 801 | vite: ^5.0.0 802 | peerDependenciesMeta: 803 | msw: 804 | optional: true 805 | vite: 806 | optional: true 807 | 808 | '@vitest/pretty-format@2.1.3': 809 | resolution: {integrity: sha512-XH1XdtoLZCpqV59KRbPrIhFCOO0hErxrQCMcvnQete3Vibb9UeIOX02uFPfVn3Z9ZXsq78etlfyhnkmIZSzIwQ==} 810 | 811 | '@vitest/runner@2.1.3': 812 | resolution: {integrity: sha512-JGzpWqmFJ4fq5ZKHtVO3Xuy1iF2rHGV4d/pdzgkYHm1+gOzNZtqjvyiaDGJytRyMU54qkxpNzCx+PErzJ1/JqQ==} 813 | 814 | '@vitest/snapshot@2.1.3': 815 | resolution: {integrity: sha512-qWC2mWc7VAXmjAkEKxrScWHWFyCQx/cmiZtuGqMi+WwqQJ2iURsVY4ZfAK6dVo6K2smKRU6l3BPwqEBvhnpQGg==} 816 | 817 | '@vitest/spy@2.1.3': 818 | resolution: {integrity: sha512-Nb2UzbcUswzeSP7JksMDaqsI43Sj5+Kry6ry6jQJT4b5gAK+NS9NED6mDb8FlMRCX8m5guaHCDZmqYMMWRy5nQ==} 819 | 820 | '@vitest/utils@2.1.3': 821 | resolution: {integrity: sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==} 822 | 823 | acorn-walk@8.3.4: 824 | resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} 825 | engines: {node: '>=0.4.0'} 826 | 827 | acorn@8.12.1: 828 | resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} 829 | engines: {node: '>=0.4.0'} 830 | hasBin: true 831 | 832 | ansi-colors@4.1.3: 833 | resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} 834 | engines: {node: '>=6'} 835 | 836 | ansi-regex@5.0.1: 837 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} 838 | engines: {node: '>=8'} 839 | 840 | ansi-regex@6.1.0: 841 | resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} 842 | engines: {node: '>=12'} 843 | 844 | ansi-styles@4.3.0: 845 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 846 | engines: {node: '>=8'} 847 | 848 | ansi-styles@6.2.1: 849 | resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} 850 | engines: {node: '>=12'} 851 | 852 | any-promise@1.3.0: 853 | resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} 854 | 855 | anymatch@3.1.3: 856 | resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} 857 | engines: {node: '>= 8'} 858 | 859 | argparse@1.0.10: 860 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 861 | 862 | array-union@2.1.0: 863 | resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} 864 | engines: {node: '>=8'} 865 | 866 | as-table@1.0.55: 867 | resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==} 868 | 869 | assertion-error@2.0.1: 870 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 871 | engines: {node: '>=12'} 872 | 873 | balanced-match@1.0.2: 874 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 875 | 876 | better-path-resolve@1.0.0: 877 | resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} 878 | engines: {node: '>=4'} 879 | 880 | binary-extensions@2.3.0: 881 | resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} 882 | engines: {node: '>=8'} 883 | 884 | birpc@0.2.14: 885 | resolution: {integrity: sha512-37FHE8rqsYM5JEKCnXFyHpBCzvgHEExwVVTq+nUmloInU7l8ezD1TpOhKpS8oe1DTYFqEK27rFZVKG43oTqXRA==} 886 | 887 | blake3-wasm@2.1.5: 888 | resolution: {integrity: sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==} 889 | 890 | brace-expansion@2.0.1: 891 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 892 | 893 | braces@3.0.3: 894 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 895 | engines: {node: '>=8'} 896 | 897 | bundle-require@5.0.0: 898 | resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==} 899 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 900 | peerDependencies: 901 | esbuild: '>=0.18' 902 | 903 | cac@6.7.14: 904 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 905 | engines: {node: '>=8'} 906 | 907 | capnp-ts@0.7.0: 908 | resolution: {integrity: sha512-XKxXAC3HVPv7r674zP0VC3RTXz+/JKhfyw94ljvF80yynK6VkTnqE3jMuN8b3dUVmmc43TjyxjW4KTsmB3c86g==} 909 | 910 | chai@5.1.1: 911 | resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} 912 | engines: {node: '>=12'} 913 | 914 | chardet@0.7.0: 915 | resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} 916 | 917 | check-error@2.1.1: 918 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 919 | engines: {node: '>= 16'} 920 | 921 | chokidar@3.6.0: 922 | resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} 923 | engines: {node: '>= 8.10.0'} 924 | 925 | ci-info@3.9.0: 926 | resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} 927 | engines: {node: '>=8'} 928 | 929 | cjs-module-lexer@1.4.1: 930 | resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} 931 | 932 | color-convert@2.0.1: 933 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 934 | engines: {node: '>=7.0.0'} 935 | 936 | color-name@1.1.4: 937 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 938 | 939 | commander@4.1.1: 940 | resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} 941 | engines: {node: '>= 6'} 942 | 943 | consola@3.2.3: 944 | resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} 945 | engines: {node: ^14.18.0 || >=16.10.0} 946 | 947 | cookie@0.7.2: 948 | resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} 949 | engines: {node: '>= 0.6'} 950 | 951 | cross-spawn@5.1.0: 952 | resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} 953 | 954 | cross-spawn@7.0.3: 955 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} 956 | engines: {node: '>= 8'} 957 | 958 | data-uri-to-buffer@2.0.2: 959 | resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==} 960 | 961 | debug@4.3.7: 962 | resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} 963 | engines: {node: '>=6.0'} 964 | peerDependencies: 965 | supports-color: '*' 966 | peerDependenciesMeta: 967 | supports-color: 968 | optional: true 969 | 970 | deep-eql@5.0.2: 971 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 972 | engines: {node: '>=6'} 973 | 974 | defu@6.1.4: 975 | resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 976 | 977 | detect-indent@6.1.0: 978 | resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} 979 | engines: {node: '>=8'} 980 | 981 | devalue@4.3.3: 982 | resolution: {integrity: sha512-UH8EL6H2ifcY8TbD2QsxwCC/pr5xSwPvv85LrLXVihmHVC3T3YqTCIwnR5ak0yO1KYqlxrPVOA/JVZJYPy2ATg==} 983 | 984 | dir-glob@3.0.1: 985 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 986 | engines: {node: '>=8'} 987 | 988 | eastasianwidth@0.2.0: 989 | resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} 990 | 991 | emoji-regex@8.0.0: 992 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} 993 | 994 | emoji-regex@9.2.2: 995 | resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} 996 | 997 | enquirer@2.4.1: 998 | resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} 999 | engines: {node: '>=8.6'} 1000 | 1001 | esbuild@0.17.19: 1002 | resolution: {integrity: sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==} 1003 | engines: {node: '>=12'} 1004 | hasBin: true 1005 | 1006 | esbuild@0.21.5: 1007 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 1008 | engines: {node: '>=12'} 1009 | hasBin: true 1010 | 1011 | esbuild@0.23.1: 1012 | resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} 1013 | engines: {node: '>=18'} 1014 | hasBin: true 1015 | 1016 | escape-string-regexp@4.0.0: 1017 | resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 1018 | engines: {node: '>=10'} 1019 | 1020 | esprima@4.0.1: 1021 | resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} 1022 | engines: {node: '>=4'} 1023 | hasBin: true 1024 | 1025 | estree-walker@0.6.1: 1026 | resolution: {integrity: sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==} 1027 | 1028 | estree-walker@3.0.3: 1029 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 1030 | 1031 | execa@5.1.1: 1032 | resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} 1033 | engines: {node: '>=10'} 1034 | 1035 | exit-hook@2.2.1: 1036 | resolution: {integrity: sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw==} 1037 | engines: {node: '>=6'} 1038 | 1039 | extendable-error@0.1.7: 1040 | resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} 1041 | 1042 | external-editor@3.1.0: 1043 | resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} 1044 | engines: {node: '>=4'} 1045 | 1046 | fast-glob@3.3.2: 1047 | resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} 1048 | engines: {node: '>=8.6.0'} 1049 | 1050 | fastq@1.17.1: 1051 | resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} 1052 | 1053 | fdir@6.4.0: 1054 | resolution: {integrity: sha512-3oB133prH1o4j/L5lLW7uOCF1PlD+/It2L0eL/iAqWMB91RBbqTewABqxhj0ibBd90EEmWZq7ntIWzVaWcXTGQ==} 1055 | peerDependencies: 1056 | picomatch: ^3 || ^4 1057 | peerDependenciesMeta: 1058 | picomatch: 1059 | optional: true 1060 | 1061 | fill-range@7.1.1: 1062 | resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 1063 | engines: {node: '>=8'} 1064 | 1065 | find-up@4.1.0: 1066 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} 1067 | engines: {node: '>=8'} 1068 | 1069 | foreground-child@3.3.0: 1070 | resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} 1071 | engines: {node: '>=14'} 1072 | 1073 | fs-extra@7.0.1: 1074 | resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} 1075 | engines: {node: '>=6 <7 || >=8'} 1076 | 1077 | fs-extra@8.1.0: 1078 | resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} 1079 | engines: {node: '>=6 <7 || >=8'} 1080 | 1081 | fsevents@2.3.3: 1082 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1083 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1084 | os: [darwin] 1085 | 1086 | function-bind@1.1.2: 1087 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 1088 | 1089 | get-source@2.0.12: 1090 | resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==} 1091 | 1092 | get-stream@6.0.1: 1093 | resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} 1094 | engines: {node: '>=10'} 1095 | 1096 | glob-parent@5.1.2: 1097 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1098 | engines: {node: '>= 6'} 1099 | 1100 | glob-to-regexp@0.4.1: 1101 | resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} 1102 | 1103 | glob@10.4.5: 1104 | resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} 1105 | hasBin: true 1106 | 1107 | globby@11.1.0: 1108 | resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} 1109 | engines: {node: '>=10'} 1110 | 1111 | graceful-fs@4.2.11: 1112 | resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} 1113 | 1114 | hasown@2.0.2: 1115 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1116 | engines: {node: '>= 0.4'} 1117 | 1118 | hono@4.6.8: 1119 | resolution: {integrity: sha512-f+2Ec9JAzabT61pglDiLJcF/DjiSefZkjCn9bzm1cYLGkD5ExJ3Jnv93ax9h0bn7UPLHF81KktoyjdQfWI2n1Q==} 1120 | engines: {node: '>=16.9.0'} 1121 | 1122 | human-id@1.0.2: 1123 | resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} 1124 | 1125 | human-signals@2.1.0: 1126 | resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} 1127 | engines: {node: '>=10.17.0'} 1128 | 1129 | iconv-lite@0.4.24: 1130 | resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} 1131 | engines: {node: '>=0.10.0'} 1132 | 1133 | ignore@5.3.2: 1134 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 1135 | engines: {node: '>= 4'} 1136 | 1137 | is-binary-path@2.1.0: 1138 | resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} 1139 | engines: {node: '>=8'} 1140 | 1141 | is-core-module@2.15.1: 1142 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 1143 | engines: {node: '>= 0.4'} 1144 | 1145 | is-extglob@2.1.1: 1146 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1147 | engines: {node: '>=0.10.0'} 1148 | 1149 | is-fullwidth-code-point@3.0.0: 1150 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} 1151 | engines: {node: '>=8'} 1152 | 1153 | is-glob@4.0.3: 1154 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1155 | engines: {node: '>=0.10.0'} 1156 | 1157 | is-number@7.0.0: 1158 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1159 | engines: {node: '>=0.12.0'} 1160 | 1161 | is-stream@2.0.1: 1162 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} 1163 | engines: {node: '>=8'} 1164 | 1165 | is-subdir@1.2.0: 1166 | resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} 1167 | engines: {node: '>=4'} 1168 | 1169 | is-windows@1.0.2: 1170 | resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} 1171 | engines: {node: '>=0.10.0'} 1172 | 1173 | isexe@2.0.0: 1174 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1175 | 1176 | jackspeak@3.4.3: 1177 | resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} 1178 | 1179 | joycon@3.1.1: 1180 | resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} 1181 | engines: {node: '>=10'} 1182 | 1183 | js-yaml@3.14.1: 1184 | resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} 1185 | hasBin: true 1186 | 1187 | jsonfile@4.0.0: 1188 | resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} 1189 | 1190 | lilconfig@3.1.2: 1191 | resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} 1192 | engines: {node: '>=14'} 1193 | 1194 | lines-and-columns@1.2.4: 1195 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} 1196 | 1197 | load-tsconfig@0.2.5: 1198 | resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} 1199 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1200 | 1201 | locate-path@5.0.0: 1202 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} 1203 | engines: {node: '>=8'} 1204 | 1205 | lodash.sortby@4.7.0: 1206 | resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} 1207 | 1208 | lodash.startcase@4.4.0: 1209 | resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} 1210 | 1211 | loupe@3.1.2: 1212 | resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} 1213 | 1214 | lru-cache@10.4.3: 1215 | resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} 1216 | 1217 | lru-cache@4.1.5: 1218 | resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} 1219 | 1220 | magic-string@0.25.9: 1221 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} 1222 | 1223 | magic-string@0.30.12: 1224 | resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} 1225 | 1226 | merge-stream@2.0.0: 1227 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 1228 | 1229 | merge2@1.4.1: 1230 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1231 | engines: {node: '>= 8'} 1232 | 1233 | micromatch@4.0.8: 1234 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1235 | engines: {node: '>=8.6'} 1236 | 1237 | mime@3.0.0: 1238 | resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} 1239 | engines: {node: '>=10.0.0'} 1240 | hasBin: true 1241 | 1242 | mimic-fn@2.1.0: 1243 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} 1244 | engines: {node: '>=6'} 1245 | 1246 | miniflare@3.20241004.0: 1247 | resolution: {integrity: sha512-QSSmCR2V1AJnnpYwlyLXobKLSGiY1FlAiZYULMdGgOUThV7HJeSysDxsmPmrH+D4GQbmUERnmDdB6M6Rrz7uPg==} 1248 | engines: {node: '>=16.13'} 1249 | hasBin: true 1250 | 1251 | minimatch@9.0.5: 1252 | resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1253 | engines: {node: '>=16 || 14 >=14.17'} 1254 | 1255 | minipass@7.1.2: 1256 | resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} 1257 | engines: {node: '>=16 || 14 >=14.17'} 1258 | 1259 | mri@1.2.0: 1260 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 1261 | engines: {node: '>=4'} 1262 | 1263 | ms@2.1.3: 1264 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1265 | 1266 | mustache@4.2.0: 1267 | resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} 1268 | hasBin: true 1269 | 1270 | mz@2.7.0: 1271 | resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} 1272 | 1273 | nanoid@3.3.7: 1274 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 1275 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1276 | hasBin: true 1277 | 1278 | node-forge@1.3.1: 1279 | resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} 1280 | engines: {node: '>= 6.13.0'} 1281 | 1282 | normalize-path@3.0.0: 1283 | resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} 1284 | engines: {node: '>=0.10.0'} 1285 | 1286 | npm-run-path@4.0.1: 1287 | resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} 1288 | engines: {node: '>=8'} 1289 | 1290 | object-assign@4.1.1: 1291 | resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} 1292 | engines: {node: '>=0.10.0'} 1293 | 1294 | ohash@1.1.4: 1295 | resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} 1296 | 1297 | onetime@5.1.2: 1298 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} 1299 | engines: {node: '>=6'} 1300 | 1301 | os-tmpdir@1.0.2: 1302 | resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} 1303 | engines: {node: '>=0.10.0'} 1304 | 1305 | outdent@0.5.0: 1306 | resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} 1307 | 1308 | p-filter@2.1.0: 1309 | resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} 1310 | engines: {node: '>=8'} 1311 | 1312 | p-limit@2.3.0: 1313 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} 1314 | engines: {node: '>=6'} 1315 | 1316 | p-locate@4.1.0: 1317 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} 1318 | engines: {node: '>=8'} 1319 | 1320 | p-map@2.1.0: 1321 | resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} 1322 | engines: {node: '>=6'} 1323 | 1324 | p-try@2.2.0: 1325 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} 1326 | engines: {node: '>=6'} 1327 | 1328 | package-json-from-dist@1.0.1: 1329 | resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} 1330 | 1331 | package-manager-detector@0.2.2: 1332 | resolution: {integrity: sha512-VgXbyrSNsml4eHWIvxxG/nTL4wgybMTXCV2Un/+yEc3aDKKU6nQBZjbeP3Pl3qm9Qg92X/1ng4ffvCeD/zwHgg==} 1333 | 1334 | path-exists@4.0.0: 1335 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1336 | engines: {node: '>=8'} 1337 | 1338 | path-key@3.1.1: 1339 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1340 | engines: {node: '>=8'} 1341 | 1342 | path-parse@1.0.7: 1343 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1344 | 1345 | path-scurry@1.11.1: 1346 | resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} 1347 | engines: {node: '>=16 || 14 >=14.18'} 1348 | 1349 | path-to-regexp@6.3.0: 1350 | resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} 1351 | 1352 | path-type@4.0.0: 1353 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1354 | engines: {node: '>=8'} 1355 | 1356 | pathe@1.1.2: 1357 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} 1358 | 1359 | pathval@2.0.0: 1360 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} 1361 | engines: {node: '>= 14.16'} 1362 | 1363 | picocolors@1.1.0: 1364 | resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} 1365 | 1366 | picomatch@2.3.1: 1367 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1368 | engines: {node: '>=8.6'} 1369 | 1370 | picomatch@4.0.2: 1371 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1372 | engines: {node: '>=12'} 1373 | 1374 | pify@4.0.1: 1375 | resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} 1376 | engines: {node: '>=6'} 1377 | 1378 | pirates@4.0.6: 1379 | resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} 1380 | engines: {node: '>= 6'} 1381 | 1382 | postcss-load-config@6.0.1: 1383 | resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} 1384 | engines: {node: '>= 18'} 1385 | peerDependencies: 1386 | jiti: '>=1.21.0' 1387 | postcss: '>=8.0.9' 1388 | tsx: ^4.8.1 1389 | yaml: ^2.4.2 1390 | peerDependenciesMeta: 1391 | jiti: 1392 | optional: true 1393 | postcss: 1394 | optional: true 1395 | tsx: 1396 | optional: true 1397 | yaml: 1398 | optional: true 1399 | 1400 | postcss@8.4.47: 1401 | resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} 1402 | engines: {node: ^10 || ^12 || >=14} 1403 | 1404 | prettier@2.8.8: 1405 | resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} 1406 | engines: {node: '>=10.13.0'} 1407 | hasBin: true 1408 | 1409 | printable-characters@1.0.42: 1410 | resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} 1411 | 1412 | pseudomap@1.0.2: 1413 | resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} 1414 | 1415 | punycode@2.3.1: 1416 | resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1417 | engines: {node: '>=6'} 1418 | 1419 | queue-microtask@1.2.3: 1420 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1421 | 1422 | read-yaml-file@1.1.0: 1423 | resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} 1424 | engines: {node: '>=6'} 1425 | 1426 | readdirp@3.6.0: 1427 | resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} 1428 | engines: {node: '>=8.10.0'} 1429 | 1430 | regenerator-runtime@0.14.1: 1431 | resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} 1432 | 1433 | resolve-from@5.0.0: 1434 | resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} 1435 | engines: {node: '>=8'} 1436 | 1437 | resolve.exports@2.0.2: 1438 | resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} 1439 | engines: {node: '>=10'} 1440 | 1441 | resolve@1.22.8: 1442 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1443 | hasBin: true 1444 | 1445 | reusify@1.0.4: 1446 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1447 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1448 | 1449 | rollup-plugin-inject@3.0.2: 1450 | resolution: {integrity: sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==} 1451 | deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject. 1452 | 1453 | rollup-plugin-node-polyfills@0.2.1: 1454 | resolution: {integrity: sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==} 1455 | 1456 | rollup-pluginutils@2.8.2: 1457 | resolution: {integrity: sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==} 1458 | 1459 | rollup@4.24.0: 1460 | resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} 1461 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1462 | hasBin: true 1463 | 1464 | run-parallel@1.2.0: 1465 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1466 | 1467 | safer-buffer@2.1.2: 1468 | resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} 1469 | 1470 | selfsigned@2.4.1: 1471 | resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} 1472 | engines: {node: '>=10'} 1473 | 1474 | semver@7.6.3: 1475 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 1476 | engines: {node: '>=10'} 1477 | hasBin: true 1478 | 1479 | shebang-command@1.2.0: 1480 | resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} 1481 | engines: {node: '>=0.10.0'} 1482 | 1483 | shebang-command@2.0.0: 1484 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1485 | engines: {node: '>=8'} 1486 | 1487 | shebang-regex@1.0.0: 1488 | resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} 1489 | engines: {node: '>=0.10.0'} 1490 | 1491 | shebang-regex@3.0.0: 1492 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1493 | engines: {node: '>=8'} 1494 | 1495 | siginfo@2.0.0: 1496 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1497 | 1498 | signal-exit@3.0.7: 1499 | resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} 1500 | 1501 | signal-exit@4.1.0: 1502 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1503 | engines: {node: '>=14'} 1504 | 1505 | slash@3.0.0: 1506 | resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} 1507 | engines: {node: '>=8'} 1508 | 1509 | source-map-js@1.2.1: 1510 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1511 | engines: {node: '>=0.10.0'} 1512 | 1513 | source-map@0.6.1: 1514 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1515 | engines: {node: '>=0.10.0'} 1516 | 1517 | source-map@0.8.0-beta.0: 1518 | resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} 1519 | engines: {node: '>= 8'} 1520 | 1521 | sourcemap-codec@1.4.8: 1522 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 1523 | deprecated: Please use @jridgewell/sourcemap-codec instead 1524 | 1525 | spawndamnit@2.0.0: 1526 | resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} 1527 | 1528 | sprintf-js@1.0.3: 1529 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 1530 | 1531 | stackback@0.0.2: 1532 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1533 | 1534 | stacktracey@2.1.8: 1535 | resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} 1536 | 1537 | std-env@3.7.0: 1538 | resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} 1539 | 1540 | stoppable@1.1.0: 1541 | resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} 1542 | engines: {node: '>=4', npm: '>=6'} 1543 | 1544 | string-width@4.2.3: 1545 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} 1546 | engines: {node: '>=8'} 1547 | 1548 | string-width@5.1.2: 1549 | resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} 1550 | engines: {node: '>=12'} 1551 | 1552 | strip-ansi@6.0.1: 1553 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} 1554 | engines: {node: '>=8'} 1555 | 1556 | strip-ansi@7.1.0: 1557 | resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} 1558 | engines: {node: '>=12'} 1559 | 1560 | strip-bom@3.0.0: 1561 | resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} 1562 | engines: {node: '>=4'} 1563 | 1564 | strip-final-newline@2.0.0: 1565 | resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} 1566 | engines: {node: '>=6'} 1567 | 1568 | sucrase@3.35.0: 1569 | resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} 1570 | engines: {node: '>=16 || 14 >=14.17'} 1571 | hasBin: true 1572 | 1573 | supports-preserve-symlinks-flag@1.0.0: 1574 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1575 | engines: {node: '>= 0.4'} 1576 | 1577 | term-size@2.2.1: 1578 | resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} 1579 | engines: {node: '>=8'} 1580 | 1581 | thenify-all@1.6.0: 1582 | resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} 1583 | engines: {node: '>=0.8'} 1584 | 1585 | thenify@3.3.1: 1586 | resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} 1587 | 1588 | tinybench@2.9.0: 1589 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1590 | 1591 | tinyexec@0.3.0: 1592 | resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} 1593 | 1594 | tinyglobby@0.2.9: 1595 | resolution: {integrity: sha512-8or1+BGEdk1Zkkw2ii16qSS7uVrQJPre5A9o/XkWPATkk23FZh/15BKFxPnlTy6vkljZxLqYCzzBMj30ZrSvjw==} 1596 | engines: {node: '>=12.0.0'} 1597 | 1598 | tinypool@1.0.1: 1599 | resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} 1600 | engines: {node: ^18.0.0 || >=20.0.0} 1601 | 1602 | tinyrainbow@1.2.0: 1603 | resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} 1604 | engines: {node: '>=14.0.0'} 1605 | 1606 | tinyspy@3.0.2: 1607 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1608 | engines: {node: '>=14.0.0'} 1609 | 1610 | tmp@0.0.33: 1611 | resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} 1612 | engines: {node: '>=0.6.0'} 1613 | 1614 | to-regex-range@5.0.1: 1615 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1616 | engines: {node: '>=8.0'} 1617 | 1618 | tr46@1.0.1: 1619 | resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} 1620 | 1621 | tree-kill@1.2.2: 1622 | resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 1623 | hasBin: true 1624 | 1625 | ts-interface-checker@0.1.13: 1626 | resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} 1627 | 1628 | tslib@2.7.0: 1629 | resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} 1630 | 1631 | tsup@8.3.0: 1632 | resolution: {integrity: sha512-ALscEeyS03IomcuNdFdc0YWGVIkwH1Ws7nfTbAPuoILvEV2hpGQAY72LIOjglGo4ShWpZfpBqP/jpQVCzqYQag==} 1633 | engines: {node: '>=18'} 1634 | hasBin: true 1635 | peerDependencies: 1636 | '@microsoft/api-extractor': ^7.36.0 1637 | '@swc/core': ^1 1638 | postcss: ^8.4.12 1639 | typescript: '>=4.5.0' 1640 | peerDependenciesMeta: 1641 | '@microsoft/api-extractor': 1642 | optional: true 1643 | '@swc/core': 1644 | optional: true 1645 | postcss: 1646 | optional: true 1647 | typescript: 1648 | optional: true 1649 | 1650 | typescript@5.6.3: 1651 | resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} 1652 | engines: {node: '>=14.17'} 1653 | hasBin: true 1654 | 1655 | ufo@1.5.4: 1656 | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} 1657 | 1658 | undici-types@6.19.8: 1659 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 1660 | 1661 | undici@5.28.4: 1662 | resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} 1663 | engines: {node: '>=14.0'} 1664 | 1665 | unenv-nightly@2.0.0-20241009-125958-e8ea22f: 1666 | resolution: {integrity: sha512-hRxmKz1iSVRmuFx/vBdPsx7rX4o7Cas9vdjDNeUeWpQTK2LzU3Xy3Jz0zbo7MJX0bpqo/LEFCA+GPwsbl6zKEQ==} 1667 | 1668 | universalify@0.1.2: 1669 | resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} 1670 | engines: {node: '>= 4.0.0'} 1671 | 1672 | vite-node@2.1.3: 1673 | resolution: {integrity: sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==} 1674 | engines: {node: ^18.0.0 || >=20.0.0} 1675 | hasBin: true 1676 | 1677 | vite@5.4.9: 1678 | resolution: {integrity: sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==} 1679 | engines: {node: ^18.0.0 || >=20.0.0} 1680 | hasBin: true 1681 | peerDependencies: 1682 | '@types/node': ^18.0.0 || >=20.0.0 1683 | less: '*' 1684 | lightningcss: ^1.21.0 1685 | sass: '*' 1686 | sass-embedded: '*' 1687 | stylus: '*' 1688 | sugarss: '*' 1689 | terser: ^5.4.0 1690 | peerDependenciesMeta: 1691 | '@types/node': 1692 | optional: true 1693 | less: 1694 | optional: true 1695 | lightningcss: 1696 | optional: true 1697 | sass: 1698 | optional: true 1699 | sass-embedded: 1700 | optional: true 1701 | stylus: 1702 | optional: true 1703 | sugarss: 1704 | optional: true 1705 | terser: 1706 | optional: true 1707 | 1708 | vitest@2.1.3: 1709 | resolution: {integrity: sha512-Zrxbg/WiIvUP2uEzelDNTXmEMJXuzJ1kCpbDvaKByFA9MNeO95V+7r/3ti0qzJzrxdyuUw5VduN7k+D3VmVOSA==} 1710 | engines: {node: ^18.0.0 || >=20.0.0} 1711 | hasBin: true 1712 | peerDependencies: 1713 | '@edge-runtime/vm': '*' 1714 | '@types/node': ^18.0.0 || >=20.0.0 1715 | '@vitest/browser': 2.1.3 1716 | '@vitest/ui': 2.1.3 1717 | happy-dom: '*' 1718 | jsdom: '*' 1719 | peerDependenciesMeta: 1720 | '@edge-runtime/vm': 1721 | optional: true 1722 | '@types/node': 1723 | optional: true 1724 | '@vitest/browser': 1725 | optional: true 1726 | '@vitest/ui': 1727 | optional: true 1728 | happy-dom: 1729 | optional: true 1730 | jsdom: 1731 | optional: true 1732 | 1733 | webidl-conversions@4.0.2: 1734 | resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} 1735 | 1736 | whatwg-url@7.1.0: 1737 | resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} 1738 | 1739 | which@1.3.1: 1740 | resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} 1741 | hasBin: true 1742 | 1743 | which@2.0.2: 1744 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1745 | engines: {node: '>= 8'} 1746 | hasBin: true 1747 | 1748 | why-is-node-running@2.3.0: 1749 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1750 | engines: {node: '>=8'} 1751 | hasBin: true 1752 | 1753 | workerd@1.20241004.0: 1754 | resolution: {integrity: sha512-TCFJ7Zw7svR3adg1fnlPWj/yXhjBnQloLEIJqdu57hli/GsgwlbomwrbM3mdMgbS+K9zYeaYqknXiBN0EXk3QQ==} 1755 | engines: {node: '>=16'} 1756 | hasBin: true 1757 | 1758 | wrangler@3.80.4: 1759 | resolution: {integrity: sha512-DyNvShtVH3k7ZyBndlIiwyRDXqtHr3g01hxwn4FfwKlAaT6EL0wb3KL3UGbsdpeM/xbJiUQxFQ4WuFBWgZS18Q==} 1760 | engines: {node: '>=16.17.0'} 1761 | hasBin: true 1762 | peerDependencies: 1763 | '@cloudflare/workers-types': ^4.20241004.0 1764 | peerDependenciesMeta: 1765 | '@cloudflare/workers-types': 1766 | optional: true 1767 | 1768 | wrap-ansi@7.0.0: 1769 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} 1770 | engines: {node: '>=10'} 1771 | 1772 | wrap-ansi@8.1.0: 1773 | resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} 1774 | engines: {node: '>=12'} 1775 | 1776 | ws@8.18.0: 1777 | resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} 1778 | engines: {node: '>=10.0.0'} 1779 | peerDependencies: 1780 | bufferutil: ^4.0.1 1781 | utf-8-validate: '>=5.0.2' 1782 | peerDependenciesMeta: 1783 | bufferutil: 1784 | optional: true 1785 | utf-8-validate: 1786 | optional: true 1787 | 1788 | xxhash-wasm@1.0.2: 1789 | resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} 1790 | 1791 | yallist@2.1.2: 1792 | resolution: {integrity: sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==} 1793 | 1794 | youch@3.3.4: 1795 | resolution: {integrity: sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg==} 1796 | 1797 | zod@3.23.8: 1798 | resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} 1799 | 1800 | snapshots: 1801 | 1802 | '@babel/runtime@7.25.7': 1803 | dependencies: 1804 | regenerator-runtime: 0.14.1 1805 | 1806 | '@biomejs/biome@1.9.3': 1807 | optionalDependencies: 1808 | '@biomejs/cli-darwin-arm64': 1.9.3 1809 | '@biomejs/cli-darwin-x64': 1.9.3 1810 | '@biomejs/cli-linux-arm64': 1.9.3 1811 | '@biomejs/cli-linux-arm64-musl': 1.9.3 1812 | '@biomejs/cli-linux-x64': 1.9.3 1813 | '@biomejs/cli-linux-x64-musl': 1.9.3 1814 | '@biomejs/cli-win32-arm64': 1.9.3 1815 | '@biomejs/cli-win32-x64': 1.9.3 1816 | 1817 | '@biomejs/cli-darwin-arm64@1.9.3': 1818 | optional: true 1819 | 1820 | '@biomejs/cli-darwin-x64@1.9.3': 1821 | optional: true 1822 | 1823 | '@biomejs/cli-linux-arm64-musl@1.9.3': 1824 | optional: true 1825 | 1826 | '@biomejs/cli-linux-arm64@1.9.3': 1827 | optional: true 1828 | 1829 | '@biomejs/cli-linux-x64-musl@1.9.3': 1830 | optional: true 1831 | 1832 | '@biomejs/cli-linux-x64@1.9.3': 1833 | optional: true 1834 | 1835 | '@biomejs/cli-win32-arm64@1.9.3': 1836 | optional: true 1837 | 1838 | '@biomejs/cli-win32-x64@1.9.3': 1839 | optional: true 1840 | 1841 | '@changesets/apply-release-plan@7.0.5': 1842 | dependencies: 1843 | '@changesets/config': 3.0.3 1844 | '@changesets/get-version-range-type': 0.4.0 1845 | '@changesets/git': 3.0.1 1846 | '@changesets/should-skip-package': 0.1.1 1847 | '@changesets/types': 6.0.0 1848 | '@manypkg/get-packages': 1.1.3 1849 | detect-indent: 6.1.0 1850 | fs-extra: 7.0.1 1851 | lodash.startcase: 4.4.0 1852 | outdent: 0.5.0 1853 | prettier: 2.8.8 1854 | resolve-from: 5.0.0 1855 | semver: 7.6.3 1856 | 1857 | '@changesets/assemble-release-plan@6.0.4': 1858 | dependencies: 1859 | '@changesets/errors': 0.2.0 1860 | '@changesets/get-dependents-graph': 2.1.2 1861 | '@changesets/should-skip-package': 0.1.1 1862 | '@changesets/types': 6.0.0 1863 | '@manypkg/get-packages': 1.1.3 1864 | semver: 7.6.3 1865 | 1866 | '@changesets/changelog-git@0.2.0': 1867 | dependencies: 1868 | '@changesets/types': 6.0.0 1869 | 1870 | '@changesets/cli@2.27.9': 1871 | dependencies: 1872 | '@changesets/apply-release-plan': 7.0.5 1873 | '@changesets/assemble-release-plan': 6.0.4 1874 | '@changesets/changelog-git': 0.2.0 1875 | '@changesets/config': 3.0.3 1876 | '@changesets/errors': 0.2.0 1877 | '@changesets/get-dependents-graph': 2.1.2 1878 | '@changesets/get-release-plan': 4.0.4 1879 | '@changesets/git': 3.0.1 1880 | '@changesets/logger': 0.1.1 1881 | '@changesets/pre': 2.0.1 1882 | '@changesets/read': 0.6.1 1883 | '@changesets/should-skip-package': 0.1.1 1884 | '@changesets/types': 6.0.0 1885 | '@changesets/write': 0.3.2 1886 | '@manypkg/get-packages': 1.1.3 1887 | ansi-colors: 4.1.3 1888 | ci-info: 3.9.0 1889 | enquirer: 2.4.1 1890 | external-editor: 3.1.0 1891 | fs-extra: 7.0.1 1892 | mri: 1.2.0 1893 | p-limit: 2.3.0 1894 | package-manager-detector: 0.2.2 1895 | picocolors: 1.1.0 1896 | resolve-from: 5.0.0 1897 | semver: 7.6.3 1898 | spawndamnit: 2.0.0 1899 | term-size: 2.2.1 1900 | 1901 | '@changesets/config@3.0.3': 1902 | dependencies: 1903 | '@changesets/errors': 0.2.0 1904 | '@changesets/get-dependents-graph': 2.1.2 1905 | '@changesets/logger': 0.1.1 1906 | '@changesets/types': 6.0.0 1907 | '@manypkg/get-packages': 1.1.3 1908 | fs-extra: 7.0.1 1909 | micromatch: 4.0.8 1910 | 1911 | '@changesets/errors@0.2.0': 1912 | dependencies: 1913 | extendable-error: 0.1.7 1914 | 1915 | '@changesets/get-dependents-graph@2.1.2': 1916 | dependencies: 1917 | '@changesets/types': 6.0.0 1918 | '@manypkg/get-packages': 1.1.3 1919 | picocolors: 1.1.0 1920 | semver: 7.6.3 1921 | 1922 | '@changesets/get-release-plan@4.0.4': 1923 | dependencies: 1924 | '@changesets/assemble-release-plan': 6.0.4 1925 | '@changesets/config': 3.0.3 1926 | '@changesets/pre': 2.0.1 1927 | '@changesets/read': 0.6.1 1928 | '@changesets/types': 6.0.0 1929 | '@manypkg/get-packages': 1.1.3 1930 | 1931 | '@changesets/get-version-range-type@0.4.0': {} 1932 | 1933 | '@changesets/git@3.0.1': 1934 | dependencies: 1935 | '@changesets/errors': 0.2.0 1936 | '@manypkg/get-packages': 1.1.3 1937 | is-subdir: 1.2.0 1938 | micromatch: 4.0.8 1939 | spawndamnit: 2.0.0 1940 | 1941 | '@changesets/logger@0.1.1': 1942 | dependencies: 1943 | picocolors: 1.1.0 1944 | 1945 | '@changesets/parse@0.4.0': 1946 | dependencies: 1947 | '@changesets/types': 6.0.0 1948 | js-yaml: 3.14.1 1949 | 1950 | '@changesets/pre@2.0.1': 1951 | dependencies: 1952 | '@changesets/errors': 0.2.0 1953 | '@changesets/types': 6.0.0 1954 | '@manypkg/get-packages': 1.1.3 1955 | fs-extra: 7.0.1 1956 | 1957 | '@changesets/read@0.6.1': 1958 | dependencies: 1959 | '@changesets/git': 3.0.1 1960 | '@changesets/logger': 0.1.1 1961 | '@changesets/parse': 0.4.0 1962 | '@changesets/types': 6.0.0 1963 | fs-extra: 7.0.1 1964 | p-filter: 2.1.0 1965 | picocolors: 1.1.0 1966 | 1967 | '@changesets/should-skip-package@0.1.1': 1968 | dependencies: 1969 | '@changesets/types': 6.0.0 1970 | '@manypkg/get-packages': 1.1.3 1971 | 1972 | '@changesets/types@4.1.0': {} 1973 | 1974 | '@changesets/types@6.0.0': {} 1975 | 1976 | '@changesets/write@0.3.2': 1977 | dependencies: 1978 | '@changesets/types': 6.0.0 1979 | fs-extra: 7.0.1 1980 | human-id: 1.0.2 1981 | prettier: 2.8.8 1982 | 1983 | '@cloudflare/kv-asset-handler@0.3.4': 1984 | dependencies: 1985 | mime: 3.0.0 1986 | 1987 | '@cloudflare/vitest-pool-workers@0.5.18(@cloudflare/workers-types@4.20241011.0)(@vitest/runner@2.1.3)(@vitest/snapshot@2.1.3)(vitest@2.1.3(@edge-runtime/vm@4.0.3)(@types/node@22.7.5))': 1988 | dependencies: 1989 | '@vitest/runner': 2.1.3 1990 | '@vitest/snapshot': 2.1.3 1991 | birpc: 0.2.14 1992 | cjs-module-lexer: 1.4.1 1993 | devalue: 4.3.3 1994 | esbuild: 0.17.19 1995 | miniflare: 3.20241004.0 1996 | semver: 7.6.3 1997 | vitest: 2.1.3(@edge-runtime/vm@4.0.3)(@types/node@22.7.5) 1998 | wrangler: 3.80.4(@cloudflare/workers-types@4.20241011.0) 1999 | zod: 3.23.8 2000 | transitivePeerDependencies: 2001 | - '@cloudflare/workers-types' 2002 | - bufferutil 2003 | - supports-color 2004 | - utf-8-validate 2005 | 2006 | '@cloudflare/workerd-darwin-64@1.20241004.0': 2007 | optional: true 2008 | 2009 | '@cloudflare/workerd-darwin-arm64@1.20241004.0': 2010 | optional: true 2011 | 2012 | '@cloudflare/workerd-linux-64@1.20241004.0': 2013 | optional: true 2014 | 2015 | '@cloudflare/workerd-linux-arm64@1.20241004.0': 2016 | optional: true 2017 | 2018 | '@cloudflare/workerd-windows-64@1.20241004.0': 2019 | optional: true 2020 | 2021 | '@cloudflare/workers-shared@0.6.0': 2022 | dependencies: 2023 | mime: 3.0.0 2024 | zod: 3.23.8 2025 | 2026 | '@cloudflare/workers-types@4.20241011.0': {} 2027 | 2028 | '@cspotcode/source-map-support@0.8.1': 2029 | dependencies: 2030 | '@jridgewell/trace-mapping': 0.3.9 2031 | 2032 | '@edge-runtime/primitives@5.1.0': 2033 | optional: true 2034 | 2035 | '@edge-runtime/vm@4.0.3': 2036 | dependencies: 2037 | '@edge-runtime/primitives': 5.1.0 2038 | optional: true 2039 | 2040 | '@esbuild-plugins/node-globals-polyfill@0.2.3(esbuild@0.17.19)': 2041 | dependencies: 2042 | esbuild: 0.17.19 2043 | 2044 | '@esbuild-plugins/node-modules-polyfill@0.2.2(esbuild@0.17.19)': 2045 | dependencies: 2046 | esbuild: 0.17.19 2047 | escape-string-regexp: 4.0.0 2048 | rollup-plugin-node-polyfills: 0.2.1 2049 | 2050 | '@esbuild/aix-ppc64@0.21.5': 2051 | optional: true 2052 | 2053 | '@esbuild/aix-ppc64@0.23.1': 2054 | optional: true 2055 | 2056 | '@esbuild/android-arm64@0.17.19': 2057 | optional: true 2058 | 2059 | '@esbuild/android-arm64@0.21.5': 2060 | optional: true 2061 | 2062 | '@esbuild/android-arm64@0.23.1': 2063 | optional: true 2064 | 2065 | '@esbuild/android-arm@0.17.19': 2066 | optional: true 2067 | 2068 | '@esbuild/android-arm@0.21.5': 2069 | optional: true 2070 | 2071 | '@esbuild/android-arm@0.23.1': 2072 | optional: true 2073 | 2074 | '@esbuild/android-x64@0.17.19': 2075 | optional: true 2076 | 2077 | '@esbuild/android-x64@0.21.5': 2078 | optional: true 2079 | 2080 | '@esbuild/android-x64@0.23.1': 2081 | optional: true 2082 | 2083 | '@esbuild/darwin-arm64@0.17.19': 2084 | optional: true 2085 | 2086 | '@esbuild/darwin-arm64@0.21.5': 2087 | optional: true 2088 | 2089 | '@esbuild/darwin-arm64@0.23.1': 2090 | optional: true 2091 | 2092 | '@esbuild/darwin-x64@0.17.19': 2093 | optional: true 2094 | 2095 | '@esbuild/darwin-x64@0.21.5': 2096 | optional: true 2097 | 2098 | '@esbuild/darwin-x64@0.23.1': 2099 | optional: true 2100 | 2101 | '@esbuild/freebsd-arm64@0.17.19': 2102 | optional: true 2103 | 2104 | '@esbuild/freebsd-arm64@0.21.5': 2105 | optional: true 2106 | 2107 | '@esbuild/freebsd-arm64@0.23.1': 2108 | optional: true 2109 | 2110 | '@esbuild/freebsd-x64@0.17.19': 2111 | optional: true 2112 | 2113 | '@esbuild/freebsd-x64@0.21.5': 2114 | optional: true 2115 | 2116 | '@esbuild/freebsd-x64@0.23.1': 2117 | optional: true 2118 | 2119 | '@esbuild/linux-arm64@0.17.19': 2120 | optional: true 2121 | 2122 | '@esbuild/linux-arm64@0.21.5': 2123 | optional: true 2124 | 2125 | '@esbuild/linux-arm64@0.23.1': 2126 | optional: true 2127 | 2128 | '@esbuild/linux-arm@0.17.19': 2129 | optional: true 2130 | 2131 | '@esbuild/linux-arm@0.21.5': 2132 | optional: true 2133 | 2134 | '@esbuild/linux-arm@0.23.1': 2135 | optional: true 2136 | 2137 | '@esbuild/linux-ia32@0.17.19': 2138 | optional: true 2139 | 2140 | '@esbuild/linux-ia32@0.21.5': 2141 | optional: true 2142 | 2143 | '@esbuild/linux-ia32@0.23.1': 2144 | optional: true 2145 | 2146 | '@esbuild/linux-loong64@0.17.19': 2147 | optional: true 2148 | 2149 | '@esbuild/linux-loong64@0.21.5': 2150 | optional: true 2151 | 2152 | '@esbuild/linux-loong64@0.23.1': 2153 | optional: true 2154 | 2155 | '@esbuild/linux-mips64el@0.17.19': 2156 | optional: true 2157 | 2158 | '@esbuild/linux-mips64el@0.21.5': 2159 | optional: true 2160 | 2161 | '@esbuild/linux-mips64el@0.23.1': 2162 | optional: true 2163 | 2164 | '@esbuild/linux-ppc64@0.17.19': 2165 | optional: true 2166 | 2167 | '@esbuild/linux-ppc64@0.21.5': 2168 | optional: true 2169 | 2170 | '@esbuild/linux-ppc64@0.23.1': 2171 | optional: true 2172 | 2173 | '@esbuild/linux-riscv64@0.17.19': 2174 | optional: true 2175 | 2176 | '@esbuild/linux-riscv64@0.21.5': 2177 | optional: true 2178 | 2179 | '@esbuild/linux-riscv64@0.23.1': 2180 | optional: true 2181 | 2182 | '@esbuild/linux-s390x@0.17.19': 2183 | optional: true 2184 | 2185 | '@esbuild/linux-s390x@0.21.5': 2186 | optional: true 2187 | 2188 | '@esbuild/linux-s390x@0.23.1': 2189 | optional: true 2190 | 2191 | '@esbuild/linux-x64@0.17.19': 2192 | optional: true 2193 | 2194 | '@esbuild/linux-x64@0.21.5': 2195 | optional: true 2196 | 2197 | '@esbuild/linux-x64@0.23.1': 2198 | optional: true 2199 | 2200 | '@esbuild/netbsd-x64@0.17.19': 2201 | optional: true 2202 | 2203 | '@esbuild/netbsd-x64@0.21.5': 2204 | optional: true 2205 | 2206 | '@esbuild/netbsd-x64@0.23.1': 2207 | optional: true 2208 | 2209 | '@esbuild/openbsd-arm64@0.23.1': 2210 | optional: true 2211 | 2212 | '@esbuild/openbsd-x64@0.17.19': 2213 | optional: true 2214 | 2215 | '@esbuild/openbsd-x64@0.21.5': 2216 | optional: true 2217 | 2218 | '@esbuild/openbsd-x64@0.23.1': 2219 | optional: true 2220 | 2221 | '@esbuild/sunos-x64@0.17.19': 2222 | optional: true 2223 | 2224 | '@esbuild/sunos-x64@0.21.5': 2225 | optional: true 2226 | 2227 | '@esbuild/sunos-x64@0.23.1': 2228 | optional: true 2229 | 2230 | '@esbuild/win32-arm64@0.17.19': 2231 | optional: true 2232 | 2233 | '@esbuild/win32-arm64@0.21.5': 2234 | optional: true 2235 | 2236 | '@esbuild/win32-arm64@0.23.1': 2237 | optional: true 2238 | 2239 | '@esbuild/win32-ia32@0.17.19': 2240 | optional: true 2241 | 2242 | '@esbuild/win32-ia32@0.21.5': 2243 | optional: true 2244 | 2245 | '@esbuild/win32-ia32@0.23.1': 2246 | optional: true 2247 | 2248 | '@esbuild/win32-x64@0.17.19': 2249 | optional: true 2250 | 2251 | '@esbuild/win32-x64@0.21.5': 2252 | optional: true 2253 | 2254 | '@esbuild/win32-x64@0.23.1': 2255 | optional: true 2256 | 2257 | '@fastify/busboy@2.1.1': {} 2258 | 2259 | '@hono/zod-validator@0.4.1(hono@4.6.8)(zod@3.23.8)': 2260 | dependencies: 2261 | hono: 4.6.8 2262 | zod: 3.23.8 2263 | 2264 | '@isaacs/cliui@8.0.2': 2265 | dependencies: 2266 | string-width: 5.1.2 2267 | string-width-cjs: string-width@4.2.3 2268 | strip-ansi: 7.1.0 2269 | strip-ansi-cjs: strip-ansi@6.0.1 2270 | wrap-ansi: 8.1.0 2271 | wrap-ansi-cjs: wrap-ansi@7.0.0 2272 | 2273 | '@jridgewell/gen-mapping@0.3.5': 2274 | dependencies: 2275 | '@jridgewell/set-array': 1.2.1 2276 | '@jridgewell/sourcemap-codec': 1.5.0 2277 | '@jridgewell/trace-mapping': 0.3.25 2278 | 2279 | '@jridgewell/resolve-uri@3.1.2': {} 2280 | 2281 | '@jridgewell/set-array@1.2.1': {} 2282 | 2283 | '@jridgewell/sourcemap-codec@1.5.0': {} 2284 | 2285 | '@jridgewell/trace-mapping@0.3.25': 2286 | dependencies: 2287 | '@jridgewell/resolve-uri': 3.1.2 2288 | '@jridgewell/sourcemap-codec': 1.5.0 2289 | 2290 | '@jridgewell/trace-mapping@0.3.9': 2291 | dependencies: 2292 | '@jridgewell/resolve-uri': 3.1.2 2293 | '@jridgewell/sourcemap-codec': 1.5.0 2294 | 2295 | '@manypkg/find-root@1.1.0': 2296 | dependencies: 2297 | '@babel/runtime': 7.25.7 2298 | '@types/node': 12.20.55 2299 | find-up: 4.1.0 2300 | fs-extra: 8.1.0 2301 | 2302 | '@manypkg/get-packages@1.1.3': 2303 | dependencies: 2304 | '@babel/runtime': 7.25.7 2305 | '@changesets/types': 4.1.0 2306 | '@manypkg/find-root': 1.1.0 2307 | fs-extra: 8.1.0 2308 | globby: 11.1.0 2309 | read-yaml-file: 1.1.0 2310 | 2311 | '@nodelib/fs.scandir@2.1.5': 2312 | dependencies: 2313 | '@nodelib/fs.stat': 2.0.5 2314 | run-parallel: 1.2.0 2315 | 2316 | '@nodelib/fs.stat@2.0.5': {} 2317 | 2318 | '@nodelib/fs.walk@1.2.8': 2319 | dependencies: 2320 | '@nodelib/fs.scandir': 2.1.5 2321 | fastq: 1.17.1 2322 | 2323 | '@pkgjs/parseargs@0.11.0': 2324 | optional: true 2325 | 2326 | '@rollup/rollup-android-arm-eabi@4.24.0': 2327 | optional: true 2328 | 2329 | '@rollup/rollup-android-arm64@4.24.0': 2330 | optional: true 2331 | 2332 | '@rollup/rollup-darwin-arm64@4.24.0': 2333 | optional: true 2334 | 2335 | '@rollup/rollup-darwin-x64@4.24.0': 2336 | optional: true 2337 | 2338 | '@rollup/rollup-linux-arm-gnueabihf@4.24.0': 2339 | optional: true 2340 | 2341 | '@rollup/rollup-linux-arm-musleabihf@4.24.0': 2342 | optional: true 2343 | 2344 | '@rollup/rollup-linux-arm64-gnu@4.24.0': 2345 | optional: true 2346 | 2347 | '@rollup/rollup-linux-arm64-musl@4.24.0': 2348 | optional: true 2349 | 2350 | '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': 2351 | optional: true 2352 | 2353 | '@rollup/rollup-linux-riscv64-gnu@4.24.0': 2354 | optional: true 2355 | 2356 | '@rollup/rollup-linux-s390x-gnu@4.24.0': 2357 | optional: true 2358 | 2359 | '@rollup/rollup-linux-x64-gnu@4.24.0': 2360 | optional: true 2361 | 2362 | '@rollup/rollup-linux-x64-musl@4.24.0': 2363 | optional: true 2364 | 2365 | '@rollup/rollup-win32-arm64-msvc@4.24.0': 2366 | optional: true 2367 | 2368 | '@rollup/rollup-win32-ia32-msvc@4.24.0': 2369 | optional: true 2370 | 2371 | '@rollup/rollup-win32-x64-msvc@4.24.0': 2372 | optional: true 2373 | 2374 | '@types/estree@1.0.6': {} 2375 | 2376 | '@types/node-forge@1.3.11': 2377 | dependencies: 2378 | '@types/node': 22.7.5 2379 | 2380 | '@types/node@12.20.55': {} 2381 | 2382 | '@types/node@22.7.5': 2383 | dependencies: 2384 | undici-types: 6.19.8 2385 | 2386 | '@vitest/expect@2.1.3': 2387 | dependencies: 2388 | '@vitest/spy': 2.1.3 2389 | '@vitest/utils': 2.1.3 2390 | chai: 5.1.1 2391 | tinyrainbow: 1.2.0 2392 | 2393 | '@vitest/mocker@2.1.3(@vitest/spy@2.1.3)(vite@5.4.9(@types/node@22.7.5))': 2394 | dependencies: 2395 | '@vitest/spy': 2.1.3 2396 | estree-walker: 3.0.3 2397 | magic-string: 0.30.12 2398 | optionalDependencies: 2399 | vite: 5.4.9(@types/node@22.7.5) 2400 | 2401 | '@vitest/pretty-format@2.1.3': 2402 | dependencies: 2403 | tinyrainbow: 1.2.0 2404 | 2405 | '@vitest/runner@2.1.3': 2406 | dependencies: 2407 | '@vitest/utils': 2.1.3 2408 | pathe: 1.1.2 2409 | 2410 | '@vitest/snapshot@2.1.3': 2411 | dependencies: 2412 | '@vitest/pretty-format': 2.1.3 2413 | magic-string: 0.30.12 2414 | pathe: 1.1.2 2415 | 2416 | '@vitest/spy@2.1.3': 2417 | dependencies: 2418 | tinyspy: 3.0.2 2419 | 2420 | '@vitest/utils@2.1.3': 2421 | dependencies: 2422 | '@vitest/pretty-format': 2.1.3 2423 | loupe: 3.1.2 2424 | tinyrainbow: 1.2.0 2425 | 2426 | acorn-walk@8.3.4: 2427 | dependencies: 2428 | acorn: 8.12.1 2429 | 2430 | acorn@8.12.1: {} 2431 | 2432 | ansi-colors@4.1.3: {} 2433 | 2434 | ansi-regex@5.0.1: {} 2435 | 2436 | ansi-regex@6.1.0: {} 2437 | 2438 | ansi-styles@4.3.0: 2439 | dependencies: 2440 | color-convert: 2.0.1 2441 | 2442 | ansi-styles@6.2.1: {} 2443 | 2444 | any-promise@1.3.0: {} 2445 | 2446 | anymatch@3.1.3: 2447 | dependencies: 2448 | normalize-path: 3.0.0 2449 | picomatch: 2.3.1 2450 | 2451 | argparse@1.0.10: 2452 | dependencies: 2453 | sprintf-js: 1.0.3 2454 | 2455 | array-union@2.1.0: {} 2456 | 2457 | as-table@1.0.55: 2458 | dependencies: 2459 | printable-characters: 1.0.42 2460 | 2461 | assertion-error@2.0.1: {} 2462 | 2463 | balanced-match@1.0.2: {} 2464 | 2465 | better-path-resolve@1.0.0: 2466 | dependencies: 2467 | is-windows: 1.0.2 2468 | 2469 | binary-extensions@2.3.0: {} 2470 | 2471 | birpc@0.2.14: {} 2472 | 2473 | blake3-wasm@2.1.5: {} 2474 | 2475 | brace-expansion@2.0.1: 2476 | dependencies: 2477 | balanced-match: 1.0.2 2478 | 2479 | braces@3.0.3: 2480 | dependencies: 2481 | fill-range: 7.1.1 2482 | 2483 | bundle-require@5.0.0(esbuild@0.23.1): 2484 | dependencies: 2485 | esbuild: 0.23.1 2486 | load-tsconfig: 0.2.5 2487 | 2488 | cac@6.7.14: {} 2489 | 2490 | capnp-ts@0.7.0: 2491 | dependencies: 2492 | debug: 4.3.7 2493 | tslib: 2.7.0 2494 | transitivePeerDependencies: 2495 | - supports-color 2496 | 2497 | chai@5.1.1: 2498 | dependencies: 2499 | assertion-error: 2.0.1 2500 | check-error: 2.1.1 2501 | deep-eql: 5.0.2 2502 | loupe: 3.1.2 2503 | pathval: 2.0.0 2504 | 2505 | chardet@0.7.0: {} 2506 | 2507 | check-error@2.1.1: {} 2508 | 2509 | chokidar@3.6.0: 2510 | dependencies: 2511 | anymatch: 3.1.3 2512 | braces: 3.0.3 2513 | glob-parent: 5.1.2 2514 | is-binary-path: 2.1.0 2515 | is-glob: 4.0.3 2516 | normalize-path: 3.0.0 2517 | readdirp: 3.6.0 2518 | optionalDependencies: 2519 | fsevents: 2.3.3 2520 | 2521 | ci-info@3.9.0: {} 2522 | 2523 | cjs-module-lexer@1.4.1: {} 2524 | 2525 | color-convert@2.0.1: 2526 | dependencies: 2527 | color-name: 1.1.4 2528 | 2529 | color-name@1.1.4: {} 2530 | 2531 | commander@4.1.1: {} 2532 | 2533 | consola@3.2.3: {} 2534 | 2535 | cookie@0.7.2: {} 2536 | 2537 | cross-spawn@5.1.0: 2538 | dependencies: 2539 | lru-cache: 4.1.5 2540 | shebang-command: 1.2.0 2541 | which: 1.3.1 2542 | 2543 | cross-spawn@7.0.3: 2544 | dependencies: 2545 | path-key: 3.1.1 2546 | shebang-command: 2.0.0 2547 | which: 2.0.2 2548 | 2549 | data-uri-to-buffer@2.0.2: {} 2550 | 2551 | debug@4.3.7: 2552 | dependencies: 2553 | ms: 2.1.3 2554 | 2555 | deep-eql@5.0.2: {} 2556 | 2557 | defu@6.1.4: {} 2558 | 2559 | detect-indent@6.1.0: {} 2560 | 2561 | devalue@4.3.3: {} 2562 | 2563 | dir-glob@3.0.1: 2564 | dependencies: 2565 | path-type: 4.0.0 2566 | 2567 | eastasianwidth@0.2.0: {} 2568 | 2569 | emoji-regex@8.0.0: {} 2570 | 2571 | emoji-regex@9.2.2: {} 2572 | 2573 | enquirer@2.4.1: 2574 | dependencies: 2575 | ansi-colors: 4.1.3 2576 | strip-ansi: 6.0.1 2577 | 2578 | esbuild@0.17.19: 2579 | optionalDependencies: 2580 | '@esbuild/android-arm': 0.17.19 2581 | '@esbuild/android-arm64': 0.17.19 2582 | '@esbuild/android-x64': 0.17.19 2583 | '@esbuild/darwin-arm64': 0.17.19 2584 | '@esbuild/darwin-x64': 0.17.19 2585 | '@esbuild/freebsd-arm64': 0.17.19 2586 | '@esbuild/freebsd-x64': 0.17.19 2587 | '@esbuild/linux-arm': 0.17.19 2588 | '@esbuild/linux-arm64': 0.17.19 2589 | '@esbuild/linux-ia32': 0.17.19 2590 | '@esbuild/linux-loong64': 0.17.19 2591 | '@esbuild/linux-mips64el': 0.17.19 2592 | '@esbuild/linux-ppc64': 0.17.19 2593 | '@esbuild/linux-riscv64': 0.17.19 2594 | '@esbuild/linux-s390x': 0.17.19 2595 | '@esbuild/linux-x64': 0.17.19 2596 | '@esbuild/netbsd-x64': 0.17.19 2597 | '@esbuild/openbsd-x64': 0.17.19 2598 | '@esbuild/sunos-x64': 0.17.19 2599 | '@esbuild/win32-arm64': 0.17.19 2600 | '@esbuild/win32-ia32': 0.17.19 2601 | '@esbuild/win32-x64': 0.17.19 2602 | 2603 | esbuild@0.21.5: 2604 | optionalDependencies: 2605 | '@esbuild/aix-ppc64': 0.21.5 2606 | '@esbuild/android-arm': 0.21.5 2607 | '@esbuild/android-arm64': 0.21.5 2608 | '@esbuild/android-x64': 0.21.5 2609 | '@esbuild/darwin-arm64': 0.21.5 2610 | '@esbuild/darwin-x64': 0.21.5 2611 | '@esbuild/freebsd-arm64': 0.21.5 2612 | '@esbuild/freebsd-x64': 0.21.5 2613 | '@esbuild/linux-arm': 0.21.5 2614 | '@esbuild/linux-arm64': 0.21.5 2615 | '@esbuild/linux-ia32': 0.21.5 2616 | '@esbuild/linux-loong64': 0.21.5 2617 | '@esbuild/linux-mips64el': 0.21.5 2618 | '@esbuild/linux-ppc64': 0.21.5 2619 | '@esbuild/linux-riscv64': 0.21.5 2620 | '@esbuild/linux-s390x': 0.21.5 2621 | '@esbuild/linux-x64': 0.21.5 2622 | '@esbuild/netbsd-x64': 0.21.5 2623 | '@esbuild/openbsd-x64': 0.21.5 2624 | '@esbuild/sunos-x64': 0.21.5 2625 | '@esbuild/win32-arm64': 0.21.5 2626 | '@esbuild/win32-ia32': 0.21.5 2627 | '@esbuild/win32-x64': 0.21.5 2628 | 2629 | esbuild@0.23.1: 2630 | optionalDependencies: 2631 | '@esbuild/aix-ppc64': 0.23.1 2632 | '@esbuild/android-arm': 0.23.1 2633 | '@esbuild/android-arm64': 0.23.1 2634 | '@esbuild/android-x64': 0.23.1 2635 | '@esbuild/darwin-arm64': 0.23.1 2636 | '@esbuild/darwin-x64': 0.23.1 2637 | '@esbuild/freebsd-arm64': 0.23.1 2638 | '@esbuild/freebsd-x64': 0.23.1 2639 | '@esbuild/linux-arm': 0.23.1 2640 | '@esbuild/linux-arm64': 0.23.1 2641 | '@esbuild/linux-ia32': 0.23.1 2642 | '@esbuild/linux-loong64': 0.23.1 2643 | '@esbuild/linux-mips64el': 0.23.1 2644 | '@esbuild/linux-ppc64': 0.23.1 2645 | '@esbuild/linux-riscv64': 0.23.1 2646 | '@esbuild/linux-s390x': 0.23.1 2647 | '@esbuild/linux-x64': 0.23.1 2648 | '@esbuild/netbsd-x64': 0.23.1 2649 | '@esbuild/openbsd-arm64': 0.23.1 2650 | '@esbuild/openbsd-x64': 0.23.1 2651 | '@esbuild/sunos-x64': 0.23.1 2652 | '@esbuild/win32-arm64': 0.23.1 2653 | '@esbuild/win32-ia32': 0.23.1 2654 | '@esbuild/win32-x64': 0.23.1 2655 | 2656 | escape-string-regexp@4.0.0: {} 2657 | 2658 | esprima@4.0.1: {} 2659 | 2660 | estree-walker@0.6.1: {} 2661 | 2662 | estree-walker@3.0.3: 2663 | dependencies: 2664 | '@types/estree': 1.0.6 2665 | 2666 | execa@5.1.1: 2667 | dependencies: 2668 | cross-spawn: 7.0.3 2669 | get-stream: 6.0.1 2670 | human-signals: 2.1.0 2671 | is-stream: 2.0.1 2672 | merge-stream: 2.0.0 2673 | npm-run-path: 4.0.1 2674 | onetime: 5.1.2 2675 | signal-exit: 3.0.7 2676 | strip-final-newline: 2.0.0 2677 | 2678 | exit-hook@2.2.1: {} 2679 | 2680 | extendable-error@0.1.7: {} 2681 | 2682 | external-editor@3.1.0: 2683 | dependencies: 2684 | chardet: 0.7.0 2685 | iconv-lite: 0.4.24 2686 | tmp: 0.0.33 2687 | 2688 | fast-glob@3.3.2: 2689 | dependencies: 2690 | '@nodelib/fs.stat': 2.0.5 2691 | '@nodelib/fs.walk': 1.2.8 2692 | glob-parent: 5.1.2 2693 | merge2: 1.4.1 2694 | micromatch: 4.0.8 2695 | 2696 | fastq@1.17.1: 2697 | dependencies: 2698 | reusify: 1.0.4 2699 | 2700 | fdir@6.4.0(picomatch@4.0.2): 2701 | optionalDependencies: 2702 | picomatch: 4.0.2 2703 | 2704 | fill-range@7.1.1: 2705 | dependencies: 2706 | to-regex-range: 5.0.1 2707 | 2708 | find-up@4.1.0: 2709 | dependencies: 2710 | locate-path: 5.0.0 2711 | path-exists: 4.0.0 2712 | 2713 | foreground-child@3.3.0: 2714 | dependencies: 2715 | cross-spawn: 7.0.3 2716 | signal-exit: 4.1.0 2717 | 2718 | fs-extra@7.0.1: 2719 | dependencies: 2720 | graceful-fs: 4.2.11 2721 | jsonfile: 4.0.0 2722 | universalify: 0.1.2 2723 | 2724 | fs-extra@8.1.0: 2725 | dependencies: 2726 | graceful-fs: 4.2.11 2727 | jsonfile: 4.0.0 2728 | universalify: 0.1.2 2729 | 2730 | fsevents@2.3.3: 2731 | optional: true 2732 | 2733 | function-bind@1.1.2: {} 2734 | 2735 | get-source@2.0.12: 2736 | dependencies: 2737 | data-uri-to-buffer: 2.0.2 2738 | source-map: 0.6.1 2739 | 2740 | get-stream@6.0.1: {} 2741 | 2742 | glob-parent@5.1.2: 2743 | dependencies: 2744 | is-glob: 4.0.3 2745 | 2746 | glob-to-regexp@0.4.1: {} 2747 | 2748 | glob@10.4.5: 2749 | dependencies: 2750 | foreground-child: 3.3.0 2751 | jackspeak: 3.4.3 2752 | minimatch: 9.0.5 2753 | minipass: 7.1.2 2754 | package-json-from-dist: 1.0.1 2755 | path-scurry: 1.11.1 2756 | 2757 | globby@11.1.0: 2758 | dependencies: 2759 | array-union: 2.1.0 2760 | dir-glob: 3.0.1 2761 | fast-glob: 3.3.2 2762 | ignore: 5.3.2 2763 | merge2: 1.4.1 2764 | slash: 3.0.0 2765 | 2766 | graceful-fs@4.2.11: {} 2767 | 2768 | hasown@2.0.2: 2769 | dependencies: 2770 | function-bind: 1.1.2 2771 | 2772 | hono@4.6.8: {} 2773 | 2774 | human-id@1.0.2: {} 2775 | 2776 | human-signals@2.1.0: {} 2777 | 2778 | iconv-lite@0.4.24: 2779 | dependencies: 2780 | safer-buffer: 2.1.2 2781 | 2782 | ignore@5.3.2: {} 2783 | 2784 | is-binary-path@2.1.0: 2785 | dependencies: 2786 | binary-extensions: 2.3.0 2787 | 2788 | is-core-module@2.15.1: 2789 | dependencies: 2790 | hasown: 2.0.2 2791 | 2792 | is-extglob@2.1.1: {} 2793 | 2794 | is-fullwidth-code-point@3.0.0: {} 2795 | 2796 | is-glob@4.0.3: 2797 | dependencies: 2798 | is-extglob: 2.1.1 2799 | 2800 | is-number@7.0.0: {} 2801 | 2802 | is-stream@2.0.1: {} 2803 | 2804 | is-subdir@1.2.0: 2805 | dependencies: 2806 | better-path-resolve: 1.0.0 2807 | 2808 | is-windows@1.0.2: {} 2809 | 2810 | isexe@2.0.0: {} 2811 | 2812 | jackspeak@3.4.3: 2813 | dependencies: 2814 | '@isaacs/cliui': 8.0.2 2815 | optionalDependencies: 2816 | '@pkgjs/parseargs': 0.11.0 2817 | 2818 | joycon@3.1.1: {} 2819 | 2820 | js-yaml@3.14.1: 2821 | dependencies: 2822 | argparse: 1.0.10 2823 | esprima: 4.0.1 2824 | 2825 | jsonfile@4.0.0: 2826 | optionalDependencies: 2827 | graceful-fs: 4.2.11 2828 | 2829 | lilconfig@3.1.2: {} 2830 | 2831 | lines-and-columns@1.2.4: {} 2832 | 2833 | load-tsconfig@0.2.5: {} 2834 | 2835 | locate-path@5.0.0: 2836 | dependencies: 2837 | p-locate: 4.1.0 2838 | 2839 | lodash.sortby@4.7.0: {} 2840 | 2841 | lodash.startcase@4.4.0: {} 2842 | 2843 | loupe@3.1.2: {} 2844 | 2845 | lru-cache@10.4.3: {} 2846 | 2847 | lru-cache@4.1.5: 2848 | dependencies: 2849 | pseudomap: 1.0.2 2850 | yallist: 2.1.2 2851 | 2852 | magic-string@0.25.9: 2853 | dependencies: 2854 | sourcemap-codec: 1.4.8 2855 | 2856 | magic-string@0.30.12: 2857 | dependencies: 2858 | '@jridgewell/sourcemap-codec': 1.5.0 2859 | 2860 | merge-stream@2.0.0: {} 2861 | 2862 | merge2@1.4.1: {} 2863 | 2864 | micromatch@4.0.8: 2865 | dependencies: 2866 | braces: 3.0.3 2867 | picomatch: 2.3.1 2868 | 2869 | mime@3.0.0: {} 2870 | 2871 | mimic-fn@2.1.0: {} 2872 | 2873 | miniflare@3.20241004.0: 2874 | dependencies: 2875 | '@cspotcode/source-map-support': 0.8.1 2876 | acorn: 8.12.1 2877 | acorn-walk: 8.3.4 2878 | capnp-ts: 0.7.0 2879 | exit-hook: 2.2.1 2880 | glob-to-regexp: 0.4.1 2881 | stoppable: 1.1.0 2882 | undici: 5.28.4 2883 | workerd: 1.20241004.0 2884 | ws: 8.18.0 2885 | youch: 3.3.4 2886 | zod: 3.23.8 2887 | transitivePeerDependencies: 2888 | - bufferutil 2889 | - supports-color 2890 | - utf-8-validate 2891 | 2892 | minimatch@9.0.5: 2893 | dependencies: 2894 | brace-expansion: 2.0.1 2895 | 2896 | minipass@7.1.2: {} 2897 | 2898 | mri@1.2.0: {} 2899 | 2900 | ms@2.1.3: {} 2901 | 2902 | mustache@4.2.0: {} 2903 | 2904 | mz@2.7.0: 2905 | dependencies: 2906 | any-promise: 1.3.0 2907 | object-assign: 4.1.1 2908 | thenify-all: 1.6.0 2909 | 2910 | nanoid@3.3.7: {} 2911 | 2912 | node-forge@1.3.1: {} 2913 | 2914 | normalize-path@3.0.0: {} 2915 | 2916 | npm-run-path@4.0.1: 2917 | dependencies: 2918 | path-key: 3.1.1 2919 | 2920 | object-assign@4.1.1: {} 2921 | 2922 | ohash@1.1.4: {} 2923 | 2924 | onetime@5.1.2: 2925 | dependencies: 2926 | mimic-fn: 2.1.0 2927 | 2928 | os-tmpdir@1.0.2: {} 2929 | 2930 | outdent@0.5.0: {} 2931 | 2932 | p-filter@2.1.0: 2933 | dependencies: 2934 | p-map: 2.1.0 2935 | 2936 | p-limit@2.3.0: 2937 | dependencies: 2938 | p-try: 2.2.0 2939 | 2940 | p-locate@4.1.0: 2941 | dependencies: 2942 | p-limit: 2.3.0 2943 | 2944 | p-map@2.1.0: {} 2945 | 2946 | p-try@2.2.0: {} 2947 | 2948 | package-json-from-dist@1.0.1: {} 2949 | 2950 | package-manager-detector@0.2.2: {} 2951 | 2952 | path-exists@4.0.0: {} 2953 | 2954 | path-key@3.1.1: {} 2955 | 2956 | path-parse@1.0.7: {} 2957 | 2958 | path-scurry@1.11.1: 2959 | dependencies: 2960 | lru-cache: 10.4.3 2961 | minipass: 7.1.2 2962 | 2963 | path-to-regexp@6.3.0: {} 2964 | 2965 | path-type@4.0.0: {} 2966 | 2967 | pathe@1.1.2: {} 2968 | 2969 | pathval@2.0.0: {} 2970 | 2971 | picocolors@1.1.0: {} 2972 | 2973 | picomatch@2.3.1: {} 2974 | 2975 | picomatch@4.0.2: {} 2976 | 2977 | pify@4.0.1: {} 2978 | 2979 | pirates@4.0.6: {} 2980 | 2981 | postcss-load-config@6.0.1(postcss@8.4.47): 2982 | dependencies: 2983 | lilconfig: 3.1.2 2984 | optionalDependencies: 2985 | postcss: 8.4.47 2986 | 2987 | postcss@8.4.47: 2988 | dependencies: 2989 | nanoid: 3.3.7 2990 | picocolors: 1.1.0 2991 | source-map-js: 1.2.1 2992 | 2993 | prettier@2.8.8: {} 2994 | 2995 | printable-characters@1.0.42: {} 2996 | 2997 | pseudomap@1.0.2: {} 2998 | 2999 | punycode@2.3.1: {} 3000 | 3001 | queue-microtask@1.2.3: {} 3002 | 3003 | read-yaml-file@1.1.0: 3004 | dependencies: 3005 | graceful-fs: 4.2.11 3006 | js-yaml: 3.14.1 3007 | pify: 4.0.1 3008 | strip-bom: 3.0.0 3009 | 3010 | readdirp@3.6.0: 3011 | dependencies: 3012 | picomatch: 2.3.1 3013 | 3014 | regenerator-runtime@0.14.1: {} 3015 | 3016 | resolve-from@5.0.0: {} 3017 | 3018 | resolve.exports@2.0.2: {} 3019 | 3020 | resolve@1.22.8: 3021 | dependencies: 3022 | is-core-module: 2.15.1 3023 | path-parse: 1.0.7 3024 | supports-preserve-symlinks-flag: 1.0.0 3025 | 3026 | reusify@1.0.4: {} 3027 | 3028 | rollup-plugin-inject@3.0.2: 3029 | dependencies: 3030 | estree-walker: 0.6.1 3031 | magic-string: 0.25.9 3032 | rollup-pluginutils: 2.8.2 3033 | 3034 | rollup-plugin-node-polyfills@0.2.1: 3035 | dependencies: 3036 | rollup-plugin-inject: 3.0.2 3037 | 3038 | rollup-pluginutils@2.8.2: 3039 | dependencies: 3040 | estree-walker: 0.6.1 3041 | 3042 | rollup@4.24.0: 3043 | dependencies: 3044 | '@types/estree': 1.0.6 3045 | optionalDependencies: 3046 | '@rollup/rollup-android-arm-eabi': 4.24.0 3047 | '@rollup/rollup-android-arm64': 4.24.0 3048 | '@rollup/rollup-darwin-arm64': 4.24.0 3049 | '@rollup/rollup-darwin-x64': 4.24.0 3050 | '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 3051 | '@rollup/rollup-linux-arm-musleabihf': 4.24.0 3052 | '@rollup/rollup-linux-arm64-gnu': 4.24.0 3053 | '@rollup/rollup-linux-arm64-musl': 4.24.0 3054 | '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 3055 | '@rollup/rollup-linux-riscv64-gnu': 4.24.0 3056 | '@rollup/rollup-linux-s390x-gnu': 4.24.0 3057 | '@rollup/rollup-linux-x64-gnu': 4.24.0 3058 | '@rollup/rollup-linux-x64-musl': 4.24.0 3059 | '@rollup/rollup-win32-arm64-msvc': 4.24.0 3060 | '@rollup/rollup-win32-ia32-msvc': 4.24.0 3061 | '@rollup/rollup-win32-x64-msvc': 4.24.0 3062 | fsevents: 2.3.3 3063 | 3064 | run-parallel@1.2.0: 3065 | dependencies: 3066 | queue-microtask: 1.2.3 3067 | 3068 | safer-buffer@2.1.2: {} 3069 | 3070 | selfsigned@2.4.1: 3071 | dependencies: 3072 | '@types/node-forge': 1.3.11 3073 | node-forge: 1.3.1 3074 | 3075 | semver@7.6.3: {} 3076 | 3077 | shebang-command@1.2.0: 3078 | dependencies: 3079 | shebang-regex: 1.0.0 3080 | 3081 | shebang-command@2.0.0: 3082 | dependencies: 3083 | shebang-regex: 3.0.0 3084 | 3085 | shebang-regex@1.0.0: {} 3086 | 3087 | shebang-regex@3.0.0: {} 3088 | 3089 | siginfo@2.0.0: {} 3090 | 3091 | signal-exit@3.0.7: {} 3092 | 3093 | signal-exit@4.1.0: {} 3094 | 3095 | slash@3.0.0: {} 3096 | 3097 | source-map-js@1.2.1: {} 3098 | 3099 | source-map@0.6.1: {} 3100 | 3101 | source-map@0.8.0-beta.0: 3102 | dependencies: 3103 | whatwg-url: 7.1.0 3104 | 3105 | sourcemap-codec@1.4.8: {} 3106 | 3107 | spawndamnit@2.0.0: 3108 | dependencies: 3109 | cross-spawn: 5.1.0 3110 | signal-exit: 3.0.7 3111 | 3112 | sprintf-js@1.0.3: {} 3113 | 3114 | stackback@0.0.2: {} 3115 | 3116 | stacktracey@2.1.8: 3117 | dependencies: 3118 | as-table: 1.0.55 3119 | get-source: 2.0.12 3120 | 3121 | std-env@3.7.0: {} 3122 | 3123 | stoppable@1.1.0: {} 3124 | 3125 | string-width@4.2.3: 3126 | dependencies: 3127 | emoji-regex: 8.0.0 3128 | is-fullwidth-code-point: 3.0.0 3129 | strip-ansi: 6.0.1 3130 | 3131 | string-width@5.1.2: 3132 | dependencies: 3133 | eastasianwidth: 0.2.0 3134 | emoji-regex: 9.2.2 3135 | strip-ansi: 7.1.0 3136 | 3137 | strip-ansi@6.0.1: 3138 | dependencies: 3139 | ansi-regex: 5.0.1 3140 | 3141 | strip-ansi@7.1.0: 3142 | dependencies: 3143 | ansi-regex: 6.1.0 3144 | 3145 | strip-bom@3.0.0: {} 3146 | 3147 | strip-final-newline@2.0.0: {} 3148 | 3149 | sucrase@3.35.0: 3150 | dependencies: 3151 | '@jridgewell/gen-mapping': 0.3.5 3152 | commander: 4.1.1 3153 | glob: 10.4.5 3154 | lines-and-columns: 1.2.4 3155 | mz: 2.7.0 3156 | pirates: 4.0.6 3157 | ts-interface-checker: 0.1.13 3158 | 3159 | supports-preserve-symlinks-flag@1.0.0: {} 3160 | 3161 | term-size@2.2.1: {} 3162 | 3163 | thenify-all@1.6.0: 3164 | dependencies: 3165 | thenify: 3.3.1 3166 | 3167 | thenify@3.3.1: 3168 | dependencies: 3169 | any-promise: 1.3.0 3170 | 3171 | tinybench@2.9.0: {} 3172 | 3173 | tinyexec@0.3.0: {} 3174 | 3175 | tinyglobby@0.2.9: 3176 | dependencies: 3177 | fdir: 6.4.0(picomatch@4.0.2) 3178 | picomatch: 4.0.2 3179 | 3180 | tinypool@1.0.1: {} 3181 | 3182 | tinyrainbow@1.2.0: {} 3183 | 3184 | tinyspy@3.0.2: {} 3185 | 3186 | tmp@0.0.33: 3187 | dependencies: 3188 | os-tmpdir: 1.0.2 3189 | 3190 | to-regex-range@5.0.1: 3191 | dependencies: 3192 | is-number: 7.0.0 3193 | 3194 | tr46@1.0.1: 3195 | dependencies: 3196 | punycode: 2.3.1 3197 | 3198 | tree-kill@1.2.2: {} 3199 | 3200 | ts-interface-checker@0.1.13: {} 3201 | 3202 | tslib@2.7.0: {} 3203 | 3204 | tsup@8.3.0(postcss@8.4.47)(typescript@5.6.3): 3205 | dependencies: 3206 | bundle-require: 5.0.0(esbuild@0.23.1) 3207 | cac: 6.7.14 3208 | chokidar: 3.6.0 3209 | consola: 3.2.3 3210 | debug: 4.3.7 3211 | esbuild: 0.23.1 3212 | execa: 5.1.1 3213 | joycon: 3.1.1 3214 | picocolors: 1.1.0 3215 | postcss-load-config: 6.0.1(postcss@8.4.47) 3216 | resolve-from: 5.0.0 3217 | rollup: 4.24.0 3218 | source-map: 0.8.0-beta.0 3219 | sucrase: 3.35.0 3220 | tinyglobby: 0.2.9 3221 | tree-kill: 1.2.2 3222 | optionalDependencies: 3223 | postcss: 8.4.47 3224 | typescript: 5.6.3 3225 | transitivePeerDependencies: 3226 | - jiti 3227 | - supports-color 3228 | - tsx 3229 | - yaml 3230 | 3231 | typescript@5.6.3: {} 3232 | 3233 | ufo@1.5.4: {} 3234 | 3235 | undici-types@6.19.8: {} 3236 | 3237 | undici@5.28.4: 3238 | dependencies: 3239 | '@fastify/busboy': 2.1.1 3240 | 3241 | unenv-nightly@2.0.0-20241009-125958-e8ea22f: 3242 | dependencies: 3243 | defu: 6.1.4 3244 | ohash: 1.1.4 3245 | pathe: 1.1.2 3246 | ufo: 1.5.4 3247 | 3248 | universalify@0.1.2: {} 3249 | 3250 | vite-node@2.1.3(@types/node@22.7.5): 3251 | dependencies: 3252 | cac: 6.7.14 3253 | debug: 4.3.7 3254 | pathe: 1.1.2 3255 | vite: 5.4.9(@types/node@22.7.5) 3256 | transitivePeerDependencies: 3257 | - '@types/node' 3258 | - less 3259 | - lightningcss 3260 | - sass 3261 | - sass-embedded 3262 | - stylus 3263 | - sugarss 3264 | - supports-color 3265 | - terser 3266 | 3267 | vite@5.4.9(@types/node@22.7.5): 3268 | dependencies: 3269 | esbuild: 0.21.5 3270 | postcss: 8.4.47 3271 | rollup: 4.24.0 3272 | optionalDependencies: 3273 | '@types/node': 22.7.5 3274 | fsevents: 2.3.3 3275 | 3276 | vitest@2.1.3(@edge-runtime/vm@4.0.3)(@types/node@22.7.5): 3277 | dependencies: 3278 | '@vitest/expect': 2.1.3 3279 | '@vitest/mocker': 2.1.3(@vitest/spy@2.1.3)(vite@5.4.9(@types/node@22.7.5)) 3280 | '@vitest/pretty-format': 2.1.3 3281 | '@vitest/runner': 2.1.3 3282 | '@vitest/snapshot': 2.1.3 3283 | '@vitest/spy': 2.1.3 3284 | '@vitest/utils': 2.1.3 3285 | chai: 5.1.1 3286 | debug: 4.3.7 3287 | magic-string: 0.30.12 3288 | pathe: 1.1.2 3289 | std-env: 3.7.0 3290 | tinybench: 2.9.0 3291 | tinyexec: 0.3.0 3292 | tinypool: 1.0.1 3293 | tinyrainbow: 1.2.0 3294 | vite: 5.4.9(@types/node@22.7.5) 3295 | vite-node: 2.1.3(@types/node@22.7.5) 3296 | why-is-node-running: 2.3.0 3297 | optionalDependencies: 3298 | '@edge-runtime/vm': 4.0.3 3299 | '@types/node': 22.7.5 3300 | transitivePeerDependencies: 3301 | - less 3302 | - lightningcss 3303 | - msw 3304 | - sass 3305 | - sass-embedded 3306 | - stylus 3307 | - sugarss 3308 | - supports-color 3309 | - terser 3310 | 3311 | webidl-conversions@4.0.2: {} 3312 | 3313 | whatwg-url@7.1.0: 3314 | dependencies: 3315 | lodash.sortby: 4.7.0 3316 | tr46: 1.0.1 3317 | webidl-conversions: 4.0.2 3318 | 3319 | which@1.3.1: 3320 | dependencies: 3321 | isexe: 2.0.0 3322 | 3323 | which@2.0.2: 3324 | dependencies: 3325 | isexe: 2.0.0 3326 | 3327 | why-is-node-running@2.3.0: 3328 | dependencies: 3329 | siginfo: 2.0.0 3330 | stackback: 0.0.2 3331 | 3332 | workerd@1.20241004.0: 3333 | optionalDependencies: 3334 | '@cloudflare/workerd-darwin-64': 1.20241004.0 3335 | '@cloudflare/workerd-darwin-arm64': 1.20241004.0 3336 | '@cloudflare/workerd-linux-64': 1.20241004.0 3337 | '@cloudflare/workerd-linux-arm64': 1.20241004.0 3338 | '@cloudflare/workerd-windows-64': 1.20241004.0 3339 | 3340 | wrangler@3.80.4(@cloudflare/workers-types@4.20241011.0): 3341 | dependencies: 3342 | '@cloudflare/kv-asset-handler': 0.3.4 3343 | '@cloudflare/workers-shared': 0.6.0 3344 | '@esbuild-plugins/node-globals-polyfill': 0.2.3(esbuild@0.17.19) 3345 | '@esbuild-plugins/node-modules-polyfill': 0.2.2(esbuild@0.17.19) 3346 | blake3-wasm: 2.1.5 3347 | chokidar: 3.6.0 3348 | esbuild: 0.17.19 3349 | miniflare: 3.20241004.0 3350 | nanoid: 3.3.7 3351 | path-to-regexp: 6.3.0 3352 | resolve: 1.22.8 3353 | resolve.exports: 2.0.2 3354 | selfsigned: 2.4.1 3355 | source-map: 0.6.1 3356 | unenv: unenv-nightly@2.0.0-20241009-125958-e8ea22f 3357 | workerd: 1.20241004.0 3358 | xxhash-wasm: 1.0.2 3359 | optionalDependencies: 3360 | '@cloudflare/workers-types': 4.20241011.0 3361 | fsevents: 2.3.3 3362 | transitivePeerDependencies: 3363 | - bufferutil 3364 | - supports-color 3365 | - utf-8-validate 3366 | 3367 | wrap-ansi@7.0.0: 3368 | dependencies: 3369 | ansi-styles: 4.3.0 3370 | string-width: 4.2.3 3371 | strip-ansi: 6.0.1 3372 | 3373 | wrap-ansi@8.1.0: 3374 | dependencies: 3375 | ansi-styles: 6.2.1 3376 | string-width: 5.1.2 3377 | strip-ansi: 7.1.0 3378 | 3379 | ws@8.18.0: {} 3380 | 3381 | xxhash-wasm@1.0.2: {} 3382 | 3383 | yallist@2.1.2: {} 3384 | 3385 | youch@3.3.4: 3386 | dependencies: 3387 | cookie: 0.7.2 3388 | mustache: 4.2.0 3389 | stacktracey: 2.1.8 3390 | 3391 | zod@3.23.8: {} 3392 | -------------------------------------------------------------------------------- /src/broadcast-message.do.e2e.test.ts: -------------------------------------------------------------------------------- 1 | import { env, listDurableObjectIds, runInDurableObject } from 'cloudflare:test'; 2 | import { vi } from 'vitest'; 3 | import { BroadcastMessage, type BroadcastMessageOptions } from './broadcast-message.do'; 4 | import type { InternalBroadcastMessage } from './broadcast-message.do/internal'; 5 | 6 | describe('BroadcastMessage Durable Object', () => { 7 | beforeEach(() => { 8 | vi.useFakeTimers(); 9 | }); 10 | afterEach(() => { 11 | vi.useRealTimers(); 12 | vi.clearAllMocks(); 13 | vi.resetAllMocks(); 14 | }); 15 | 16 | describe('Initialization', () => { 17 | it('initializes and starts correctly', async () => { 18 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 19 | const stub = env.BROADCAST_MESSAGE.get(id); 20 | 21 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 22 | expect(instance).toBeInstanceOf(BroadcastMessage); 23 | expect(state.getWebSocketAutoResponse()).toEqual(instance.REQUEST_RESPONSE_PAIR); 24 | expect(instance.sessions.size).toBe(0); 25 | }); 26 | }); 27 | }); 28 | 29 | describe('Room Creation', () => { 30 | it('creates a room', async () => { 31 | const date = new Date(); 32 | vi.setSystemTime(date); 33 | 34 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 35 | const stub = env.BROADCAST_MESSAGE.get(id); 36 | 37 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 38 | const roomId = 'room1'; 39 | const uid = 'user1'; 40 | 41 | const ws = await instance.createRoom(roomId, uid); 42 | expect(ws).toBeInstanceOf(WebSocket); 43 | 44 | const alarm = await state.storage.getAlarm(); 45 | expect(alarm).toBe(date.getTime() + instance.INTERVAL); 46 | expect(instance.sessions.size).toBe(1); 47 | }); 48 | }); 49 | 50 | it('creates a webSocket from a request', async () => { 51 | const date = new Date(); 52 | vi.setSystemTime(date); 53 | 54 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 55 | const stub = env.BROADCAST_MESSAGE.get(id); 56 | 57 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 58 | const roomId = 'room1'; 59 | const uid = 'user1'; 60 | 61 | const request = new Request(`http://localhost/rooms/${roomId}?uid=${uid}`, { 62 | headers: { Upgrade: 'websocket' }, 63 | }); 64 | const res = await instance.fetch(request); 65 | 66 | expect(res.webSocket).toBeInstanceOf(WebSocket); 67 | const alarm = await state.storage.getAlarm(); 68 | expect(alarm).toBe(date.getTime() + instance.INTERVAL); 69 | expect(instance.sessions.size).toBe(1); 70 | }); 71 | }); 72 | }); 73 | 74 | describe('AUTO_CLOSE Handling', () => { 75 | it('sets alarm when AUTO_CLOSE is true', async () => { 76 | const date = new Date(); 77 | vi.setSystemTime(date); 78 | 79 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 80 | const stub = env.BROADCAST_MESSAGE.get(id); 81 | 82 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 83 | vi.spyOn(state.storage, 'setAlarm'); 84 | instance.options.autoClose = true; 85 | 86 | const roomId = 'room1'; 87 | const uid = 'user1'; 88 | await instance.createRoom(roomId, uid); 89 | 90 | expect(state.storage.setAlarm).toHaveBeenCalled(); 91 | expect(state.storage.setAlarm).toHaveBeenCalledWith(date.getTime() + instance.INTERVAL); 92 | }); 93 | }); 94 | 95 | it('does not set alarm when AUTO_CLOSE is false', async () => { 96 | const date = new Date(); 97 | vi.setSystemTime(date); 98 | 99 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 100 | const stub = env.BROADCAST_MESSAGE.get(id); 101 | 102 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 103 | vi.spyOn(state.storage, 'setAlarm'); 104 | instance.options.autoClose = false; 105 | 106 | const roomId = 'room1'; 107 | const uid = 'user1'; 108 | await instance.createRoom(roomId, uid); 109 | 110 | expect(state.storage.setAlarm).not.toHaveBeenCalled(); 111 | }); 112 | }); 113 | }); 114 | 115 | describe('WebSocket State Serialization', () => { 116 | it('serializes WebSocket state correctly', async () => { 117 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 118 | const stub = env.BROADCAST_MESSAGE.get(id); 119 | const date = new Date(); 120 | vi.setSystemTime(date); 121 | 122 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage) => { 123 | const roomId = 'room1'; 124 | const uid = 'user1'; 125 | await instance.createRoom(roomId, uid); 126 | const ws = Array.from(instance.sessions.values()).at(0)!; 127 | 128 | const state = ws.deserializeAttachment(); 129 | expect(state).toEqual({ 130 | roomId, 131 | uid, 132 | connectedAt: date, 133 | }); 134 | }); 135 | }); 136 | }); 137 | 138 | describe('Broadcast Messages', () => { 139 | it.each([ 140 | { excludes: true, uid: [], message: 'test message', calledTimes: 0 }, 141 | { excludes: false, uid: ['user2'], message: 'test message', calledTimes: 0 }, 142 | { excludes: false, uid: ['user1'], message: 'test message', calledTimes: 1 }, 143 | { excludes: false, uid: [], message: 'test message', calledTimes: 1 }, 144 | ])('broadcasts messages correctly', async ({ excludes, uid, message, calledTimes }) => { 145 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 146 | const stub = env.BROADCAST_MESSAGE.get(id); 147 | 148 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage) => { 149 | await instance.createRoom('room1', 'user1'); 150 | const server = Array.from(instance.sessions.values()).at(0)!; 151 | vi.spyOn(server, 'send'); 152 | 153 | if (excludes) { 154 | instance.broadcast(message, { excludes: [server] }); 155 | } else { 156 | instance.broadcast(message, { uid }); 157 | } 158 | expect(server.send).toHaveBeenCalledTimes(calledTimes); 159 | }); 160 | }); 161 | }); 162 | 163 | describe('WebSocket Aliveness Check', () => { 164 | it.each([ 165 | { description: 'checks if a WebSocket is alive', offset: () => 0, expected: true }, 166 | { description: 'detects expired WebSocket', offset: (timeout: number) => timeout + 1, expected: false }, 167 | ])('$description', async ({ offset, expected }) => { 168 | const date = new Date(); 169 | vi.setSystemTime(date); 170 | 171 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 172 | const stub = env.BROADCAST_MESSAGE.get(id); 173 | 174 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 175 | await instance.createRoom('room1', 'user1'); 176 | const ws = Array.from(instance.sessions.values()).at(0)!; 177 | 178 | const offsetTime = offset(instance.TIMEOUT); 179 | vi.setSystemTime(new Date(date.getTime() + offsetTime)); 180 | 181 | expect(instance.isAliveSocket(ws)).toBe(expected); 182 | }); 183 | }); 184 | 185 | it.each([ 186 | { description: 'checks WebSocket aliveness with ping', offset: () => 0, expected: true }, 187 | { 188 | description: 'detects expired WebSocket with ping', 189 | offset: (timeout: number) => -timeout - 1, 190 | expected: false, 191 | }, 192 | ])('$description', async ({ offset, expected }) => { 193 | const date = new Date(); 194 | vi.setSystemTime(date); 195 | 196 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 197 | const stub = env.BROADCAST_MESSAGE.get(id); 198 | 199 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 200 | await instance.createRoom('room1', 'user1'); 201 | const ws = Array.from(instance.sessions.values()).at(0)!; 202 | 203 | const offsetTime = offset(instance.TIMEOUT); 204 | vi.spyOn(state, 'getWebSocketAutoResponseTimestamp').mockReturnValue(new Date(date.getTime() + offsetTime)); 205 | 206 | expect(instance.isAliveSocket(ws)).toBe(expected); 207 | }); 208 | }); 209 | }); 210 | 211 | describe('WebSocket Message Handling', () => { 212 | it('handles WebSocket messages correctly', async () => { 213 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 214 | const stub = env.BROADCAST_MESSAGE.get(id); 215 | 216 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage) => { 217 | await instance.createRoom('room1', 'user1'); 218 | const server = Array.from(instance.sessions.values()).at(0)!; 219 | vi.spyOn(instance, 'broadcast'); 220 | 221 | await instance.webSocketMessage?.(server, 'message'); 222 | expect(instance.broadcast).toHaveBeenCalledWith('message'); 223 | }); 224 | }); 225 | }); 226 | 227 | describe('Alarm Handling', () => { 228 | it('resets alarm correctly', async () => { 229 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 230 | const stub = env.BROADCAST_MESSAGE.get(id); 231 | 232 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 233 | vi.spyOn(state.storage, 'setAlarm'); 234 | 235 | await instance.createRoom('room1', 'user1'); 236 | await instance.alarm?.(); 237 | expect(state.storage.setAlarm).toHaveBeenCalled(); 238 | expect(state.storage.setAlarm).toHaveBeenCalledWith(Date.now() + instance.INTERVAL); 239 | }); 240 | }); 241 | }); 242 | 243 | describe('Durable Object IDs', () => { 244 | it('lists durable object IDs', async () => { 245 | let ids = await listDurableObjectIds(env.BROADCAST_MESSAGE); 246 | expect(ids.length).toBe(0); 247 | 248 | const id = await env.BROADCAST_MESSAGE.newUniqueId(); 249 | const stub = env.BROADCAST_MESSAGE.get(id); 250 | const req = new Request('http://localhost/rooms/room1?uid=user1', { 251 | headers: { 252 | Upgrade: 'websocket', 253 | }, 254 | }); 255 | await stub.fetch(req); 256 | 257 | ids = await listDurableObjectIds(env.BROADCAST_MESSAGE); 258 | expect(ids.length).toBe(1); 259 | }); 260 | }); 261 | }); 262 | 263 | describe('BroadcastMessage Durable Object with Options', () => { 264 | beforeEach(() => { 265 | vi.useFakeTimers(); 266 | }); 267 | afterEach(() => { 268 | vi.useRealTimers(); 269 | vi.clearAllMocks(); 270 | vi.resetAllMocks(); 271 | }); 272 | 273 | const createStubWithOptions = async (options: BroadcastMessageOptions) => { 274 | const id = env.BROADCAST_MESSAGE.newUniqueId(); 275 | const stub = env.BROADCAST_MESSAGE.get(id); 276 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage) => { 277 | Object.assign(instance.options, options); 278 | }); 279 | return stub; 280 | }; 281 | 282 | describe('autoClose Option', () => { 283 | it('sets alarm when autoClose is true', async () => { 284 | const date = new Date(); 285 | vi.setSystemTime(date); 286 | 287 | const stub = await createStubWithOptions({ autoClose: true }); 288 | 289 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 290 | vi.spyOn(state.storage, 'setAlarm'); 291 | 292 | await instance.createRoom('room1', 'user1'); 293 | expect(state.storage.setAlarm).toHaveBeenCalledWith(date.getTime() + instance.INTERVAL); 294 | }); 295 | }); 296 | 297 | it('does not set alarm when autoClose is false', async () => { 298 | const date = new Date(); 299 | vi.setSystemTime(date); 300 | 301 | const stub = await createStubWithOptions({ autoClose: false }); 302 | 303 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 304 | vi.spyOn(state.storage, 'setAlarm'); 305 | 306 | await instance.createRoom('room1', 'user1'); 307 | expect(state.storage.setAlarm).not.toHaveBeenCalled(); 308 | }); 309 | }); 310 | }); 311 | 312 | describe('interval Option', () => { 313 | it('updates interval and sets alarm accordingly', async () => { 314 | const date = new Date(); 315 | vi.setSystemTime(date); 316 | 317 | const newInterval = 60000; 318 | const stub = await createStubWithOptions({ interval: newInterval }); 319 | 320 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 321 | vi.spyOn(state.storage, 'setAlarm'); 322 | 323 | await instance.createRoom('room1', 'user1'); 324 | expect(state.storage.setAlarm).toHaveBeenCalledWith(date.getTime() + newInterval); 325 | }); 326 | }); 327 | }); 328 | 329 | describe('timeout Option', () => { 330 | it('updates timeout and checks WebSocket aliveness accordingly', async () => { 331 | const date = new Date(); 332 | vi.setSystemTime(date); 333 | 334 | const newTimeout = 120000; 335 | const stub = await createStubWithOptions({ timeout: newTimeout }); 336 | 337 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 338 | await instance.createRoom('room1', 'user1'); 339 | const ws = Array.from(instance.sessions.values()).at(0)!; 340 | 341 | const offsetTime = newTimeout + 1; 342 | vi.setSystemTime(new Date(date.getTime() + offsetTime)); 343 | 344 | expect(instance.isAliveSocket(ws)).toBe(false); 345 | }); 346 | }); 347 | }); 348 | 349 | describe('requestResponsePair Option', () => { 350 | it('updates requestResponsePair and checks ping-pong messages', async () => { 351 | const date = new Date(); 352 | vi.setSystemTime(date); 353 | 354 | const newRequestResponsePair = { request: 'hello', response: 'world' }; 355 | const stub = await createStubWithOptions({ requestResponsePair: newRequestResponsePair }); 356 | 357 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage) => { 358 | expect(instance.REQUEST_RESPONSE_PAIR.request).toBe('hello'); 359 | expect(instance.REQUEST_RESPONSE_PAIR.response).toBe('world'); 360 | }); 361 | }); 362 | }); 363 | 364 | describe('Combination of Options', () => { 365 | it('handles a combination of options correctly', async () => { 366 | const date = new Date(); 367 | vi.setSystemTime(date); 368 | 369 | const options: BroadcastMessageOptions = { 370 | autoClose: true, 371 | interval: 45000, 372 | timeout: 90000, 373 | requestResponsePair: { request: 'ping', response: 'pong' }, 374 | }; 375 | const stub = await createStubWithOptions(options); 376 | 377 | await runInDurableObject(stub, async (instance: InternalBroadcastMessage, state) => { 378 | vi.spyOn(state.storage, 'setAlarm'); 379 | 380 | await instance.createRoom('room1', 'user1'); 381 | expect(state.storage.setAlarm).toHaveBeenCalledWith(date.getTime() + options.interval!); 382 | 383 | const ws = Array.from(instance.sessions.values()).at(0)!; 384 | const offsetTime = options.timeout! + 1; 385 | vi.setSystemTime(new Date(date.getTime() + offsetTime)); 386 | expect(instance.isAliveSocket(ws)).toBe(false); 387 | 388 | expect(instance.REQUEST_RESPONSE_PAIR.request).toBe('ping'); 389 | expect(instance.REQUEST_RESPONSE_PAIR.response).toBe('pong'); 390 | }); 391 | }); 392 | }); 393 | }); 394 | -------------------------------------------------------------------------------- /src/broadcast-message.do/app/app.e2e.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * undici fetch では `new Response(null, { status: 101 })` がエラーになるので `@cloudflare/vitest-pool-workers` に乗っかることにする 3 | * cf: https://leaysgur.github.io/posts/2023/04/19/150218/ 4 | **/ 5 | 6 | import { createApp } from '.'; 7 | 8 | const mockService = { 9 | createRoom: vi.fn(), 10 | }; 11 | 12 | const app = createApp(mockService); 13 | 14 | describe('Room Creation API', () => { 15 | beforeEach(() => { 16 | vi.clearAllMocks(); 17 | }); 18 | 19 | it('successfully creates a room and establishes a WebSocket connection', async () => { 20 | const mockWebSocket = new WebSocket('ws://example.com'); 21 | mockService.createRoom.mockResolvedValue(mockWebSocket); 22 | 23 | const response = await app.request('http://localhost/rooms/testRoom?uid=testUser', { 24 | headers: { 25 | Upgrade: 'websocket', 26 | }, 27 | }); 28 | 29 | expect(response.status).toBe(101); 30 | expect(response.webSocket).toBe(mockWebSocket); 31 | expect(mockService.createRoom).toHaveBeenCalledWith('testRoom', 'testUser'); 32 | }); 33 | 34 | it('returns 400 when uid query parameter is missing', async () => { 35 | const response = await app.request('http://localhost/rooms/testRoom', { 36 | headers: { 37 | Upgrade: 'websocket', 38 | }, 39 | }); 40 | 41 | expect(response.status).toBe(400); 42 | }); 43 | 44 | it('returns 400 when uid query parameter is invalid', async () => { 45 | const response = await app.request('http://localhost/rooms/testRoom?uid=', { 46 | headers: { 47 | Upgrade: 'websocket', 48 | }, 49 | }); 50 | 51 | expect(response.status).toBe(400); 52 | }); 53 | 54 | it('handles service error correctly', async () => { 55 | mockService.createRoom.mockRejectedValue(new Error('Service Error')); 56 | const response = await app.request('http://localhost/rooms/testRoom?uid=testUser', { 57 | headers: { 58 | Upgrade: 'websocket', 59 | }, 60 | }); 61 | 62 | expect(response.status).toBe(500); 63 | }); 64 | }); 65 | -------------------------------------------------------------------------------- /src/broadcast-message.do/app/index.ts: -------------------------------------------------------------------------------- 1 | import { zValidator } from '@hono/zod-validator'; 2 | import { Hono } from 'hono'; 3 | import { z } from 'zod'; 4 | 5 | type Service = { 6 | createRoom(roomId: string, uid: string): Promise; 7 | }; 8 | export const createApp = (service: Service) => { 9 | const app = new Hono(); 10 | 11 | return app.get('/rooms/:roomId', zValidator('query', z.object({ uid: z.string().min(1) })), async (c) => { 12 | const query = c.req.valid('query'); 13 | const webSocket = await service.createRoom(c.req.param('roomId'), query.uid); 14 | 15 | return new Response(null, { status: 101, webSocket }); 16 | }); 17 | }; 18 | -------------------------------------------------------------------------------- /src/broadcast-message.do/index.ts: -------------------------------------------------------------------------------- 1 | import { DurableObject } from 'cloudflare:workers'; 2 | import { createApp } from './app'; 3 | 4 | import type { Env } from 'hono'; 5 | import type { BroadcastMessageOptions, BroadcastOptions, WebSocketAttachment } from './types'; 6 | 7 | type BroadcastMessageAppType = ReturnType; 8 | class BroadcastMessage extends DurableObject { 9 | protected options: BroadcastMessageOptions = { 10 | autoClose: true, 11 | interval: 30 * 1000, 12 | timeout: 60 * 1000, 13 | requestResponsePair: { 14 | request: 'ping', 15 | response: 'pong', 16 | }, 17 | }; 18 | protected get AUTO_CLOSE() { 19 | return this.options.autoClose ?? true; 20 | } 21 | protected get INTERVAL() { 22 | return this.options.interval ?? 30 * 1000; 23 | } 24 | protected get TIMEOUT() { 25 | return this.options.timeout ?? 60 * 1000; 26 | } 27 | protected get REQUEST_RESPONSE_PAIR() { 28 | return new WebSocketRequestResponsePair( 29 | this.options.requestResponsePair?.request ?? 'ping', 30 | this.options.requestResponsePair?.response ?? 'pong', 31 | ); 32 | } 33 | 34 | protected sessions = new Set(); 35 | private app = createApp({ 36 | createRoom: this.createRoom.bind(this), 37 | }); 38 | 39 | constructor( 40 | public ctx: DurableObjectState, 41 | public env: E['Bindings'], 42 | ) { 43 | super(ctx, env); 44 | ctx.blockConcurrencyWhile(this.onStart.bind(this)); 45 | } 46 | 47 | protected async onStart(): Promise { 48 | this.ctx.setWebSocketAutoResponse(this.REQUEST_RESPONSE_PAIR); 49 | for (const ws of this.ctx.getWebSockets()) { 50 | this.sessions.add(ws); 51 | } 52 | } 53 | 54 | protected async createRoom(roomId: string, uid: string): Promise { 55 | const pair = new WebSocketPair(); 56 | const client = pair[0]; 57 | const server = pair[1]; 58 | 59 | this.ctx.acceptWebSocket(server); 60 | this.sessions.add(server); 61 | server.serializeAttachment({ 62 | roomId, 63 | uid, 64 | connectedAt: new Date(), 65 | } satisfies WebSocketAttachment); 66 | 67 | if (this.AUTO_CLOSE) { 68 | const alarm = await this.ctx.storage.getAlarm(); 69 | if (alarm === null) { 70 | await this.ctx.storage.setAlarm(Date.now() + this.INTERVAL); 71 | } 72 | } 73 | 74 | return client; 75 | } 76 | 77 | broadcast(message: string | ArrayBuffer, options: BroadcastOptions = {}): void { 78 | const { excludes = [], uid = [] } = options; 79 | 80 | for (const ws of this.ctx.getWebSockets()) { 81 | const state: WebSocketAttachment = ws.deserializeAttachment(); 82 | if (excludes.includes(ws)) continue; 83 | if (uid.length > 0 && !uid.includes(state.uid)) continue; 84 | 85 | ws.send(message); 86 | } 87 | } 88 | 89 | isAliveSocket(ws: WebSocket): boolean { 90 | const state: WebSocketAttachment = ws.deserializeAttachment(); 91 | const pingAt = this.ctx.getWebSocketAutoResponseTimestamp(ws); 92 | const responseAt = pingAt ?? state.connectedAt; 93 | 94 | return Date.now() - responseAt.getTime() < this.TIMEOUT; 95 | } 96 | 97 | webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void { 98 | this.broadcast(message); 99 | } 100 | 101 | webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean): void { 102 | this.sessions.delete(ws); 103 | } 104 | 105 | fetch(request: Request): Response | Promise { 106 | return this.app.request(request, undefined, this.env); 107 | } 108 | 109 | async alarm(): Promise { 110 | if (this.AUTO_CLOSE) { 111 | for (const ws of this.sessions) { 112 | if (!this.isAliveSocket(ws)) { 113 | ws.close(); 114 | this.sessions.delete(ws); 115 | } 116 | } 117 | 118 | const alarm = await this.ctx.storage.getAlarm(); 119 | if (this.sessions.size > 0 && alarm === null) { 120 | await this.ctx.storage.setAlarm(Date.now() + this.INTERVAL); 121 | } 122 | } 123 | } 124 | } 125 | 126 | export { 127 | BroadcastMessage, 128 | type BroadcastMessageOptions, 129 | type WebSocketAttachment, 130 | type BroadcastOptions, 131 | type BroadcastMessageAppType, 132 | }; 133 | -------------------------------------------------------------------------------- /src/broadcast-message.do/internal.ts: -------------------------------------------------------------------------------- 1 | import type { BroadcastMessageAppType, BroadcastMessageOptions, BroadcastOptions } from '.'; 2 | 3 | export interface InternalBroadcastMessage extends DurableObject { 4 | // constants 5 | readonly AUTO_CLOSE: boolean; 6 | readonly INTERVAL: number; 7 | readonly TIMEOUT: number; 8 | readonly REQUEST_RESPONSE_PAIR: WebSocketRequestResponsePair; 9 | 10 | // user custom options 11 | options: BroadcastMessageOptions; 12 | 13 | // internal state 14 | sessions: Set; 15 | app: BroadcastMessageAppType; 16 | 17 | // internal methods 18 | onStart(): Promise; 19 | createRoom(roomId: string, uid: string): Promise; 20 | 21 | // public methods 22 | broadcast(message: string, options?: BroadcastOptions): void; 23 | isAliveSocket(ws: WebSocket): boolean; 24 | } 25 | -------------------------------------------------------------------------------- /src/broadcast-message.do/types.ts: -------------------------------------------------------------------------------- 1 | type DeepPartial = { 2 | [K in keyof T]?: T[K] extends Record ? DeepPartial : T[K]; 3 | }; 4 | export type BroadcastMessageOptions = DeepPartial<{ 5 | autoClose: boolean; 6 | interval: number; 7 | timeout: number; 8 | requestResponsePair: { 9 | request: string; 10 | response: string; 11 | }; 12 | }>; 13 | export type WebSocketAttachment = { 14 | roomId: string; 15 | uid: string; 16 | connectedAt: Date; 17 | }; 18 | export type BroadcastOptions = { 19 | uid?: string[]; 20 | excludes?: WebSocket[]; 21 | }; 22 | -------------------------------------------------------------------------------- /src/client/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ping-websocket'; 2 | -------------------------------------------------------------------------------- /src/client/ping-websocket/index.ts: -------------------------------------------------------------------------------- 1 | type Subscription = () => void; 2 | type Options = { 3 | interval: number; 4 | ping: string; 5 | }; 6 | 7 | export const pingWebSocket = (ws: WebSocket, options?: Options): Subscription => { 8 | const id = setInterval( 9 | () => { 10 | ws.send(options?.ping ?? 'ping'); 11 | }, 12 | options?.interval ?? 10 * 1000, 13 | ); 14 | 15 | return () => { 16 | clearInterval(id); 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /src/client/ping-websocket/ping-websocket.unit.test.ts: -------------------------------------------------------------------------------- 1 | import { vi } from 'vitest'; 2 | import { pingWebSocket } from '.'; 3 | 4 | describe('pingWebSocket', () => { 5 | let ws: WebSocket; 6 | beforeEach(() => { 7 | // @ts-expect-error 8 | ws = { send: vi.fn() }; 9 | vi.useFakeTimers(); 10 | }); 11 | 12 | afterEach(() => { 13 | vi.useRealTimers(); 14 | }); 15 | 16 | it('should send "ping" message at default interval when no options are provided', () => { 17 | const subscription = pingWebSocket(ws); 18 | 19 | vi.advanceTimersByTime(10000); 20 | 21 | expect(ws.send).toHaveBeenCalledWith('ping'); 22 | expect(ws.send).toHaveBeenCalledTimes(1); 23 | 24 | vi.advanceTimersByTime(10000); 25 | 26 | expect(ws.send).toHaveBeenCalledTimes(2); 27 | 28 | subscription(); 29 | }); 30 | 31 | it('should send custom ping message at custom interval', () => { 32 | const options = { interval: 5000, ping: 'hello' }; 33 | const subscription = pingWebSocket(ws, options); 34 | 35 | vi.advanceTimersByTime(5000); 36 | 37 | expect(ws.send).toHaveBeenCalledWith('hello'); 38 | expect(ws.send).toHaveBeenCalledTimes(1); 39 | 40 | vi.advanceTimersByTime(5000); 41 | 42 | expect(ws.send).toHaveBeenCalledTimes(2); 43 | 44 | subscription(); 45 | }); 46 | 47 | it('should stop sending messages after subscription is called', () => { 48 | const subscription = pingWebSocket(ws); 49 | 50 | vi.advanceTimersByTime(10000); 51 | expect(ws.send).toHaveBeenCalledTimes(1); 52 | 53 | subscription(); 54 | 55 | vi.advanceTimersByTime(10000); 56 | 57 | expect(ws.send).toHaveBeenCalledTimes(1); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { zValidator } from '@hono/zod-validator'; 2 | import { Hono } from 'hono'; 3 | import { hc } from 'hono/client'; 4 | import { z } from 'zod'; 5 | import { upgrade } from './middleware/upgrade'; 6 | 7 | import type { BroadcastMessage, BroadcastMessageAppType } from './broadcast-message.do'; 8 | 9 | type Env = { 10 | Bindings: { 11 | BROADCAST_MESSAGE: DurableObjectNamespace; 12 | }; 13 | }; 14 | 15 | const app = new Hono(); 16 | 17 | const route = app 18 | .get('/rooms/:roomId', upgrade(), zValidator('query', z.object({ uid: z.string() })), async (c) => { 19 | const roomId = c.req.param('roomId'); 20 | const query = c.req.valid('query'); 21 | const id = c.env.BROADCAST_MESSAGE.idFromName(roomId); 22 | const stub = c.env.BROADCAST_MESSAGE.get(id); 23 | 24 | const client = hc(new URL('/', c.req.url).toString(), { 25 | fetch: stub.fetch.bind(stub), 26 | }); 27 | 28 | const res = await client.rooms[':roomId'].$get( 29 | { query: { uid: query.uid }, param: { roomId } }, 30 | { init: { headers: c.req.raw.headers } }, 31 | ); 32 | 33 | return new Response(null, { 34 | webSocket: res.webSocket, 35 | status: res.status, 36 | headers: res.headers, 37 | statusText: res.statusText, 38 | }); 39 | }) 40 | .post('/rooms/:roomId/broadcast', zValidator('json', z.object({ message: z.string() })), async (c) => { 41 | const roomId = c.req.param('roomId'); 42 | const id = c.env.BROADCAST_MESSAGE.idFromName(roomId); 43 | const stub = c.env.BROADCAST_MESSAGE.get(id); 44 | 45 | await stub.broadcast(c.req.valid('json').message); 46 | return c.json(null, 200); 47 | }); 48 | 49 | export type AppType = typeof route; 50 | export default app; 51 | export * from './broadcast-message.do'; 52 | -------------------------------------------------------------------------------- /src/middleware/upgrade/index.ts: -------------------------------------------------------------------------------- 1 | import type { Env } from 'hono'; 2 | import { createMiddleware } from 'hono/factory'; 3 | 4 | export const upgrade = () => { 5 | return createMiddleware(async (c, next) => { 6 | if (c.req.header('Upgrade') !== 'websocket') { 7 | return c.text('Expected websocket', { 8 | status: 426, 9 | statusText: 'Upgrade Required', 10 | }); 11 | } 12 | 13 | return next(); 14 | }); 15 | }; 16 | -------------------------------------------------------------------------------- /src/middleware/upgrade/upgrade.unit.test.ts: -------------------------------------------------------------------------------- 1 | import { Hono } from 'hono'; 2 | import { upgrade } from '.'; 3 | 4 | describe('Upgrade Middleware', () => { 5 | let app: Hono; 6 | 7 | beforeEach(() => { 8 | app = new Hono(); 9 | app.get('/', upgrade(), (c) => c.text('WebSocket connection established')); 10 | }); 11 | 12 | it('returns status 426 when Upgrade header is not websocket', async () => { 13 | const req = new Request('http://localhost/', { 14 | headers: { Upgrade: 'non-websocket' }, 15 | }); 16 | const res = await app.request(req); 17 | expect(res.status).toBe(426); 18 | expect(await res.text()).toBe('Expected websocket'); 19 | }); 20 | 21 | it('passes to the next middleware when Upgrade header is websocket', async () => { 22 | const req = new Request('http://localhost/', { 23 | headers: { Upgrade: 'websocket' }, 24 | }); 25 | const res = await app.request(req); 26 | expect(res.status).toBe(200); 27 | expect(await res.text()).toBe('WebSocket connection established'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "ESNext", 5 | "moduleResolution": "Bundler", 6 | "strict": true, 7 | "skipLibCheck": true, 8 | "lib": ["ESNext"], 9 | "types": ["@cloudflare/workers-types", "vitest/globals", "@cloudflare/vitest-pool-workers"], 10 | "jsx": "react-jsx", 11 | "jsxImportSource": "hono/jsx" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: { 5 | index: 'src/broadcast-message.do/index.ts', 6 | 'helpers/upgrade': 'src/middleware/upgrade/index.ts', 7 | 'helpers/client': 'src/client/index.ts', 8 | }, 9 | external: ['hono', /cloudflare:/], 10 | format: ['cjs', 'esm'], 11 | clean: true, 12 | sourcemap: true, 13 | dts: { 14 | banner: "/// ", 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /types/index.d.ts: -------------------------------------------------------------------------------- 1 | interface CfEnv { 2 | BROADCAST_MESSAGE: DurableObjectNamespace; 3 | } 4 | 5 | declare module 'cloudflare:test' { 6 | interface ProvidedEnv extends CfEnv {} 7 | } 8 | -------------------------------------------------------------------------------- /vitest.workspace.ts: -------------------------------------------------------------------------------- 1 | import { defineWorkersProject } from '@cloudflare/vitest-pool-workers/config'; 2 | import { defineConfig, defineWorkspace } from 'vitest/config'; 3 | 4 | export default defineWorkspace([ 5 | defineConfig({ 6 | test: { 7 | globals: true, 8 | name: 'unit', 9 | include: ['**/*.unit.test.ts'], 10 | }, 11 | }), 12 | defineWorkersProject({ 13 | esbuild: { 14 | target: 'ES2022', 15 | }, 16 | test: { 17 | globals: true, 18 | name: 'e2e', 19 | include: ['**/*.e2e.test.ts'], 20 | poolOptions: { 21 | workers: { 22 | singleWorker: true, 23 | miniflare: { 24 | compatibilityFlags: ['nodejs_compat', 'service_binding_extra_handlers'], 25 | }, 26 | wrangler: { 27 | configPath: './wrangler.toml', 28 | environment: 'test', 29 | }, 30 | }, 31 | }, 32 | }, 33 | }), 34 | ]); 35 | -------------------------------------------------------------------------------- /wrangler.toml: -------------------------------------------------------------------------------- 1 | name = "durabcast" 2 | main = "src/index.ts" 3 | compatibility_date = "2024-07-18" 4 | 5 | [[env.test.durable_objects.bindings]] 6 | class_name = "BroadcastMessage" 7 | name = "BROADCAST_MESSAGE" 8 | 9 | [[env.test.migrations]] 10 | tag = "v1" 11 | new_classes = ["BroadcastMessage"] --------------------------------------------------------------------------------