├── .github └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── README.md ├── biome.json ├── build.config.ts ├── package.json ├── pnpm-lock.yaml ├── src ├── base32.ts ├── base64.test.ts ├── base64.ts ├── binary.ts ├── ecdsa.test.ts ├── ecdsa.ts ├── hash.test.ts ├── hash.ts ├── hex.test.ts ├── hex.ts ├── hmac.test.ts ├── hmac.ts ├── index.ts ├── otp.test.ts ├── otp.ts ├── random.test.ts ├── random.ts ├── rsa.test.ts ├── rsa.ts └── type.ts ├── tsconfig.json └── vitest.config.ts /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | branches: main 6 | push: 7 | branches: main 8 | merge_group: {} 9 | 10 | jobs: 11 | test: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - uses: pnpm/action-setup@v4 19 | with: 20 | version: 9.9.0 21 | 22 | - uses: actions/setup-node@v4 23 | with: 24 | node-version: 20.x 25 | registry-url: 'https://registry.npmjs.org' 26 | cache: pnpm 27 | 28 | - name: Install 29 | run: pnpm install 30 | 31 | - name: Build 32 | run: pnpm build 33 | 34 | - name: Test 35 | run: pnpm test 36 | 37 | - name: Typecheck 38 | run: pnpm typecheck 39 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - 'v*' 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | release: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | 19 | - uses: actions/setup-node@v4 20 | with: 21 | node-version: 20.x 22 | 23 | - run: npx changelogithub 24 | env: 25 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} 26 | 27 | - uses: pnpm/action-setup@v4 28 | with: 29 | version: 9.9.0 30 | 31 | - uses: actions/setup-node@v4 32 | with: 33 | node-version: 20.x 34 | registry-url: 'https://registry.npmjs.org' 35 | 36 | - run: pnpm install 37 | 38 | - name: Build 39 | run: pnpm build 40 | 41 | - name: Determine npm tag 42 | id: determine_npm_tag 43 | shell: bash 44 | run: | 45 | TAG="${GITHUB_REF#refs/tags/}" 46 | if [[ "$TAG" =~ -(next|canary|beta|rc) ]]; then 47 | # Extract pre-release tag (e.g., beta, rc) 48 | NPM_TAG=${BASH_REMATCH[1]} 49 | else 50 | # Check if the commit is on the main branch 51 | git fetch origin main 52 | if git merge-base --is-ancestor "$GITHUB_SHA" origin/main; then 53 | NPM_TAG="latest" 54 | else 55 | echo "The tagged commit is not on the main branch." 56 | echo "::error ::Releases with the 'latest' npm tag must be on the main branch." 57 | exit 1 58 | fi 59 | fi 60 | echo "npm_tag=$NPM_TAG" >> $GITHUB_OUTPUT 61 | echo "Using npm tag: $NPM_TAG" 62 | 63 | - name: Publish to npm 64 | run: pnpm -r publish --access public --no-git-checks --tag ${{ steps.determine_npm_tag.outputs.npm_tag }} 65 | env: 66 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js dependencies 2 | node_modules/ 3 | 4 | # TypeScript compiled output 5 | dist/ 6 | build/ 7 | 8 | # TypeScript cache 9 | *.tsbuildinfo 10 | 11 | # Logs 12 | logs/ 13 | *.log 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | 18 | # Environment variables 19 | .env 20 | .env.local 21 | .env.development.local 22 | .env.test.local 23 | .env.production.local 24 | 25 | # IDE specific files 26 | .vscode/ 27 | .idea/ 28 | *.suo 29 | *.ntvs* 30 | *.njsproj 31 | *.sln 32 | 33 | # MacOS specific files 34 | .DS_Store 35 | 36 | # Temporary files 37 | tmp/ 38 | temp/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Better Auth Utils 2 | 3 | A simple typescript API for common auth utilities like hashing, encryption, encoding, and OTP generation. Built on top of Web Crypto APIs and it wraps over [uncrypto](https://github.com/unjs/uncrypto) to provide a unified API for both Node.js (using the Crypto module) and web environments (using the Web Crypto API) through Conditional Exports. 4 | 5 | ```bash 6 | pnpm add @better-auth/utils 7 | ``` 8 | 9 | ## Utilities at a Glance 10 | 11 | utilities provided by `@better-auth/utils`: 12 | 13 | | Utility | Description | 14 | |-------------------|----------------------------------------------------| 15 | | [**Hash**](#hash) | Hash inputs using sha family hash functions. | 16 | | [**HMAC**](#hmac) | Hash inputs using HMAC with a secret key. | 17 | | [**Random String**](#random-string) | Generate random strings with a specified length and charset. | 18 | | [**RSA**](#rsa) | Perform encryption, decryption, signing, and verification with RSA keys. | 19 | | [**ECDSA**](#ecdsa) | Perform signing and verification with ECDSA keys. | 20 | | [**OTP**](#otp) | Generate and verify one-time passwords. | 21 | | [**Base64**](#base64) | Encode and decode data in base64 format. | 22 | | [**Hex**](#hex) | Encode and decode data in hexadecimal format. | 23 | | [**Binary**](#binary) | Encode and decode data in binary format. | 24 | 25 | ## Hash 26 | 27 | Digest provides a way to hash an input using sha family hash functions. It wraps over `crypto.digest` and provide utilities to encode output in hex or base 64. 28 | 29 | ```ts 30 | import { createHash } from "@better-auth/utils/hash" 31 | 32 | const hashBuffer = await createHash("SHA-256").digest("text"); 33 | const hashInHex = await createHash("SHA-256", "hex").digest("text"); 34 | ``` 35 | 36 | To encode output in base64 37 | 38 | ```ts 39 | const hashInBase64 = await createHash("SHA-256", "base64").digest("text"); 40 | ``` 41 | 42 | ## HMAC 43 | 44 | The HMAC utility allows you to securely hash data using a secret key and SHA family hash functions. It provides methods to `sign`, `verify`, and `create` a customized HMAC instance with specific hashing algorithms and encoding formats. 45 | 46 | ### Create HMAC 47 | 48 | To create an HMAC instance, use the createHMAC function. You can specify the SHA family algorithm ("SHA-256", "SHA-384", or "SHA-512") and the desired encoding format ("none", "hex", "base64", "base64url", or "base64urlnopad"). 49 | 50 | It takes a secret key and returns a key object which could be used to sign and verify data. 51 | 52 | ```ts 53 | import { createHMAC } from './hmac'; 54 | 55 | const hmac = createHMAC("SHA-256", "hex"); // Customize algorithm and encoding 56 | ``` 57 | 58 | ### Import Key 59 | 60 | The importKey method takes a secret key (string, buffer, or typed array) and returns a CryptoKey object that can be used for signing and verifying data. 61 | 62 | ```ts 63 | const secretKey = "my-secret-key"; // Can also be a buffer or TypedArray 64 | const key = await hmac.importKey(secretKey); 65 | ``` 66 | 67 | ### Sign 68 | 69 | The sign method takes a secret key (or CryptoKey) and data to generate a signature. If you provide a raw secret key, it will automatically be imported. 70 | 71 | ```ts 72 | const key = await hmac.importKey("my-secret-key"); 73 | const signature = await hmac.sign(key, "text to sign"); 74 | console.log(signature); // Encoded based on the selected encoding format (e.g., hex) 75 | ``` 76 | 77 | You could also directly sign using the raw string secret key. 78 | 79 | ```ts 80 | const signature2 = await hmac.sign("secret-key",{ 81 | data: "text" 82 | }); 83 | ``` 84 | 85 | ### Verify 86 | 87 | The verify method checks if a given signature matches the data using the secret key. You can provide either a raw secret key or a CryptoKey. 88 | 89 | ```ts 90 | const key = await hmac.importKey("my-secret-key"); 91 | const isValid = await hmac.verify(key, "text to sign", signature); 92 | console.log(isValid); // true or false 93 | ``` 94 | 95 | ## Random String 96 | 97 | Random crypto secure string generator. It wraps over `crypto.getRandomValues` and provide utilities to generator based on length and charset. 98 | 99 | 1. first create a random string generator with desired charset. 100 | ```ts 101 | import { createRandomStringGenerator } from "@better-auth/utils/random" 102 | 103 | export const generateRandomString = createRandomStringGenerator("A-Z", "0-9", "a-z", "-_") 104 | ``` 105 | 106 | 2. generate random string based on length. 107 | ```ts 108 | const randomString = generateRandomString(32) 109 | const randomString2 = generateRandomString(32, "A-Z", "0-9") // override charset 110 | ``` 111 | 112 | ## RSA 113 | 114 | RSA utilities provide a simple interface to work with RSA cryptographic operations, such as generating key pairs, encrypting and decrypting data, and signing and verifying messages. 115 | 116 | ### Key Pair Generation 117 | 118 | You can generate RSA key pairs with specified parameters. By default, the `modulusLength` is 2048 bits and the hash algorithm is `SHA-256`. 119 | 120 | ```ts 121 | import { rsa } from "@better-auth/utils/rsa"; 122 | 123 | const keyPair = await rsa.generateKeyPair(2048, "SHA-256"); 124 | const { publicKey, privateKey } = keyPair; 125 | ``` 126 | 127 | ### Exporting Keys 128 | 129 | Export a public or private key in your preferred format. 130 | 131 | ```ts 132 | const jwk = await rsa.exportKey(publicKey, "jwk"); 133 | const spki = await rsa.exportKey(publicKey, "spki"); 134 | ``` 135 | 136 | ### Importing Keys 137 | 138 | Import a key in the `jwk` format for specific usage (`encrypt`, `decrypt`, `sign`, or `verify`). 139 | 140 | ```ts 141 | const importedKey = await rsa.importKey(jwk, "encrypt"); 142 | ``` 143 | 144 | ### Encryption 145 | 146 | Encrypt sensitive data using an RSA public key. Input can be a string, `ArrayBuffer`, `TypedArray` or `string`. 147 | 148 | ```ts 149 | const encryptedData = await rsa.encrypt(publicKey, "Sensitive data"); 150 | ``` 151 | 152 | ### Decryption 153 | 154 | Decrypt encrypted data using the corresponding RSA private key. 155 | 156 | ```ts 157 | const decryptedData = await rsa.decrypt(privateKey, encryptedData); 158 | const originalText = new TextDecoder().decode(decryptedData); 159 | ``` 160 | 161 | ### Signing 162 | 163 | Sign a message using the RSA private key. Input can be a string, `ArrayBuffer`, or `TypedArray`. 164 | 165 | ```ts 166 | const signature = await rsa.sign(privateKey, "Message to sign"); 167 | ``` 168 | 169 | ### Verifying 170 | 171 | Verify a signature against the original data using the RSA public key. 172 | 173 | ```ts 174 | const isValid = await rsa.verify(publicKey, { 175 | signature, 176 | data: "Message to sign", 177 | }); 178 | ``` 179 | 180 | ## ECDSA 181 | 182 | ECDSA utilities provide a simple interface to perform key pair generation, signing, and verification using elliptic curve cryptography. 183 | 184 | ### Key Pair Generation 185 | 186 | You can generate ECDSA key pairs with your preferred curve. Supported curves are `"P-256"`, `"P-384"`, and `"P-521"`. 187 | 188 | ```ts 189 | import { ecdsa } from "@better-auth/utils/ecdsa"; 190 | 191 | const { privateKey, publicKey } = await ecdsa.generateKeyPair("P-256"); 192 | ``` 193 | 194 | ### Exporting Keys 195 | 196 | Export a public or private key in your preferred format, such as `pkcs8` or `spki`. 197 | 198 | ```ts 199 | const exportedPrivateKey = await ecdsa.exportKey(privateKey, "pkcs8"); 200 | const exportedPublicKey = await ecdsa.exportKey(publicKey, "spki"); 201 | ``` 202 | 203 | ### Importing Keys 204 | 205 | Import an ECDSA private or public key in the appropriate format. Public keys can also be provided as strings. 206 | 207 | ```ts 208 | const importedPrivateKey = await ecdsa.importPrivateKey(exportedPrivateKey, "P-256"); 209 | const importedPublicKey = await ecdsa.importPublicKey(exportedPublicKey, "P-256"); 210 | ``` 211 | 212 | ### Signing 213 | 214 | Sign data using the ECDSA private key. The input can be a string or `ArrayBuffer`. You can specify the hash algorithm, which defaults to `"SHA-256"`. 215 | 216 | ```ts 217 | const signature = await ecdsa.sign(privateKey, "Message to sign", "SHA-256"); 218 | ``` 219 | 220 | ### Verifying 221 | 222 | Verify a signature against the original data using the ECDSA public key. Input can be a string or `ArrayBuffer`. Signature verification requires providing the signature, data, and hash algorithm (default: `"SHA-256"`). 223 | 224 | ```ts 225 | const isValid = await ecdsa.verify(publicKey, { 226 | signature, 227 | data: "Message to verify", 228 | hash: "SHA-256", 229 | }); 230 | ``` 231 | 232 | ## OTP 233 | 234 | The OTP utility provides a simple and secure way to generate and verify one-time passwords (OTPs), commonly used in multi-factor authentication (MFA) systems. It includes support for both HOTP (HMAC-based One-Time Password) and TOTP (Time-based One-Time Password) standards. 235 | 236 | It's implemented based on [RFC 4226](https://tools.ietf.org/html/rfc4226) and [RFC 6238](https://tools.ietf.org/html/rfc6238). 237 | 238 | ### Generating HOTP 239 | 240 | HOTP generates a one-time password based on a counter value and a secret key. The counter should be incremented for each new OTP. 241 | 242 | ```ts 243 | import { createOTP } from "@better-auth/utils/otp"; 244 | const secret = "my-super-secret-key"; 245 | const counter = 1234; 246 | const otp = createOTP(secret, { 247 | digits: 6, 248 | }).hotp(counter); 249 | ``` 250 | 251 | ### Generating TOTP 252 | 253 | TOTP generates a one-time password based on the current time and a secret key. The time step is typically 30 seconds. 254 | 255 | ```ts 256 | import { createOTP } from "@better-auth/utils/otp"; 257 | const secret = "my-super-secret-key" 258 | const otp = createOTP(secret, { 259 | digits: 6, 260 | period: 30, 261 | }).totp(); 262 | ``` 263 | 264 | ### Verifying TOTP 265 | 266 | Verify a TOTP against the secret key and a specified time window. The default time window is 30 seconds. 267 | 268 | ```ts 269 | import { createOTP } from "@better-auth/utils/otp"; 270 | const secret = "my-super-secret-key" 271 | const isValid = createOTP(secret, { 272 | digits: 6, 273 | period: 30, 274 | }).verify(otp); 275 | ``` 276 | 277 | You can also specify the time window in seconds. 278 | 279 | ```ts 280 | import { createOTP } from "@better-auth/utils"; 281 | const isValid = createOTP(secret).verify(otp, { window: 60 }); 282 | ``` 283 | 284 | ### Generate URL for Authenticator App 285 | 286 | Generate a URL for provisioning a TOTP secret key in an authenticator app. 287 | 288 | - `issuer` - The name of the service or app. 289 | - `account` - The user's email or username. 290 | 291 | ```ts 292 | import { createOTP } from "@better-auth/utils/otp"; 293 | 294 | const secret = "my-super-secret-key"; 295 | const qrCodeUrl = createOTP(secret).url("my-app", "user@email.com"); 296 | ``` 297 | 298 | 299 | ## Base64 300 | 301 | Base64 utilities provide a simple interface to encode and decode data in base64 format. 302 | 303 | ### Encoding 304 | 305 | Encode data in base64 format. Input can be a string, `ArrayBuffer`, or `TypedArray`. 306 | 307 | ```ts 308 | import { base64 } from "@better-auth/utils/base64"; 309 | 310 | const encodedData = base64.encode("Data to encode"); 311 | ``` 312 | 313 | options: 314 | - `padding` - Include padding characters (`=`) at the end of the encoded string 315 | 316 | ```ts 317 | const encodedData = base64.encode("Data to encode", { url: true, padding: false }); 318 | ``` 319 | 320 | ### Decoding 321 | 322 | Decode base64-encoded data. Input can be a string or `ArrayBuffer`. 323 | 324 | ```ts 325 | const decodedData = await base64.decode(encodedData); 326 | ``` 327 | 328 | It automatically detects if the input is URL-safe and includes padding characters. 329 | 330 | ### Base64Url 331 | 332 | Url safe alternative 333 | 334 | ```ts 335 | import { base64Url } from "@better-auth/utils/base64"; 336 | 337 | const encodedData = base64Url.encode("Data to encode"); 338 | ``` 339 | 340 | ## Hex 341 | 342 | Hex utilities provide a simple interface to encode and decode data in hexadecimal format. 343 | 344 | ### Encoding 345 | 346 | Encode data in hexadecimal format. Input can be a string, `ArrayBuffer`, or `TypedArray`. 347 | 348 | ```ts 349 | import { hex } from "@better-auth/utils/hex"; 350 | 351 | const encodedData = hex.encode("Data to encode"); 352 | ``` 353 | 354 | ### Decoding 355 | 356 | Decode hexadecimal-encoded data. Input can be a string or `ArrayBuffer`. 357 | 358 | ```ts 359 | const decodedData = hex.decode(encodedData); 360 | ``` 361 | 362 | ## Binary 363 | 364 | A utilities provide a simple interface to encode and decode data in binary format. It uses `TextEncode` and `TextDecoder` to encode and decode data respectively. 365 | 366 | ### Encoding 367 | 368 | ```ts 369 | import { binary } from "@better-auth/util/binary" 370 | 371 | const data = binary.encode("Hello World!") 372 | ``` 373 | 374 | ### Decoding 375 | 376 | ```ts 377 | import { binary } from "@better-auth/util/binary" 378 | 379 | const data = binary.decode(new Unit8Array([[72, 101, 108, 108, 111]])) 380 | ``` 381 | 382 | ## License 383 | 384 | MIT 385 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", 3 | "formatter": { 4 | "enabled": true, 5 | "indentStyle": "tab" 6 | }, 7 | "organizeImports": { 8 | "enabled": false 9 | }, 10 | "linter": { 11 | "enabled": true, 12 | "rules": { 13 | "recommended": false, 14 | "suspicious": { 15 | "noImplicitAnyLet": "warn", 16 | "noDuplicateObjectKeys": "warn" 17 | }, 18 | "performance": { 19 | "noDelete": "error" 20 | }, 21 | "complexity": { 22 | "noUselessSwitchCase": "warn", 23 | "noUselessTypeConstraint": "warn" 24 | } 25 | } 26 | }, 27 | "files": { 28 | "ignore": ["dist"] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from "unbuild"; 2 | 3 | export default defineBuildConfig({ 4 | outDir: "dist", 5 | declaration: true, 6 | }); 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@better-auth/utils", 3 | "version": "0.2.5", 4 | "license": "MIT", 5 | "description": "A collection of utilities for better-auth", 6 | "main": "./dist/index.cjs", 7 | "module": "./dist/index.mjs", 8 | "scripts": { 9 | "test": "vitest", 10 | "typecheck": "tsc --noEmit", 11 | "build": "unbuild", 12 | "lint:fix": "biome check . --write" 13 | }, 14 | "keywords": [ 15 | "auth", 16 | "utils", 17 | "typescript", 18 | "better-auth", 19 | "better-auth-utils" 20 | ], 21 | "author": "Bereket Engida", 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/better-auth/utils" 25 | }, 26 | "dependencies": { 27 | "typescript": "^5.8.2", 28 | "uncrypto": "^0.1.3" 29 | }, 30 | "devDependencies": { 31 | "@biomejs/biome": "^1.9.4", 32 | "@types/node": "^22.10.1", 33 | "bumpp": "^9.9.0", 34 | "happy-dom": "^15.11.7", 35 | "unbuild": "^2.0.0", 36 | "vitest": "^2.1.8" 37 | }, 38 | "exports": { 39 | ".": { 40 | "import": "./dist/index.mjs", 41 | "require": "./dist/index.cjs" 42 | }, 43 | "./base32": { 44 | "import": "./dist/base32.mjs", 45 | "require": "./dist/base32.cjs" 46 | }, 47 | "./base64": { 48 | "import": "./dist/base64.mjs", 49 | "require": "./dist/base64.cjs" 50 | }, 51 | "./binary": { 52 | "import": "./dist/binary.mjs", 53 | "require": "./dist/binary.cjs" 54 | }, 55 | "./hash": { 56 | "import": "./dist/hash.mjs", 57 | "require": "./dist/hash.cjs" 58 | }, 59 | "./ecdsa": { 60 | "import": "./dist/ecdsa.mjs", 61 | "require": "./dist/ecdsa.cjs" 62 | }, 63 | "./hex": { 64 | "import": "./dist/hex.mjs", 65 | "require": "./dist/hex.cjs" 66 | }, 67 | "./hmac": { 68 | "import": "./dist/hmac.mjs", 69 | "require": "./dist/hmac.cjs" 70 | }, 71 | "./otp": { 72 | "import": "./dist/otp.mjs", 73 | "require": "./dist/otp.cjs" 74 | }, 75 | "./random": { 76 | "import": "./dist/random.mjs", 77 | "require": "./dist/random.cjs" 78 | }, 79 | "./rsa": { 80 | "import": "./dist/rsa.mjs", 81 | "require": "./dist/rsa.cjs" 82 | } 83 | }, 84 | "files": [ 85 | "dist" 86 | ] 87 | } -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | typescript: 12 | specifier: ^5.8.2 13 | version: 5.8.2 14 | uncrypto: 15 | specifier: ^0.1.3 16 | version: 0.1.3 17 | devDependencies: 18 | '@biomejs/biome': 19 | specifier: ^1.9.4 20 | version: 1.9.4 21 | '@types/node': 22 | specifier: ^22.10.1 23 | version: 22.10.1 24 | bumpp: 25 | specifier: ^9.9.0 26 | version: 9.9.0 27 | happy-dom: 28 | specifier: ^15.11.7 29 | version: 15.11.7 30 | unbuild: 31 | specifier: ^2.0.0 32 | version: 2.0.0(typescript@5.8.2) 33 | vitest: 34 | specifier: ^2.1.8 35 | version: 2.1.8(@types/node@22.10.1)(happy-dom@15.11.7) 36 | 37 | packages: 38 | 39 | '@ampproject/remapping@2.3.0': 40 | resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} 41 | engines: {node: '>=6.0.0'} 42 | 43 | '@babel/code-frame@7.26.2': 44 | resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} 45 | engines: {node: '>=6.9.0'} 46 | 47 | '@babel/compat-data@7.26.3': 48 | resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} 49 | engines: {node: '>=6.9.0'} 50 | 51 | '@babel/core@7.26.0': 52 | resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} 53 | engines: {node: '>=6.9.0'} 54 | 55 | '@babel/generator@7.26.3': 56 | resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} 57 | engines: {node: '>=6.9.0'} 58 | 59 | '@babel/helper-compilation-targets@7.25.9': 60 | resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} 61 | engines: {node: '>=6.9.0'} 62 | 63 | '@babel/helper-module-imports@7.25.9': 64 | resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} 65 | engines: {node: '>=6.9.0'} 66 | 67 | '@babel/helper-module-transforms@7.26.0': 68 | resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} 69 | engines: {node: '>=6.9.0'} 70 | peerDependencies: 71 | '@babel/core': ^7.0.0 72 | 73 | '@babel/helper-string-parser@7.25.9': 74 | resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} 75 | engines: {node: '>=6.9.0'} 76 | 77 | '@babel/helper-validator-identifier@7.25.9': 78 | resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} 79 | engines: {node: '>=6.9.0'} 80 | 81 | '@babel/helper-validator-option@7.25.9': 82 | resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} 83 | engines: {node: '>=6.9.0'} 84 | 85 | '@babel/helpers@7.26.0': 86 | resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} 87 | engines: {node: '>=6.9.0'} 88 | 89 | '@babel/parser@7.26.3': 90 | resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} 91 | engines: {node: '>=6.0.0'} 92 | hasBin: true 93 | 94 | '@babel/standalone@7.26.4': 95 | resolution: {integrity: sha512-SF+g7S2mhTT1b7CHyfNjDkPU1corxg4LPYsyP0x5KuCl+EbtBQHRLqr9N3q7e7+x7NQ5LYxQf8mJ2PmzebLr0A==} 96 | engines: {node: '>=6.9.0'} 97 | 98 | '@babel/template@7.25.9': 99 | resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} 100 | engines: {node: '>=6.9.0'} 101 | 102 | '@babel/traverse@7.26.4': 103 | resolution: {integrity: sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==} 104 | engines: {node: '>=6.9.0'} 105 | 106 | '@babel/types@7.26.3': 107 | resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} 108 | engines: {node: '>=6.9.0'} 109 | 110 | '@biomejs/biome@1.9.4': 111 | resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} 112 | engines: {node: '>=14.21.3'} 113 | hasBin: true 114 | 115 | '@biomejs/cli-darwin-arm64@1.9.4': 116 | resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} 117 | engines: {node: '>=14.21.3'} 118 | cpu: [arm64] 119 | os: [darwin] 120 | 121 | '@biomejs/cli-darwin-x64@1.9.4': 122 | resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} 123 | engines: {node: '>=14.21.3'} 124 | cpu: [x64] 125 | os: [darwin] 126 | 127 | '@biomejs/cli-linux-arm64-musl@1.9.4': 128 | resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} 129 | engines: {node: '>=14.21.3'} 130 | cpu: [arm64] 131 | os: [linux] 132 | 133 | '@biomejs/cli-linux-arm64@1.9.4': 134 | resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} 135 | engines: {node: '>=14.21.3'} 136 | cpu: [arm64] 137 | os: [linux] 138 | 139 | '@biomejs/cli-linux-x64-musl@1.9.4': 140 | resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} 141 | engines: {node: '>=14.21.3'} 142 | cpu: [x64] 143 | os: [linux] 144 | 145 | '@biomejs/cli-linux-x64@1.9.4': 146 | resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} 147 | engines: {node: '>=14.21.3'} 148 | cpu: [x64] 149 | os: [linux] 150 | 151 | '@biomejs/cli-win32-arm64@1.9.4': 152 | resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} 153 | engines: {node: '>=14.21.3'} 154 | cpu: [arm64] 155 | os: [win32] 156 | 157 | '@biomejs/cli-win32-x64@1.9.4': 158 | resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} 159 | engines: {node: '>=14.21.3'} 160 | cpu: [x64] 161 | os: [win32] 162 | 163 | '@esbuild/aix-ppc64@0.19.12': 164 | resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} 165 | engines: {node: '>=12'} 166 | cpu: [ppc64] 167 | os: [aix] 168 | 169 | '@esbuild/aix-ppc64@0.21.5': 170 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 171 | engines: {node: '>=12'} 172 | cpu: [ppc64] 173 | os: [aix] 174 | 175 | '@esbuild/aix-ppc64@0.24.0': 176 | resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} 177 | engines: {node: '>=18'} 178 | cpu: [ppc64] 179 | os: [aix] 180 | 181 | '@esbuild/android-arm64@0.19.12': 182 | resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} 183 | engines: {node: '>=12'} 184 | cpu: [arm64] 185 | os: [android] 186 | 187 | '@esbuild/android-arm64@0.21.5': 188 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 189 | engines: {node: '>=12'} 190 | cpu: [arm64] 191 | os: [android] 192 | 193 | '@esbuild/android-arm64@0.24.0': 194 | resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} 195 | engines: {node: '>=18'} 196 | cpu: [arm64] 197 | os: [android] 198 | 199 | '@esbuild/android-arm@0.19.12': 200 | resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} 201 | engines: {node: '>=12'} 202 | cpu: [arm] 203 | os: [android] 204 | 205 | '@esbuild/android-arm@0.21.5': 206 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 207 | engines: {node: '>=12'} 208 | cpu: [arm] 209 | os: [android] 210 | 211 | '@esbuild/android-arm@0.24.0': 212 | resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} 213 | engines: {node: '>=18'} 214 | cpu: [arm] 215 | os: [android] 216 | 217 | '@esbuild/android-x64@0.19.12': 218 | resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} 219 | engines: {node: '>=12'} 220 | cpu: [x64] 221 | os: [android] 222 | 223 | '@esbuild/android-x64@0.21.5': 224 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 225 | engines: {node: '>=12'} 226 | cpu: [x64] 227 | os: [android] 228 | 229 | '@esbuild/android-x64@0.24.0': 230 | resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} 231 | engines: {node: '>=18'} 232 | cpu: [x64] 233 | os: [android] 234 | 235 | '@esbuild/darwin-arm64@0.19.12': 236 | resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} 237 | engines: {node: '>=12'} 238 | cpu: [arm64] 239 | os: [darwin] 240 | 241 | '@esbuild/darwin-arm64@0.21.5': 242 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 243 | engines: {node: '>=12'} 244 | cpu: [arm64] 245 | os: [darwin] 246 | 247 | '@esbuild/darwin-arm64@0.24.0': 248 | resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} 249 | engines: {node: '>=18'} 250 | cpu: [arm64] 251 | os: [darwin] 252 | 253 | '@esbuild/darwin-x64@0.19.12': 254 | resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} 255 | engines: {node: '>=12'} 256 | cpu: [x64] 257 | os: [darwin] 258 | 259 | '@esbuild/darwin-x64@0.21.5': 260 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 261 | engines: {node: '>=12'} 262 | cpu: [x64] 263 | os: [darwin] 264 | 265 | '@esbuild/darwin-x64@0.24.0': 266 | resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} 267 | engines: {node: '>=18'} 268 | cpu: [x64] 269 | os: [darwin] 270 | 271 | '@esbuild/freebsd-arm64@0.19.12': 272 | resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} 273 | engines: {node: '>=12'} 274 | cpu: [arm64] 275 | os: [freebsd] 276 | 277 | '@esbuild/freebsd-arm64@0.21.5': 278 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 279 | engines: {node: '>=12'} 280 | cpu: [arm64] 281 | os: [freebsd] 282 | 283 | '@esbuild/freebsd-arm64@0.24.0': 284 | resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} 285 | engines: {node: '>=18'} 286 | cpu: [arm64] 287 | os: [freebsd] 288 | 289 | '@esbuild/freebsd-x64@0.19.12': 290 | resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} 291 | engines: {node: '>=12'} 292 | cpu: [x64] 293 | os: [freebsd] 294 | 295 | '@esbuild/freebsd-x64@0.21.5': 296 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 297 | engines: {node: '>=12'} 298 | cpu: [x64] 299 | os: [freebsd] 300 | 301 | '@esbuild/freebsd-x64@0.24.0': 302 | resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} 303 | engines: {node: '>=18'} 304 | cpu: [x64] 305 | os: [freebsd] 306 | 307 | '@esbuild/linux-arm64@0.19.12': 308 | resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} 309 | engines: {node: '>=12'} 310 | cpu: [arm64] 311 | os: [linux] 312 | 313 | '@esbuild/linux-arm64@0.21.5': 314 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 315 | engines: {node: '>=12'} 316 | cpu: [arm64] 317 | os: [linux] 318 | 319 | '@esbuild/linux-arm64@0.24.0': 320 | resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} 321 | engines: {node: '>=18'} 322 | cpu: [arm64] 323 | os: [linux] 324 | 325 | '@esbuild/linux-arm@0.19.12': 326 | resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} 327 | engines: {node: '>=12'} 328 | cpu: [arm] 329 | os: [linux] 330 | 331 | '@esbuild/linux-arm@0.21.5': 332 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 333 | engines: {node: '>=12'} 334 | cpu: [arm] 335 | os: [linux] 336 | 337 | '@esbuild/linux-arm@0.24.0': 338 | resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} 339 | engines: {node: '>=18'} 340 | cpu: [arm] 341 | os: [linux] 342 | 343 | '@esbuild/linux-ia32@0.19.12': 344 | resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} 345 | engines: {node: '>=12'} 346 | cpu: [ia32] 347 | os: [linux] 348 | 349 | '@esbuild/linux-ia32@0.21.5': 350 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 351 | engines: {node: '>=12'} 352 | cpu: [ia32] 353 | os: [linux] 354 | 355 | '@esbuild/linux-ia32@0.24.0': 356 | resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} 357 | engines: {node: '>=18'} 358 | cpu: [ia32] 359 | os: [linux] 360 | 361 | '@esbuild/linux-loong64@0.19.12': 362 | resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} 363 | engines: {node: '>=12'} 364 | cpu: [loong64] 365 | os: [linux] 366 | 367 | '@esbuild/linux-loong64@0.21.5': 368 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 369 | engines: {node: '>=12'} 370 | cpu: [loong64] 371 | os: [linux] 372 | 373 | '@esbuild/linux-loong64@0.24.0': 374 | resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} 375 | engines: {node: '>=18'} 376 | cpu: [loong64] 377 | os: [linux] 378 | 379 | '@esbuild/linux-mips64el@0.19.12': 380 | resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} 381 | engines: {node: '>=12'} 382 | cpu: [mips64el] 383 | os: [linux] 384 | 385 | '@esbuild/linux-mips64el@0.21.5': 386 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 387 | engines: {node: '>=12'} 388 | cpu: [mips64el] 389 | os: [linux] 390 | 391 | '@esbuild/linux-mips64el@0.24.0': 392 | resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} 393 | engines: {node: '>=18'} 394 | cpu: [mips64el] 395 | os: [linux] 396 | 397 | '@esbuild/linux-ppc64@0.19.12': 398 | resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} 399 | engines: {node: '>=12'} 400 | cpu: [ppc64] 401 | os: [linux] 402 | 403 | '@esbuild/linux-ppc64@0.21.5': 404 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 405 | engines: {node: '>=12'} 406 | cpu: [ppc64] 407 | os: [linux] 408 | 409 | '@esbuild/linux-ppc64@0.24.0': 410 | resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} 411 | engines: {node: '>=18'} 412 | cpu: [ppc64] 413 | os: [linux] 414 | 415 | '@esbuild/linux-riscv64@0.19.12': 416 | resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} 417 | engines: {node: '>=12'} 418 | cpu: [riscv64] 419 | os: [linux] 420 | 421 | '@esbuild/linux-riscv64@0.21.5': 422 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 423 | engines: {node: '>=12'} 424 | cpu: [riscv64] 425 | os: [linux] 426 | 427 | '@esbuild/linux-riscv64@0.24.0': 428 | resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} 429 | engines: {node: '>=18'} 430 | cpu: [riscv64] 431 | os: [linux] 432 | 433 | '@esbuild/linux-s390x@0.19.12': 434 | resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} 435 | engines: {node: '>=12'} 436 | cpu: [s390x] 437 | os: [linux] 438 | 439 | '@esbuild/linux-s390x@0.21.5': 440 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 441 | engines: {node: '>=12'} 442 | cpu: [s390x] 443 | os: [linux] 444 | 445 | '@esbuild/linux-s390x@0.24.0': 446 | resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} 447 | engines: {node: '>=18'} 448 | cpu: [s390x] 449 | os: [linux] 450 | 451 | '@esbuild/linux-x64@0.19.12': 452 | resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} 453 | engines: {node: '>=12'} 454 | cpu: [x64] 455 | os: [linux] 456 | 457 | '@esbuild/linux-x64@0.21.5': 458 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 459 | engines: {node: '>=12'} 460 | cpu: [x64] 461 | os: [linux] 462 | 463 | '@esbuild/linux-x64@0.24.0': 464 | resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} 465 | engines: {node: '>=18'} 466 | cpu: [x64] 467 | os: [linux] 468 | 469 | '@esbuild/netbsd-x64@0.19.12': 470 | resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} 471 | engines: {node: '>=12'} 472 | cpu: [x64] 473 | os: [netbsd] 474 | 475 | '@esbuild/netbsd-x64@0.21.5': 476 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 477 | engines: {node: '>=12'} 478 | cpu: [x64] 479 | os: [netbsd] 480 | 481 | '@esbuild/netbsd-x64@0.24.0': 482 | resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} 483 | engines: {node: '>=18'} 484 | cpu: [x64] 485 | os: [netbsd] 486 | 487 | '@esbuild/openbsd-arm64@0.24.0': 488 | resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} 489 | engines: {node: '>=18'} 490 | cpu: [arm64] 491 | os: [openbsd] 492 | 493 | '@esbuild/openbsd-x64@0.19.12': 494 | resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} 495 | engines: {node: '>=12'} 496 | cpu: [x64] 497 | os: [openbsd] 498 | 499 | '@esbuild/openbsd-x64@0.21.5': 500 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 501 | engines: {node: '>=12'} 502 | cpu: [x64] 503 | os: [openbsd] 504 | 505 | '@esbuild/openbsd-x64@0.24.0': 506 | resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} 507 | engines: {node: '>=18'} 508 | cpu: [x64] 509 | os: [openbsd] 510 | 511 | '@esbuild/sunos-x64@0.19.12': 512 | resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} 513 | engines: {node: '>=12'} 514 | cpu: [x64] 515 | os: [sunos] 516 | 517 | '@esbuild/sunos-x64@0.21.5': 518 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 519 | engines: {node: '>=12'} 520 | cpu: [x64] 521 | os: [sunos] 522 | 523 | '@esbuild/sunos-x64@0.24.0': 524 | resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} 525 | engines: {node: '>=18'} 526 | cpu: [x64] 527 | os: [sunos] 528 | 529 | '@esbuild/win32-arm64@0.19.12': 530 | resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} 531 | engines: {node: '>=12'} 532 | cpu: [arm64] 533 | os: [win32] 534 | 535 | '@esbuild/win32-arm64@0.21.5': 536 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 537 | engines: {node: '>=12'} 538 | cpu: [arm64] 539 | os: [win32] 540 | 541 | '@esbuild/win32-arm64@0.24.0': 542 | resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} 543 | engines: {node: '>=18'} 544 | cpu: [arm64] 545 | os: [win32] 546 | 547 | '@esbuild/win32-ia32@0.19.12': 548 | resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} 549 | engines: {node: '>=12'} 550 | cpu: [ia32] 551 | os: [win32] 552 | 553 | '@esbuild/win32-ia32@0.21.5': 554 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 555 | engines: {node: '>=12'} 556 | cpu: [ia32] 557 | os: [win32] 558 | 559 | '@esbuild/win32-ia32@0.24.0': 560 | resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} 561 | engines: {node: '>=18'} 562 | cpu: [ia32] 563 | os: [win32] 564 | 565 | '@esbuild/win32-x64@0.19.12': 566 | resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} 567 | engines: {node: '>=12'} 568 | cpu: [x64] 569 | os: [win32] 570 | 571 | '@esbuild/win32-x64@0.21.5': 572 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 573 | engines: {node: '>=12'} 574 | cpu: [x64] 575 | os: [win32] 576 | 577 | '@esbuild/win32-x64@0.24.0': 578 | resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} 579 | engines: {node: '>=18'} 580 | cpu: [x64] 581 | os: [win32] 582 | 583 | '@jridgewell/gen-mapping@0.3.5': 584 | resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} 585 | engines: {node: '>=6.0.0'} 586 | 587 | '@jridgewell/resolve-uri@3.1.2': 588 | resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 589 | engines: {node: '>=6.0.0'} 590 | 591 | '@jridgewell/set-array@1.2.1': 592 | resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} 593 | engines: {node: '>=6.0.0'} 594 | 595 | '@jridgewell/sourcemap-codec@1.5.0': 596 | resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} 597 | 598 | '@jridgewell/trace-mapping@0.3.25': 599 | resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} 600 | 601 | '@nodelib/fs.scandir@2.1.5': 602 | resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 603 | engines: {node: '>= 8'} 604 | 605 | '@nodelib/fs.stat@2.0.5': 606 | resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 607 | engines: {node: '>= 8'} 608 | 609 | '@nodelib/fs.walk@1.2.8': 610 | resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 611 | engines: {node: '>= 8'} 612 | 613 | '@rollup/plugin-alias@5.1.1': 614 | resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} 615 | engines: {node: '>=14.0.0'} 616 | peerDependencies: 617 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 618 | peerDependenciesMeta: 619 | rollup: 620 | optional: true 621 | 622 | '@rollup/plugin-commonjs@25.0.8': 623 | resolution: {integrity: sha512-ZEZWTK5n6Qde0to4vS9Mr5x/0UZoqCxPVR9KRUjU4kA2sO7GEUn1fop0DAwpO6z0Nw/kJON9bDmSxdWxO/TT1A==} 624 | engines: {node: '>=14.0.0'} 625 | peerDependencies: 626 | rollup: ^2.68.0||^3.0.0||^4.0.0 627 | peerDependenciesMeta: 628 | rollup: 629 | optional: true 630 | 631 | '@rollup/plugin-json@6.1.0': 632 | resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} 633 | engines: {node: '>=14.0.0'} 634 | peerDependencies: 635 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 636 | peerDependenciesMeta: 637 | rollup: 638 | optional: true 639 | 640 | '@rollup/plugin-node-resolve@15.3.0': 641 | resolution: {integrity: sha512-9eO5McEICxMzJpDW9OnMYSv4Sta3hmt7VtBFz5zR9273suNOydOyq/FrGeGy+KsTRFm8w0SLVhzig2ILFT63Ag==} 642 | engines: {node: '>=14.0.0'} 643 | peerDependencies: 644 | rollup: ^2.78.0||^3.0.0||^4.0.0 645 | peerDependenciesMeta: 646 | rollup: 647 | optional: true 648 | 649 | '@rollup/plugin-replace@5.0.7': 650 | resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==} 651 | engines: {node: '>=14.0.0'} 652 | peerDependencies: 653 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 654 | peerDependenciesMeta: 655 | rollup: 656 | optional: true 657 | 658 | '@rollup/pluginutils@5.1.3': 659 | resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} 660 | engines: {node: '>=14.0.0'} 661 | peerDependencies: 662 | rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 663 | peerDependenciesMeta: 664 | rollup: 665 | optional: true 666 | 667 | '@rollup/rollup-android-arm-eabi@4.28.1': 668 | resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==} 669 | cpu: [arm] 670 | os: [android] 671 | 672 | '@rollup/rollup-android-arm64@4.28.1': 673 | resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==} 674 | cpu: [arm64] 675 | os: [android] 676 | 677 | '@rollup/rollup-darwin-arm64@4.28.1': 678 | resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==} 679 | cpu: [arm64] 680 | os: [darwin] 681 | 682 | '@rollup/rollup-darwin-x64@4.28.1': 683 | resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==} 684 | cpu: [x64] 685 | os: [darwin] 686 | 687 | '@rollup/rollup-freebsd-arm64@4.28.1': 688 | resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==} 689 | cpu: [arm64] 690 | os: [freebsd] 691 | 692 | '@rollup/rollup-freebsd-x64@4.28.1': 693 | resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==} 694 | cpu: [x64] 695 | os: [freebsd] 696 | 697 | '@rollup/rollup-linux-arm-gnueabihf@4.28.1': 698 | resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==} 699 | cpu: [arm] 700 | os: [linux] 701 | 702 | '@rollup/rollup-linux-arm-musleabihf@4.28.1': 703 | resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==} 704 | cpu: [arm] 705 | os: [linux] 706 | 707 | '@rollup/rollup-linux-arm64-gnu@4.28.1': 708 | resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==} 709 | cpu: [arm64] 710 | os: [linux] 711 | 712 | '@rollup/rollup-linux-arm64-musl@4.28.1': 713 | resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==} 714 | cpu: [arm64] 715 | os: [linux] 716 | 717 | '@rollup/rollup-linux-loongarch64-gnu@4.28.1': 718 | resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==} 719 | cpu: [loong64] 720 | os: [linux] 721 | 722 | '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': 723 | resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==} 724 | cpu: [ppc64] 725 | os: [linux] 726 | 727 | '@rollup/rollup-linux-riscv64-gnu@4.28.1': 728 | resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==} 729 | cpu: [riscv64] 730 | os: [linux] 731 | 732 | '@rollup/rollup-linux-s390x-gnu@4.28.1': 733 | resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==} 734 | cpu: [s390x] 735 | os: [linux] 736 | 737 | '@rollup/rollup-linux-x64-gnu@4.28.1': 738 | resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==} 739 | cpu: [x64] 740 | os: [linux] 741 | 742 | '@rollup/rollup-linux-x64-musl@4.28.1': 743 | resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==} 744 | cpu: [x64] 745 | os: [linux] 746 | 747 | '@rollup/rollup-win32-arm64-msvc@4.28.1': 748 | resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==} 749 | cpu: [arm64] 750 | os: [win32] 751 | 752 | '@rollup/rollup-win32-ia32-msvc@4.28.1': 753 | resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==} 754 | cpu: [ia32] 755 | os: [win32] 756 | 757 | '@rollup/rollup-win32-x64-msvc@4.28.1': 758 | resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==} 759 | cpu: [x64] 760 | os: [win32] 761 | 762 | '@trysound/sax@0.2.0': 763 | resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} 764 | engines: {node: '>=10.13.0'} 765 | 766 | '@types/estree@1.0.6': 767 | resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} 768 | 769 | '@types/node@22.10.1': 770 | resolution: {integrity: sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==} 771 | 772 | '@types/resolve@1.20.2': 773 | resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} 774 | 775 | '@vitest/expect@2.1.8': 776 | resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==} 777 | 778 | '@vitest/mocker@2.1.8': 779 | resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==} 780 | peerDependencies: 781 | msw: ^2.4.9 782 | vite: ^5.0.0 783 | peerDependenciesMeta: 784 | msw: 785 | optional: true 786 | vite: 787 | optional: true 788 | 789 | '@vitest/pretty-format@2.1.8': 790 | resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==} 791 | 792 | '@vitest/runner@2.1.8': 793 | resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==} 794 | 795 | '@vitest/snapshot@2.1.8': 796 | resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==} 797 | 798 | '@vitest/spy@2.1.8': 799 | resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==} 800 | 801 | '@vitest/utils@2.1.8': 802 | resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} 803 | 804 | acorn@8.14.0: 805 | resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} 806 | engines: {node: '>=0.4.0'} 807 | hasBin: true 808 | 809 | argparse@2.0.1: 810 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 811 | 812 | assertion-error@2.0.1: 813 | resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 814 | engines: {node: '>=12'} 815 | 816 | autoprefixer@10.4.20: 817 | resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} 818 | engines: {node: ^10 || ^12 || >=14} 819 | hasBin: true 820 | peerDependencies: 821 | postcss: ^8.1.0 822 | 823 | balanced-match@1.0.2: 824 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 825 | 826 | boolbase@1.0.0: 827 | resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} 828 | 829 | brace-expansion@2.0.1: 830 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 831 | 832 | braces@3.0.3: 833 | resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 834 | engines: {node: '>=8'} 835 | 836 | browserslist@4.24.2: 837 | resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} 838 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 839 | hasBin: true 840 | 841 | bumpp@9.9.0: 842 | resolution: {integrity: sha512-d6Bv4O26po6gOrrjqDQte4+LxedxW885ZW7gJcNFUwkn9XH+8tKIB80za69SRluWkAgWPmSt7288pkMpzY1lnw==} 843 | engines: {node: '>=10'} 844 | hasBin: true 845 | 846 | c12@2.0.1: 847 | resolution: {integrity: sha512-Z4JgsKXHG37C6PYUtIxCfLJZvo6FyhHJoClwwb9ftUkLpPSkuYqn6Tr+vnaN8hymm0kIbcg6Ey3kv/Q71k5w/A==} 848 | peerDependencies: 849 | magicast: ^0.3.5 850 | peerDependenciesMeta: 851 | magicast: 852 | optional: true 853 | 854 | cac@6.7.14: 855 | resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 856 | engines: {node: '>=8'} 857 | 858 | caniuse-api@3.0.0: 859 | resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} 860 | 861 | caniuse-lite@1.0.30001687: 862 | resolution: {integrity: sha512-0S/FDhf4ZiqrTUiQ39dKeUjYRjkv7lOZU1Dgif2rIqrTzX/1wV2hfKu9TOm1IHkdSijfLswxTFzl/cvir+SLSQ==} 863 | 864 | chai@5.1.2: 865 | resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} 866 | engines: {node: '>=12'} 867 | 868 | chalk@5.3.0: 869 | resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} 870 | engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 871 | 872 | check-error@2.1.1: 873 | resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 874 | engines: {node: '>= 16'} 875 | 876 | chokidar@4.0.1: 877 | resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} 878 | engines: {node: '>= 14.16.0'} 879 | 880 | chownr@2.0.0: 881 | resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} 882 | engines: {node: '>=10'} 883 | 884 | citty@0.1.6: 885 | resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} 886 | 887 | colord@2.9.3: 888 | resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} 889 | 890 | commander@7.2.0: 891 | resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} 892 | engines: {node: '>= 10'} 893 | 894 | commondir@1.0.1: 895 | resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} 896 | 897 | confbox@0.1.8: 898 | resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} 899 | 900 | consola@3.2.3: 901 | resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} 902 | engines: {node: ^14.18.0 || >=16.10.0} 903 | 904 | convert-source-map@2.0.0: 905 | resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} 906 | 907 | cross-spawn@7.0.6: 908 | resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 909 | engines: {node: '>= 8'} 910 | 911 | css-declaration-sorter@7.2.0: 912 | resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==} 913 | engines: {node: ^14 || ^16 || >=18} 914 | peerDependencies: 915 | postcss: ^8.0.9 916 | 917 | css-select@5.1.0: 918 | resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} 919 | 920 | css-tree@2.2.1: 921 | resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} 922 | engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} 923 | 924 | css-tree@2.3.1: 925 | resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} 926 | engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} 927 | 928 | css-what@6.1.0: 929 | resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} 930 | engines: {node: '>= 6'} 931 | 932 | cssesc@3.0.0: 933 | resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} 934 | engines: {node: '>=4'} 935 | hasBin: true 936 | 937 | cssnano-preset-default@7.0.6: 938 | resolution: {integrity: sha512-ZzrgYupYxEvdGGuqL+JKOY70s7+saoNlHSCK/OGn1vB2pQK8KSET8jvenzItcY+kA7NoWvfbb/YhlzuzNKjOhQ==} 939 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 940 | peerDependencies: 941 | postcss: ^8.4.31 942 | 943 | cssnano-utils@5.0.0: 944 | resolution: {integrity: sha512-Uij0Xdxc24L6SirFr25MlwC2rCFX6scyUmuKpzI+JQ7cyqDEwD42fJ0xfB3yLfOnRDU5LKGgjQ9FA6LYh76GWQ==} 945 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 946 | peerDependencies: 947 | postcss: ^8.4.31 948 | 949 | cssnano@7.0.6: 950 | resolution: {integrity: sha512-54woqx8SCbp8HwvNZYn68ZFAepuouZW4lTwiMVnBErM3VkO7/Sd4oTOt3Zz3bPx3kxQ36aISppyXj2Md4lg8bw==} 951 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 952 | peerDependencies: 953 | postcss: ^8.4.31 954 | 955 | csso@5.0.5: 956 | resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} 957 | engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} 958 | 959 | debug@4.4.0: 960 | resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} 961 | engines: {node: '>=6.0'} 962 | peerDependencies: 963 | supports-color: '*' 964 | peerDependenciesMeta: 965 | supports-color: 966 | optional: true 967 | 968 | deep-eql@5.0.2: 969 | resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 970 | engines: {node: '>=6'} 971 | 972 | deepmerge@4.3.1: 973 | resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} 974 | engines: {node: '>=0.10.0'} 975 | 976 | defu@6.1.4: 977 | resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 978 | 979 | destr@2.0.3: 980 | resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} 981 | 982 | dir-glob@3.0.1: 983 | resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} 984 | engines: {node: '>=8'} 985 | 986 | dom-serializer@2.0.0: 987 | resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} 988 | 989 | domelementtype@2.3.0: 990 | resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} 991 | 992 | domhandler@5.0.3: 993 | resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} 994 | engines: {node: '>= 4'} 995 | 996 | domutils@3.1.0: 997 | resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} 998 | 999 | dotenv@16.4.7: 1000 | resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} 1001 | engines: {node: '>=12'} 1002 | 1003 | electron-to-chromium@1.5.72: 1004 | resolution: {integrity: sha512-ZpSAUOZ2Izby7qnZluSrAlGgGQzucmFbN0n64dYzocYxnxV5ufurpj3VgEe4cUp7ir9LmeLxNYo8bVnlM8bQHw==} 1005 | 1006 | entities@4.5.0: 1007 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 1008 | engines: {node: '>=0.12'} 1009 | 1010 | es-module-lexer@1.5.4: 1011 | resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} 1012 | 1013 | esbuild@0.19.12: 1014 | resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} 1015 | engines: {node: '>=12'} 1016 | hasBin: true 1017 | 1018 | esbuild@0.21.5: 1019 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 1020 | engines: {node: '>=12'} 1021 | hasBin: true 1022 | 1023 | esbuild@0.24.0: 1024 | resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} 1025 | engines: {node: '>=18'} 1026 | hasBin: true 1027 | 1028 | escalade@3.2.0: 1029 | resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 1030 | engines: {node: '>=6'} 1031 | 1032 | estree-walker@2.0.2: 1033 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 1034 | 1035 | estree-walker@3.0.3: 1036 | resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 1037 | 1038 | execa@8.0.1: 1039 | resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} 1040 | engines: {node: '>=16.17'} 1041 | 1042 | expect-type@1.1.0: 1043 | resolution: {integrity: sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==} 1044 | engines: {node: '>=12.0.0'} 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.2: 1054 | resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} 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 | fraction.js@4.3.7: 1066 | resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} 1067 | 1068 | fs-minipass@2.1.0: 1069 | resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} 1070 | engines: {node: '>= 8'} 1071 | 1072 | fs.realpath@1.0.0: 1073 | resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} 1074 | 1075 | fsevents@2.3.3: 1076 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 1077 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 1078 | os: [darwin] 1079 | 1080 | function-bind@1.1.2: 1081 | resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 1082 | 1083 | gensync@1.0.0-beta.2: 1084 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 1085 | engines: {node: '>=6.9.0'} 1086 | 1087 | get-stream@8.0.1: 1088 | resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} 1089 | engines: {node: '>=16'} 1090 | 1091 | giget@1.2.3: 1092 | resolution: {integrity: sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==} 1093 | hasBin: true 1094 | 1095 | glob-parent@5.1.2: 1096 | resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 1097 | engines: {node: '>= 6'} 1098 | 1099 | glob@8.1.0: 1100 | resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} 1101 | engines: {node: '>=12'} 1102 | deprecated: Glob versions prior to v9 are no longer supported 1103 | 1104 | globals@11.12.0: 1105 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 1106 | engines: {node: '>=4'} 1107 | 1108 | globby@13.2.2: 1109 | resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} 1110 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1111 | 1112 | happy-dom@15.11.7: 1113 | resolution: {integrity: sha512-KyrFvnl+J9US63TEzwoiJOQzZBJY7KgBushJA8X61DMbNsH+2ONkDuLDnCnwUiPTF42tLoEmrPyoqbenVA5zrg==} 1114 | engines: {node: '>=18.0.0'} 1115 | 1116 | hasown@2.0.2: 1117 | resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} 1118 | engines: {node: '>= 0.4'} 1119 | 1120 | hookable@5.5.3: 1121 | resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} 1122 | 1123 | human-signals@5.0.0: 1124 | resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} 1125 | engines: {node: '>=16.17.0'} 1126 | 1127 | ignore@5.3.2: 1128 | resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 1129 | engines: {node: '>= 4'} 1130 | 1131 | inflight@1.0.6: 1132 | resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} 1133 | deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. 1134 | 1135 | inherits@2.0.4: 1136 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} 1137 | 1138 | is-core-module@2.15.1: 1139 | resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} 1140 | engines: {node: '>= 0.4'} 1141 | 1142 | is-extglob@2.1.1: 1143 | resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1144 | engines: {node: '>=0.10.0'} 1145 | 1146 | is-glob@4.0.3: 1147 | resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1148 | engines: {node: '>=0.10.0'} 1149 | 1150 | is-module@1.0.0: 1151 | resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} 1152 | 1153 | is-number@7.0.0: 1154 | resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1155 | engines: {node: '>=0.12.0'} 1156 | 1157 | is-reference@1.2.1: 1158 | resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} 1159 | 1160 | is-stream@3.0.0: 1161 | resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} 1162 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1163 | 1164 | isexe@2.0.0: 1165 | resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1166 | 1167 | jiti@1.21.6: 1168 | resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} 1169 | hasBin: true 1170 | 1171 | jiti@2.4.1: 1172 | resolution: {integrity: sha512-yPBThwecp1wS9DmoA4x4KR2h3QoslacnDR8ypuFM962kI4/456Iy1oHx2RAgh4jfZNdn0bctsdadceiBUgpU1g==} 1173 | hasBin: true 1174 | 1175 | js-tokens@4.0.0: 1176 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 1177 | 1178 | js-yaml@4.1.0: 1179 | resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1180 | hasBin: true 1181 | 1182 | jsesc@3.0.2: 1183 | resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} 1184 | engines: {node: '>=6'} 1185 | hasBin: true 1186 | 1187 | json5@2.2.3: 1188 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 1189 | engines: {node: '>=6'} 1190 | hasBin: true 1191 | 1192 | jsonc-parser@3.3.1: 1193 | resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} 1194 | 1195 | kleur@3.0.3: 1196 | resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} 1197 | engines: {node: '>=6'} 1198 | 1199 | lilconfig@3.1.3: 1200 | resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} 1201 | engines: {node: '>=14'} 1202 | 1203 | lodash.memoize@4.1.2: 1204 | resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} 1205 | 1206 | lodash.uniq@4.5.0: 1207 | resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} 1208 | 1209 | loupe@3.1.2: 1210 | resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} 1211 | 1212 | lru-cache@5.1.1: 1213 | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 1214 | 1215 | magic-string@0.30.15: 1216 | resolution: {integrity: sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==} 1217 | 1218 | mdn-data@2.0.28: 1219 | resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} 1220 | 1221 | mdn-data@2.0.30: 1222 | resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} 1223 | 1224 | merge-stream@2.0.0: 1225 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} 1226 | 1227 | merge2@1.4.1: 1228 | resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1229 | engines: {node: '>= 8'} 1230 | 1231 | micromatch@4.0.8: 1232 | resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1233 | engines: {node: '>=8.6'} 1234 | 1235 | mimic-fn@4.0.0: 1236 | resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} 1237 | engines: {node: '>=12'} 1238 | 1239 | minimatch@5.1.6: 1240 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} 1241 | engines: {node: '>=10'} 1242 | 1243 | minipass@3.3.6: 1244 | resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} 1245 | engines: {node: '>=8'} 1246 | 1247 | minipass@5.0.0: 1248 | resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} 1249 | engines: {node: '>=8'} 1250 | 1251 | minizlib@2.1.2: 1252 | resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} 1253 | engines: {node: '>= 8'} 1254 | 1255 | mkdirp@1.0.4: 1256 | resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} 1257 | engines: {node: '>=10'} 1258 | hasBin: true 1259 | 1260 | mkdist@1.6.0: 1261 | resolution: {integrity: sha512-nD7J/mx33Lwm4Q4qoPgRBVA9JQNKgyE7fLo5vdPWVDdjz96pXglGERp/fRnGPCTB37Kykfxs5bDdXa9BWOT9nw==} 1262 | hasBin: true 1263 | peerDependencies: 1264 | sass: ^1.78.0 1265 | typescript: '>=5.5.4' 1266 | vue-tsc: ^1.8.27 || ^2.0.21 1267 | peerDependenciesMeta: 1268 | sass: 1269 | optional: true 1270 | typescript: 1271 | optional: true 1272 | vue-tsc: 1273 | optional: true 1274 | 1275 | mlly@1.7.3: 1276 | resolution: {integrity: sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==} 1277 | 1278 | mri@1.2.0: 1279 | resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} 1280 | engines: {node: '>=4'} 1281 | 1282 | ms@2.1.3: 1283 | resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1284 | 1285 | nanoid@3.3.8: 1286 | resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} 1287 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1288 | hasBin: true 1289 | 1290 | node-fetch-native@1.6.4: 1291 | resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} 1292 | 1293 | node-releases@2.0.19: 1294 | resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} 1295 | 1296 | normalize-range@0.1.2: 1297 | resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} 1298 | engines: {node: '>=0.10.0'} 1299 | 1300 | npm-run-path@5.3.0: 1301 | resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} 1302 | engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} 1303 | 1304 | nth-check@2.1.1: 1305 | resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} 1306 | 1307 | nypm@0.3.12: 1308 | resolution: {integrity: sha512-D3pzNDWIvgA+7IORhD/IuWzEk4uXv6GsgOxiid4UU3h9oq5IqV1KtPDi63n4sZJ/xcWlr88c0QM2RgN5VbOhFA==} 1309 | engines: {node: ^14.16.0 || >=16.10.0} 1310 | hasBin: true 1311 | 1312 | ohash@1.1.4: 1313 | resolution: {integrity: sha512-FlDryZAahJmEF3VR3w1KogSEdWX3WhA5GPakFx4J81kEAiHyLMpdLLElS8n8dfNadMgAne/MywcvmogzscVt4g==} 1314 | 1315 | once@1.4.0: 1316 | resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} 1317 | 1318 | onetime@6.0.0: 1319 | resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} 1320 | engines: {node: '>=12'} 1321 | 1322 | path-key@3.1.1: 1323 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1324 | engines: {node: '>=8'} 1325 | 1326 | path-key@4.0.0: 1327 | resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} 1328 | engines: {node: '>=12'} 1329 | 1330 | path-parse@1.0.7: 1331 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} 1332 | 1333 | path-type@4.0.0: 1334 | resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} 1335 | engines: {node: '>=8'} 1336 | 1337 | pathe@1.1.2: 1338 | resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} 1339 | 1340 | pathval@2.0.0: 1341 | resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} 1342 | engines: {node: '>= 14.16'} 1343 | 1344 | perfect-debounce@1.0.0: 1345 | resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} 1346 | 1347 | picocolors@1.1.1: 1348 | resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1349 | 1350 | picomatch@2.3.1: 1351 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1352 | engines: {node: '>=8.6'} 1353 | 1354 | picomatch@4.0.2: 1355 | resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} 1356 | engines: {node: '>=12'} 1357 | 1358 | pkg-types@1.2.1: 1359 | resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} 1360 | 1361 | postcss-calc@10.0.2: 1362 | resolution: {integrity: sha512-DT/Wwm6fCKgpYVI7ZEWuPJ4az8hiEHtCUeYjZXqU7Ou4QqYh1Df2yCQ7Ca6N7xqKPFkxN3fhf+u9KSoOCJNAjg==} 1363 | engines: {node: ^18.12 || ^20.9 || >=22.0} 1364 | peerDependencies: 1365 | postcss: ^8.4.38 1366 | 1367 | postcss-colormin@7.0.2: 1368 | resolution: {integrity: sha512-YntRXNngcvEvDbEjTdRWGU606eZvB5prmHG4BF0yLmVpamXbpsRJzevyy6MZVyuecgzI2AWAlvFi8DAeCqwpvA==} 1369 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1370 | peerDependencies: 1371 | postcss: ^8.4.31 1372 | 1373 | postcss-convert-values@7.0.4: 1374 | resolution: {integrity: sha512-e2LSXPqEHVW6aoGbjV9RsSSNDO3A0rZLCBxN24zvxF25WknMPpX8Dm9UxxThyEbaytzggRuZxaGXqaOhxQ514Q==} 1375 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1376 | peerDependencies: 1377 | postcss: ^8.4.31 1378 | 1379 | postcss-discard-comments@7.0.3: 1380 | resolution: {integrity: sha512-q6fjd4WU4afNhWOA2WltHgCbkRhZPgQe7cXF74fuVB/ge4QbM9HEaOIzGSiMvM+g/cOsNAUGdf2JDzqA2F8iLA==} 1381 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1382 | peerDependencies: 1383 | postcss: ^8.4.31 1384 | 1385 | postcss-discard-duplicates@7.0.1: 1386 | resolution: {integrity: sha512-oZA+v8Jkpu1ct/xbbrntHRsfLGuzoP+cpt0nJe5ED2FQF8n8bJtn7Bo28jSmBYwqgqnqkuSXJfSUEE7if4nClQ==} 1387 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1388 | peerDependencies: 1389 | postcss: ^8.4.31 1390 | 1391 | postcss-discard-empty@7.0.0: 1392 | resolution: {integrity: sha512-e+QzoReTZ8IAwhnSdp/++7gBZ/F+nBq9y6PomfwORfP7q9nBpK5AMP64kOt0bA+lShBFbBDcgpJ3X4etHg4lzA==} 1393 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1394 | peerDependencies: 1395 | postcss: ^8.4.31 1396 | 1397 | postcss-discard-overridden@7.0.0: 1398 | resolution: {integrity: sha512-GmNAzx88u3k2+sBTZrJSDauR0ccpE24omTQCVmaTTZFz1du6AasspjaUPMJ2ud4RslZpoFKyf+6MSPETLojc6w==} 1399 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1400 | peerDependencies: 1401 | postcss: ^8.4.31 1402 | 1403 | postcss-merge-longhand@7.0.4: 1404 | resolution: {integrity: sha512-zer1KoZA54Q8RVHKOY5vMke0cCdNxMP3KBfDerjH/BYHh4nCIh+1Yy0t1pAEQF18ac/4z3OFclO+ZVH8azjR4A==} 1405 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1406 | peerDependencies: 1407 | postcss: ^8.4.31 1408 | 1409 | postcss-merge-rules@7.0.4: 1410 | resolution: {integrity: sha512-ZsaamiMVu7uBYsIdGtKJ64PkcQt6Pcpep/uO90EpLS3dxJi6OXamIobTYcImyXGoW0Wpugh7DSD3XzxZS9JCPg==} 1411 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1412 | peerDependencies: 1413 | postcss: ^8.4.31 1414 | 1415 | postcss-minify-font-values@7.0.0: 1416 | resolution: {integrity: sha512-2ckkZtgT0zG8SMc5aoNwtm5234eUx1GGFJKf2b1bSp8UflqaeFzR50lid4PfqVI9NtGqJ2J4Y7fwvnP/u1cQog==} 1417 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1418 | peerDependencies: 1419 | postcss: ^8.4.31 1420 | 1421 | postcss-minify-gradients@7.0.0: 1422 | resolution: {integrity: sha512-pdUIIdj/C93ryCHew0UgBnL2DtUS3hfFa5XtERrs4x+hmpMYGhbzo6l/Ir5de41O0GaKVpK1ZbDNXSY6GkXvtg==} 1423 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1424 | peerDependencies: 1425 | postcss: ^8.4.31 1426 | 1427 | postcss-minify-params@7.0.2: 1428 | resolution: {integrity: sha512-nyqVLu4MFl9df32zTsdcLqCFfE/z2+f8GE1KHPxWOAmegSo6lpV2GNy5XQvrzwbLmiU7d+fYay4cwto1oNdAaQ==} 1429 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1430 | peerDependencies: 1431 | postcss: ^8.4.31 1432 | 1433 | postcss-minify-selectors@7.0.4: 1434 | resolution: {integrity: sha512-JG55VADcNb4xFCf75hXkzc1rNeURhlo7ugf6JjiiKRfMsKlDzN9CXHZDyiG6x/zGchpjQS+UAgb1d4nqXqOpmA==} 1435 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1436 | peerDependencies: 1437 | postcss: ^8.4.31 1438 | 1439 | postcss-nested@6.2.0: 1440 | resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} 1441 | engines: {node: '>=12.0'} 1442 | peerDependencies: 1443 | postcss: ^8.2.14 1444 | 1445 | postcss-normalize-charset@7.0.0: 1446 | resolution: {integrity: sha512-ABisNUXMeZeDNzCQxPxBCkXexvBrUHV+p7/BXOY+ulxkcjUZO0cp8ekGBwvIh2LbCwnWbyMPNJVtBSdyhM2zYQ==} 1447 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1448 | peerDependencies: 1449 | postcss: ^8.4.31 1450 | 1451 | postcss-normalize-display-values@7.0.0: 1452 | resolution: {integrity: sha512-lnFZzNPeDf5uGMPYgGOw7v0BfB45+irSRz9gHQStdkkhiM0gTfvWkWB5BMxpn0OqgOQuZG/mRlZyJxp0EImr2Q==} 1453 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1454 | peerDependencies: 1455 | postcss: ^8.4.31 1456 | 1457 | postcss-normalize-positions@7.0.0: 1458 | resolution: {integrity: sha512-I0yt8wX529UKIGs2y/9Ybs2CelSvItfmvg/DBIjTnoUSrPxSV7Z0yZ8ShSVtKNaV/wAY+m7bgtyVQLhB00A1NQ==} 1459 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1460 | peerDependencies: 1461 | postcss: ^8.4.31 1462 | 1463 | postcss-normalize-repeat-style@7.0.0: 1464 | resolution: {integrity: sha512-o3uSGYH+2q30ieM3ppu9GTjSXIzOrRdCUn8UOMGNw7Af61bmurHTWI87hRybrP6xDHvOe5WlAj3XzN6vEO8jLw==} 1465 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1466 | peerDependencies: 1467 | postcss: ^8.4.31 1468 | 1469 | postcss-normalize-string@7.0.0: 1470 | resolution: {integrity: sha512-w/qzL212DFVOpMy3UGyxrND+Kb0fvCiBBujiaONIihq7VvtC7bswjWgKQU/w4VcRyDD8gpfqUiBQ4DUOwEJ6Qg==} 1471 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1472 | peerDependencies: 1473 | postcss: ^8.4.31 1474 | 1475 | postcss-normalize-timing-functions@7.0.0: 1476 | resolution: {integrity: sha512-tNgw3YV0LYoRwg43N3lTe3AEWZ66W7Dh7lVEpJbHoKOuHc1sLrzMLMFjP8SNULHaykzsonUEDbKedv8C+7ej6g==} 1477 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1478 | peerDependencies: 1479 | postcss: ^8.4.31 1480 | 1481 | postcss-normalize-unicode@7.0.2: 1482 | resolution: {integrity: sha512-ztisabK5C/+ZWBdYC+Y9JCkp3M9qBv/XFvDtSw0d/XwfT3UaKeW/YTm/MD/QrPNxuecia46vkfEhewjwcYFjkg==} 1483 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1484 | peerDependencies: 1485 | postcss: ^8.4.31 1486 | 1487 | postcss-normalize-url@7.0.0: 1488 | resolution: {integrity: sha512-+d7+PpE+jyPX1hDQZYG+NaFD+Nd2ris6r8fPTBAjE8z/U41n/bib3vze8x7rKs5H1uEw5ppe9IojewouHk0klQ==} 1489 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1490 | peerDependencies: 1491 | postcss: ^8.4.31 1492 | 1493 | postcss-normalize-whitespace@7.0.0: 1494 | resolution: {integrity: sha512-37/toN4wwZErqohedXYqWgvcHUGlT8O/m2jVkAfAe9Bd4MzRqlBmXrJRePH0e9Wgnz2X7KymTgTOaaFizQe3AQ==} 1495 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1496 | peerDependencies: 1497 | postcss: ^8.4.31 1498 | 1499 | postcss-ordered-values@7.0.1: 1500 | resolution: {integrity: sha512-irWScWRL6nRzYmBOXReIKch75RRhNS86UPUAxXdmW/l0FcAsg0lvAXQCby/1lymxn/o0gVa6Rv/0f03eJOwHxw==} 1501 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1502 | peerDependencies: 1503 | postcss: ^8.4.31 1504 | 1505 | postcss-reduce-initial@7.0.2: 1506 | resolution: {integrity: sha512-pOnu9zqQww7dEKf62Nuju6JgsW2V0KRNBHxeKohU+JkHd/GAH5uvoObqFLqkeB2n20mr6yrlWDvo5UBU5GnkfA==} 1507 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1508 | peerDependencies: 1509 | postcss: ^8.4.31 1510 | 1511 | postcss-reduce-transforms@7.0.0: 1512 | resolution: {integrity: sha512-pnt1HKKZ07/idH8cpATX/ujMbtOGhUfE+m8gbqwJE05aTaNw8gbo34a2e3if0xc0dlu75sUOiqvwCGY3fzOHew==} 1513 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1514 | peerDependencies: 1515 | postcss: ^8.4.31 1516 | 1517 | postcss-selector-parser@6.1.2: 1518 | resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} 1519 | engines: {node: '>=4'} 1520 | 1521 | postcss-svgo@7.0.1: 1522 | resolution: {integrity: sha512-0WBUlSL4lhD9rA5k1e5D8EN5wCEyZD6HJk0jIvRxl+FDVOMlJ7DePHYWGGVc5QRqrJ3/06FTXM0bxjmJpmTPSA==} 1523 | engines: {node: ^18.12.0 || ^20.9.0 || >= 18} 1524 | peerDependencies: 1525 | postcss: ^8.4.31 1526 | 1527 | postcss-unique-selectors@7.0.3: 1528 | resolution: {integrity: sha512-J+58u5Ic5T1QjP/LDV9g3Cx4CNOgB5vz+kM6+OxHHhFACdcDeKhBXjQmB7fnIZM12YSTvsL0Opwco83DmacW2g==} 1529 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1530 | peerDependencies: 1531 | postcss: ^8.4.31 1532 | 1533 | postcss-value-parser@4.2.0: 1534 | resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} 1535 | 1536 | postcss@8.4.49: 1537 | resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} 1538 | engines: {node: ^10 || ^12 || >=14} 1539 | 1540 | pretty-bytes@6.1.1: 1541 | resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} 1542 | engines: {node: ^14.13.1 || >=16.0.0} 1543 | 1544 | prompts@2.4.2: 1545 | resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} 1546 | engines: {node: '>= 6'} 1547 | 1548 | queue-microtask@1.2.3: 1549 | resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1550 | 1551 | rc9@2.1.2: 1552 | resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} 1553 | 1554 | readdirp@4.0.2: 1555 | resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} 1556 | engines: {node: '>= 14.16.0'} 1557 | 1558 | resolve@1.22.8: 1559 | resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} 1560 | hasBin: true 1561 | 1562 | reusify@1.0.4: 1563 | resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} 1564 | engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1565 | 1566 | rollup-plugin-dts@6.1.1: 1567 | resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} 1568 | engines: {node: '>=16'} 1569 | peerDependencies: 1570 | rollup: ^3.29.4 || ^4 1571 | typescript: ^4.5 || ^5.0 1572 | 1573 | rollup@3.29.5: 1574 | resolution: {integrity: sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==} 1575 | engines: {node: '>=14.18.0', npm: '>=8.0.0'} 1576 | hasBin: true 1577 | 1578 | rollup@4.28.1: 1579 | resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==} 1580 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1581 | hasBin: true 1582 | 1583 | run-parallel@1.2.0: 1584 | resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1585 | 1586 | scule@1.3.0: 1587 | resolution: {integrity: sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==} 1588 | 1589 | semver@6.3.1: 1590 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 1591 | hasBin: true 1592 | 1593 | semver@7.6.3: 1594 | resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} 1595 | engines: {node: '>=10'} 1596 | hasBin: true 1597 | 1598 | shebang-command@2.0.0: 1599 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1600 | engines: {node: '>=8'} 1601 | 1602 | shebang-regex@3.0.0: 1603 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1604 | engines: {node: '>=8'} 1605 | 1606 | siginfo@2.0.0: 1607 | resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1608 | 1609 | signal-exit@4.1.0: 1610 | resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} 1611 | engines: {node: '>=14'} 1612 | 1613 | sisteransi@1.0.5: 1614 | resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} 1615 | 1616 | slash@4.0.0: 1617 | resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} 1618 | engines: {node: '>=12'} 1619 | 1620 | source-map-js@1.2.1: 1621 | resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1622 | engines: {node: '>=0.10.0'} 1623 | 1624 | stackback@0.0.2: 1625 | resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1626 | 1627 | std-env@3.8.0: 1628 | resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} 1629 | 1630 | strip-final-newline@3.0.0: 1631 | resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} 1632 | engines: {node: '>=12'} 1633 | 1634 | stylehacks@7.0.4: 1635 | resolution: {integrity: sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==} 1636 | engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} 1637 | peerDependencies: 1638 | postcss: ^8.4.31 1639 | 1640 | supports-preserve-symlinks-flag@1.0.0: 1641 | resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} 1642 | engines: {node: '>= 0.4'} 1643 | 1644 | svgo@3.3.2: 1645 | resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} 1646 | engines: {node: '>=14.0.0'} 1647 | hasBin: true 1648 | 1649 | tar@6.2.1: 1650 | resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} 1651 | engines: {node: '>=10'} 1652 | 1653 | tinybench@2.9.0: 1654 | resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1655 | 1656 | tinyexec@0.3.1: 1657 | resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} 1658 | 1659 | tinyglobby@0.2.10: 1660 | resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} 1661 | engines: {node: '>=12.0.0'} 1662 | 1663 | tinypool@1.0.2: 1664 | resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} 1665 | engines: {node: ^18.0.0 || >=20.0.0} 1666 | 1667 | tinyrainbow@1.2.0: 1668 | resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} 1669 | engines: {node: '>=14.0.0'} 1670 | 1671 | tinyspy@3.0.2: 1672 | resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} 1673 | engines: {node: '>=14.0.0'} 1674 | 1675 | to-regex-range@5.0.1: 1676 | resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1677 | engines: {node: '>=8.0'} 1678 | 1679 | typescript@5.8.2: 1680 | resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} 1681 | engines: {node: '>=14.17'} 1682 | hasBin: true 1683 | 1684 | ufo@1.5.4: 1685 | resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} 1686 | 1687 | unbuild@2.0.0: 1688 | resolution: {integrity: sha512-JWCUYx3Oxdzvw2J9kTAp+DKE8df/BnH/JTSj6JyA4SH40ECdFu7FoJJcrm8G92B7TjofQ6GZGjJs50TRxoH6Wg==} 1689 | hasBin: true 1690 | peerDependencies: 1691 | typescript: ^5.1.6 1692 | peerDependenciesMeta: 1693 | typescript: 1694 | optional: true 1695 | 1696 | uncrypto@0.1.3: 1697 | resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} 1698 | 1699 | undici-types@6.20.0: 1700 | resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} 1701 | 1702 | untyped@1.5.1: 1703 | resolution: {integrity: sha512-reBOnkJBFfBZ8pCKaeHgfZLcehXtM6UTxc+vqs1JvCps0c4amLNp3fhdGBZwYp+VLyoY9n3X5KOP7lCyWBUX9A==} 1704 | hasBin: true 1705 | 1706 | update-browserslist-db@1.1.1: 1707 | resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} 1708 | hasBin: true 1709 | peerDependencies: 1710 | browserslist: '>= 4.21.0' 1711 | 1712 | util-deprecate@1.0.2: 1713 | resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} 1714 | 1715 | vite-node@2.1.8: 1716 | resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} 1717 | engines: {node: ^18.0.0 || >=20.0.0} 1718 | hasBin: true 1719 | 1720 | vite@5.4.11: 1721 | resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} 1722 | engines: {node: ^18.0.0 || >=20.0.0} 1723 | hasBin: true 1724 | peerDependencies: 1725 | '@types/node': ^18.0.0 || >=20.0.0 1726 | less: '*' 1727 | lightningcss: ^1.21.0 1728 | sass: '*' 1729 | sass-embedded: '*' 1730 | stylus: '*' 1731 | sugarss: '*' 1732 | terser: ^5.4.0 1733 | peerDependenciesMeta: 1734 | '@types/node': 1735 | optional: true 1736 | less: 1737 | optional: true 1738 | lightningcss: 1739 | optional: true 1740 | sass: 1741 | optional: true 1742 | sass-embedded: 1743 | optional: true 1744 | stylus: 1745 | optional: true 1746 | sugarss: 1747 | optional: true 1748 | terser: 1749 | optional: true 1750 | 1751 | vitest@2.1.8: 1752 | resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==} 1753 | engines: {node: ^18.0.0 || >=20.0.0} 1754 | hasBin: true 1755 | peerDependencies: 1756 | '@edge-runtime/vm': '*' 1757 | '@types/node': ^18.0.0 || >=20.0.0 1758 | '@vitest/browser': 2.1.8 1759 | '@vitest/ui': 2.1.8 1760 | happy-dom: '*' 1761 | jsdom: '*' 1762 | peerDependenciesMeta: 1763 | '@edge-runtime/vm': 1764 | optional: true 1765 | '@types/node': 1766 | optional: true 1767 | '@vitest/browser': 1768 | optional: true 1769 | '@vitest/ui': 1770 | optional: true 1771 | happy-dom: 1772 | optional: true 1773 | jsdom: 1774 | optional: true 1775 | 1776 | webidl-conversions@7.0.0: 1777 | resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} 1778 | engines: {node: '>=12'} 1779 | 1780 | whatwg-mimetype@3.0.0: 1781 | resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} 1782 | engines: {node: '>=12'} 1783 | 1784 | which@2.0.2: 1785 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1786 | engines: {node: '>= 8'} 1787 | hasBin: true 1788 | 1789 | why-is-node-running@2.3.0: 1790 | resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1791 | engines: {node: '>=8'} 1792 | hasBin: true 1793 | 1794 | wrappy@1.0.2: 1795 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} 1796 | 1797 | yallist@3.1.1: 1798 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 1799 | 1800 | yallist@4.0.0: 1801 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} 1802 | 1803 | snapshots: 1804 | 1805 | '@ampproject/remapping@2.3.0': 1806 | dependencies: 1807 | '@jridgewell/gen-mapping': 0.3.5 1808 | '@jridgewell/trace-mapping': 0.3.25 1809 | 1810 | '@babel/code-frame@7.26.2': 1811 | dependencies: 1812 | '@babel/helper-validator-identifier': 7.25.9 1813 | js-tokens: 4.0.0 1814 | picocolors: 1.1.1 1815 | 1816 | '@babel/compat-data@7.26.3': {} 1817 | 1818 | '@babel/core@7.26.0': 1819 | dependencies: 1820 | '@ampproject/remapping': 2.3.0 1821 | '@babel/code-frame': 7.26.2 1822 | '@babel/generator': 7.26.3 1823 | '@babel/helper-compilation-targets': 7.25.9 1824 | '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) 1825 | '@babel/helpers': 7.26.0 1826 | '@babel/parser': 7.26.3 1827 | '@babel/template': 7.25.9 1828 | '@babel/traverse': 7.26.4 1829 | '@babel/types': 7.26.3 1830 | convert-source-map: 2.0.0 1831 | debug: 4.4.0 1832 | gensync: 1.0.0-beta.2 1833 | json5: 2.2.3 1834 | semver: 6.3.1 1835 | transitivePeerDependencies: 1836 | - supports-color 1837 | 1838 | '@babel/generator@7.26.3': 1839 | dependencies: 1840 | '@babel/parser': 7.26.3 1841 | '@babel/types': 7.26.3 1842 | '@jridgewell/gen-mapping': 0.3.5 1843 | '@jridgewell/trace-mapping': 0.3.25 1844 | jsesc: 3.0.2 1845 | 1846 | '@babel/helper-compilation-targets@7.25.9': 1847 | dependencies: 1848 | '@babel/compat-data': 7.26.3 1849 | '@babel/helper-validator-option': 7.25.9 1850 | browserslist: 4.24.2 1851 | lru-cache: 5.1.1 1852 | semver: 6.3.1 1853 | 1854 | '@babel/helper-module-imports@7.25.9': 1855 | dependencies: 1856 | '@babel/traverse': 7.26.4 1857 | '@babel/types': 7.26.3 1858 | transitivePeerDependencies: 1859 | - supports-color 1860 | 1861 | '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': 1862 | dependencies: 1863 | '@babel/core': 7.26.0 1864 | '@babel/helper-module-imports': 7.25.9 1865 | '@babel/helper-validator-identifier': 7.25.9 1866 | '@babel/traverse': 7.26.4 1867 | transitivePeerDependencies: 1868 | - supports-color 1869 | 1870 | '@babel/helper-string-parser@7.25.9': {} 1871 | 1872 | '@babel/helper-validator-identifier@7.25.9': {} 1873 | 1874 | '@babel/helper-validator-option@7.25.9': {} 1875 | 1876 | '@babel/helpers@7.26.0': 1877 | dependencies: 1878 | '@babel/template': 7.25.9 1879 | '@babel/types': 7.26.3 1880 | 1881 | '@babel/parser@7.26.3': 1882 | dependencies: 1883 | '@babel/types': 7.26.3 1884 | 1885 | '@babel/standalone@7.26.4': {} 1886 | 1887 | '@babel/template@7.25.9': 1888 | dependencies: 1889 | '@babel/code-frame': 7.26.2 1890 | '@babel/parser': 7.26.3 1891 | '@babel/types': 7.26.3 1892 | 1893 | '@babel/traverse@7.26.4': 1894 | dependencies: 1895 | '@babel/code-frame': 7.26.2 1896 | '@babel/generator': 7.26.3 1897 | '@babel/parser': 7.26.3 1898 | '@babel/template': 7.25.9 1899 | '@babel/types': 7.26.3 1900 | debug: 4.4.0 1901 | globals: 11.12.0 1902 | transitivePeerDependencies: 1903 | - supports-color 1904 | 1905 | '@babel/types@7.26.3': 1906 | dependencies: 1907 | '@babel/helper-string-parser': 7.25.9 1908 | '@babel/helper-validator-identifier': 7.25.9 1909 | 1910 | '@biomejs/biome@1.9.4': 1911 | optionalDependencies: 1912 | '@biomejs/cli-darwin-arm64': 1.9.4 1913 | '@biomejs/cli-darwin-x64': 1.9.4 1914 | '@biomejs/cli-linux-arm64': 1.9.4 1915 | '@biomejs/cli-linux-arm64-musl': 1.9.4 1916 | '@biomejs/cli-linux-x64': 1.9.4 1917 | '@biomejs/cli-linux-x64-musl': 1.9.4 1918 | '@biomejs/cli-win32-arm64': 1.9.4 1919 | '@biomejs/cli-win32-x64': 1.9.4 1920 | 1921 | '@biomejs/cli-darwin-arm64@1.9.4': 1922 | optional: true 1923 | 1924 | '@biomejs/cli-darwin-x64@1.9.4': 1925 | optional: true 1926 | 1927 | '@biomejs/cli-linux-arm64-musl@1.9.4': 1928 | optional: true 1929 | 1930 | '@biomejs/cli-linux-arm64@1.9.4': 1931 | optional: true 1932 | 1933 | '@biomejs/cli-linux-x64-musl@1.9.4': 1934 | optional: true 1935 | 1936 | '@biomejs/cli-linux-x64@1.9.4': 1937 | optional: true 1938 | 1939 | '@biomejs/cli-win32-arm64@1.9.4': 1940 | optional: true 1941 | 1942 | '@biomejs/cli-win32-x64@1.9.4': 1943 | optional: true 1944 | 1945 | '@esbuild/aix-ppc64@0.19.12': 1946 | optional: true 1947 | 1948 | '@esbuild/aix-ppc64@0.21.5': 1949 | optional: true 1950 | 1951 | '@esbuild/aix-ppc64@0.24.0': 1952 | optional: true 1953 | 1954 | '@esbuild/android-arm64@0.19.12': 1955 | optional: true 1956 | 1957 | '@esbuild/android-arm64@0.21.5': 1958 | optional: true 1959 | 1960 | '@esbuild/android-arm64@0.24.0': 1961 | optional: true 1962 | 1963 | '@esbuild/android-arm@0.19.12': 1964 | optional: true 1965 | 1966 | '@esbuild/android-arm@0.21.5': 1967 | optional: true 1968 | 1969 | '@esbuild/android-arm@0.24.0': 1970 | optional: true 1971 | 1972 | '@esbuild/android-x64@0.19.12': 1973 | optional: true 1974 | 1975 | '@esbuild/android-x64@0.21.5': 1976 | optional: true 1977 | 1978 | '@esbuild/android-x64@0.24.0': 1979 | optional: true 1980 | 1981 | '@esbuild/darwin-arm64@0.19.12': 1982 | optional: true 1983 | 1984 | '@esbuild/darwin-arm64@0.21.5': 1985 | optional: true 1986 | 1987 | '@esbuild/darwin-arm64@0.24.0': 1988 | optional: true 1989 | 1990 | '@esbuild/darwin-x64@0.19.12': 1991 | optional: true 1992 | 1993 | '@esbuild/darwin-x64@0.21.5': 1994 | optional: true 1995 | 1996 | '@esbuild/darwin-x64@0.24.0': 1997 | optional: true 1998 | 1999 | '@esbuild/freebsd-arm64@0.19.12': 2000 | optional: true 2001 | 2002 | '@esbuild/freebsd-arm64@0.21.5': 2003 | optional: true 2004 | 2005 | '@esbuild/freebsd-arm64@0.24.0': 2006 | optional: true 2007 | 2008 | '@esbuild/freebsd-x64@0.19.12': 2009 | optional: true 2010 | 2011 | '@esbuild/freebsd-x64@0.21.5': 2012 | optional: true 2013 | 2014 | '@esbuild/freebsd-x64@0.24.0': 2015 | optional: true 2016 | 2017 | '@esbuild/linux-arm64@0.19.12': 2018 | optional: true 2019 | 2020 | '@esbuild/linux-arm64@0.21.5': 2021 | optional: true 2022 | 2023 | '@esbuild/linux-arm64@0.24.0': 2024 | optional: true 2025 | 2026 | '@esbuild/linux-arm@0.19.12': 2027 | optional: true 2028 | 2029 | '@esbuild/linux-arm@0.21.5': 2030 | optional: true 2031 | 2032 | '@esbuild/linux-arm@0.24.0': 2033 | optional: true 2034 | 2035 | '@esbuild/linux-ia32@0.19.12': 2036 | optional: true 2037 | 2038 | '@esbuild/linux-ia32@0.21.5': 2039 | optional: true 2040 | 2041 | '@esbuild/linux-ia32@0.24.0': 2042 | optional: true 2043 | 2044 | '@esbuild/linux-loong64@0.19.12': 2045 | optional: true 2046 | 2047 | '@esbuild/linux-loong64@0.21.5': 2048 | optional: true 2049 | 2050 | '@esbuild/linux-loong64@0.24.0': 2051 | optional: true 2052 | 2053 | '@esbuild/linux-mips64el@0.19.12': 2054 | optional: true 2055 | 2056 | '@esbuild/linux-mips64el@0.21.5': 2057 | optional: true 2058 | 2059 | '@esbuild/linux-mips64el@0.24.0': 2060 | optional: true 2061 | 2062 | '@esbuild/linux-ppc64@0.19.12': 2063 | optional: true 2064 | 2065 | '@esbuild/linux-ppc64@0.21.5': 2066 | optional: true 2067 | 2068 | '@esbuild/linux-ppc64@0.24.0': 2069 | optional: true 2070 | 2071 | '@esbuild/linux-riscv64@0.19.12': 2072 | optional: true 2073 | 2074 | '@esbuild/linux-riscv64@0.21.5': 2075 | optional: true 2076 | 2077 | '@esbuild/linux-riscv64@0.24.0': 2078 | optional: true 2079 | 2080 | '@esbuild/linux-s390x@0.19.12': 2081 | optional: true 2082 | 2083 | '@esbuild/linux-s390x@0.21.5': 2084 | optional: true 2085 | 2086 | '@esbuild/linux-s390x@0.24.0': 2087 | optional: true 2088 | 2089 | '@esbuild/linux-x64@0.19.12': 2090 | optional: true 2091 | 2092 | '@esbuild/linux-x64@0.21.5': 2093 | optional: true 2094 | 2095 | '@esbuild/linux-x64@0.24.0': 2096 | optional: true 2097 | 2098 | '@esbuild/netbsd-x64@0.19.12': 2099 | optional: true 2100 | 2101 | '@esbuild/netbsd-x64@0.21.5': 2102 | optional: true 2103 | 2104 | '@esbuild/netbsd-x64@0.24.0': 2105 | optional: true 2106 | 2107 | '@esbuild/openbsd-arm64@0.24.0': 2108 | optional: true 2109 | 2110 | '@esbuild/openbsd-x64@0.19.12': 2111 | optional: true 2112 | 2113 | '@esbuild/openbsd-x64@0.21.5': 2114 | optional: true 2115 | 2116 | '@esbuild/openbsd-x64@0.24.0': 2117 | optional: true 2118 | 2119 | '@esbuild/sunos-x64@0.19.12': 2120 | optional: true 2121 | 2122 | '@esbuild/sunos-x64@0.21.5': 2123 | optional: true 2124 | 2125 | '@esbuild/sunos-x64@0.24.0': 2126 | optional: true 2127 | 2128 | '@esbuild/win32-arm64@0.19.12': 2129 | optional: true 2130 | 2131 | '@esbuild/win32-arm64@0.21.5': 2132 | optional: true 2133 | 2134 | '@esbuild/win32-arm64@0.24.0': 2135 | optional: true 2136 | 2137 | '@esbuild/win32-ia32@0.19.12': 2138 | optional: true 2139 | 2140 | '@esbuild/win32-ia32@0.21.5': 2141 | optional: true 2142 | 2143 | '@esbuild/win32-ia32@0.24.0': 2144 | optional: true 2145 | 2146 | '@esbuild/win32-x64@0.19.12': 2147 | optional: true 2148 | 2149 | '@esbuild/win32-x64@0.21.5': 2150 | optional: true 2151 | 2152 | '@esbuild/win32-x64@0.24.0': 2153 | optional: true 2154 | 2155 | '@jridgewell/gen-mapping@0.3.5': 2156 | dependencies: 2157 | '@jridgewell/set-array': 1.2.1 2158 | '@jridgewell/sourcemap-codec': 1.5.0 2159 | '@jridgewell/trace-mapping': 0.3.25 2160 | 2161 | '@jridgewell/resolve-uri@3.1.2': {} 2162 | 2163 | '@jridgewell/set-array@1.2.1': {} 2164 | 2165 | '@jridgewell/sourcemap-codec@1.5.0': {} 2166 | 2167 | '@jridgewell/trace-mapping@0.3.25': 2168 | dependencies: 2169 | '@jridgewell/resolve-uri': 3.1.2 2170 | '@jridgewell/sourcemap-codec': 1.5.0 2171 | 2172 | '@nodelib/fs.scandir@2.1.5': 2173 | dependencies: 2174 | '@nodelib/fs.stat': 2.0.5 2175 | run-parallel: 1.2.0 2176 | 2177 | '@nodelib/fs.stat@2.0.5': {} 2178 | 2179 | '@nodelib/fs.walk@1.2.8': 2180 | dependencies: 2181 | '@nodelib/fs.scandir': 2.1.5 2182 | fastq: 1.17.1 2183 | 2184 | '@rollup/plugin-alias@5.1.1(rollup@3.29.5)': 2185 | optionalDependencies: 2186 | rollup: 3.29.5 2187 | 2188 | '@rollup/plugin-commonjs@25.0.8(rollup@3.29.5)': 2189 | dependencies: 2190 | '@rollup/pluginutils': 5.1.3(rollup@3.29.5) 2191 | commondir: 1.0.1 2192 | estree-walker: 2.0.2 2193 | glob: 8.1.0 2194 | is-reference: 1.2.1 2195 | magic-string: 0.30.15 2196 | optionalDependencies: 2197 | rollup: 3.29.5 2198 | 2199 | '@rollup/plugin-json@6.1.0(rollup@3.29.5)': 2200 | dependencies: 2201 | '@rollup/pluginutils': 5.1.3(rollup@3.29.5) 2202 | optionalDependencies: 2203 | rollup: 3.29.5 2204 | 2205 | '@rollup/plugin-node-resolve@15.3.0(rollup@3.29.5)': 2206 | dependencies: 2207 | '@rollup/pluginutils': 5.1.3(rollup@3.29.5) 2208 | '@types/resolve': 1.20.2 2209 | deepmerge: 4.3.1 2210 | is-module: 1.0.0 2211 | resolve: 1.22.8 2212 | optionalDependencies: 2213 | rollup: 3.29.5 2214 | 2215 | '@rollup/plugin-replace@5.0.7(rollup@3.29.5)': 2216 | dependencies: 2217 | '@rollup/pluginutils': 5.1.3(rollup@3.29.5) 2218 | magic-string: 0.30.15 2219 | optionalDependencies: 2220 | rollup: 3.29.5 2221 | 2222 | '@rollup/pluginutils@5.1.3(rollup@3.29.5)': 2223 | dependencies: 2224 | '@types/estree': 1.0.6 2225 | estree-walker: 2.0.2 2226 | picomatch: 4.0.2 2227 | optionalDependencies: 2228 | rollup: 3.29.5 2229 | 2230 | '@rollup/rollup-android-arm-eabi@4.28.1': 2231 | optional: true 2232 | 2233 | '@rollup/rollup-android-arm64@4.28.1': 2234 | optional: true 2235 | 2236 | '@rollup/rollup-darwin-arm64@4.28.1': 2237 | optional: true 2238 | 2239 | '@rollup/rollup-darwin-x64@4.28.1': 2240 | optional: true 2241 | 2242 | '@rollup/rollup-freebsd-arm64@4.28.1': 2243 | optional: true 2244 | 2245 | '@rollup/rollup-freebsd-x64@4.28.1': 2246 | optional: true 2247 | 2248 | '@rollup/rollup-linux-arm-gnueabihf@4.28.1': 2249 | optional: true 2250 | 2251 | '@rollup/rollup-linux-arm-musleabihf@4.28.1': 2252 | optional: true 2253 | 2254 | '@rollup/rollup-linux-arm64-gnu@4.28.1': 2255 | optional: true 2256 | 2257 | '@rollup/rollup-linux-arm64-musl@4.28.1': 2258 | optional: true 2259 | 2260 | '@rollup/rollup-linux-loongarch64-gnu@4.28.1': 2261 | optional: true 2262 | 2263 | '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': 2264 | optional: true 2265 | 2266 | '@rollup/rollup-linux-riscv64-gnu@4.28.1': 2267 | optional: true 2268 | 2269 | '@rollup/rollup-linux-s390x-gnu@4.28.1': 2270 | optional: true 2271 | 2272 | '@rollup/rollup-linux-x64-gnu@4.28.1': 2273 | optional: true 2274 | 2275 | '@rollup/rollup-linux-x64-musl@4.28.1': 2276 | optional: true 2277 | 2278 | '@rollup/rollup-win32-arm64-msvc@4.28.1': 2279 | optional: true 2280 | 2281 | '@rollup/rollup-win32-ia32-msvc@4.28.1': 2282 | optional: true 2283 | 2284 | '@rollup/rollup-win32-x64-msvc@4.28.1': 2285 | optional: true 2286 | 2287 | '@trysound/sax@0.2.0': {} 2288 | 2289 | '@types/estree@1.0.6': {} 2290 | 2291 | '@types/node@22.10.1': 2292 | dependencies: 2293 | undici-types: 6.20.0 2294 | 2295 | '@types/resolve@1.20.2': {} 2296 | 2297 | '@vitest/expect@2.1.8': 2298 | dependencies: 2299 | '@vitest/spy': 2.1.8 2300 | '@vitest/utils': 2.1.8 2301 | chai: 5.1.2 2302 | tinyrainbow: 1.2.0 2303 | 2304 | '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@22.10.1))': 2305 | dependencies: 2306 | '@vitest/spy': 2.1.8 2307 | estree-walker: 3.0.3 2308 | magic-string: 0.30.15 2309 | optionalDependencies: 2310 | vite: 5.4.11(@types/node@22.10.1) 2311 | 2312 | '@vitest/pretty-format@2.1.8': 2313 | dependencies: 2314 | tinyrainbow: 1.2.0 2315 | 2316 | '@vitest/runner@2.1.8': 2317 | dependencies: 2318 | '@vitest/utils': 2.1.8 2319 | pathe: 1.1.2 2320 | 2321 | '@vitest/snapshot@2.1.8': 2322 | dependencies: 2323 | '@vitest/pretty-format': 2.1.8 2324 | magic-string: 0.30.15 2325 | pathe: 1.1.2 2326 | 2327 | '@vitest/spy@2.1.8': 2328 | dependencies: 2329 | tinyspy: 3.0.2 2330 | 2331 | '@vitest/utils@2.1.8': 2332 | dependencies: 2333 | '@vitest/pretty-format': 2.1.8 2334 | loupe: 3.1.2 2335 | tinyrainbow: 1.2.0 2336 | 2337 | acorn@8.14.0: {} 2338 | 2339 | argparse@2.0.1: {} 2340 | 2341 | assertion-error@2.0.1: {} 2342 | 2343 | autoprefixer@10.4.20(postcss@8.4.49): 2344 | dependencies: 2345 | browserslist: 4.24.2 2346 | caniuse-lite: 1.0.30001687 2347 | fraction.js: 4.3.7 2348 | normalize-range: 0.1.2 2349 | picocolors: 1.1.1 2350 | postcss: 8.4.49 2351 | postcss-value-parser: 4.2.0 2352 | 2353 | balanced-match@1.0.2: {} 2354 | 2355 | boolbase@1.0.0: {} 2356 | 2357 | brace-expansion@2.0.1: 2358 | dependencies: 2359 | balanced-match: 1.0.2 2360 | 2361 | braces@3.0.3: 2362 | dependencies: 2363 | fill-range: 7.1.1 2364 | 2365 | browserslist@4.24.2: 2366 | dependencies: 2367 | caniuse-lite: 1.0.30001687 2368 | electron-to-chromium: 1.5.72 2369 | node-releases: 2.0.19 2370 | update-browserslist-db: 1.1.1(browserslist@4.24.2) 2371 | 2372 | bumpp@9.9.0: 2373 | dependencies: 2374 | c12: 2.0.1 2375 | cac: 6.7.14 2376 | escalade: 3.2.0 2377 | js-yaml: 4.1.0 2378 | jsonc-parser: 3.3.1 2379 | prompts: 2.4.2 2380 | semver: 7.6.3 2381 | tinyexec: 0.3.1 2382 | tinyglobby: 0.2.10 2383 | transitivePeerDependencies: 2384 | - magicast 2385 | 2386 | c12@2.0.1: 2387 | dependencies: 2388 | chokidar: 4.0.1 2389 | confbox: 0.1.8 2390 | defu: 6.1.4 2391 | dotenv: 16.4.7 2392 | giget: 1.2.3 2393 | jiti: 2.4.1 2394 | mlly: 1.7.3 2395 | ohash: 1.1.4 2396 | pathe: 1.1.2 2397 | perfect-debounce: 1.0.0 2398 | pkg-types: 1.2.1 2399 | rc9: 2.1.2 2400 | 2401 | cac@6.7.14: {} 2402 | 2403 | caniuse-api@3.0.0: 2404 | dependencies: 2405 | browserslist: 4.24.2 2406 | caniuse-lite: 1.0.30001687 2407 | lodash.memoize: 4.1.2 2408 | lodash.uniq: 4.5.0 2409 | 2410 | caniuse-lite@1.0.30001687: {} 2411 | 2412 | chai@5.1.2: 2413 | dependencies: 2414 | assertion-error: 2.0.1 2415 | check-error: 2.1.1 2416 | deep-eql: 5.0.2 2417 | loupe: 3.1.2 2418 | pathval: 2.0.0 2419 | 2420 | chalk@5.3.0: {} 2421 | 2422 | check-error@2.1.1: {} 2423 | 2424 | chokidar@4.0.1: 2425 | dependencies: 2426 | readdirp: 4.0.2 2427 | 2428 | chownr@2.0.0: {} 2429 | 2430 | citty@0.1.6: 2431 | dependencies: 2432 | consola: 3.2.3 2433 | 2434 | colord@2.9.3: {} 2435 | 2436 | commander@7.2.0: {} 2437 | 2438 | commondir@1.0.1: {} 2439 | 2440 | confbox@0.1.8: {} 2441 | 2442 | consola@3.2.3: {} 2443 | 2444 | convert-source-map@2.0.0: {} 2445 | 2446 | cross-spawn@7.0.6: 2447 | dependencies: 2448 | path-key: 3.1.1 2449 | shebang-command: 2.0.0 2450 | which: 2.0.2 2451 | 2452 | css-declaration-sorter@7.2.0(postcss@8.4.49): 2453 | dependencies: 2454 | postcss: 8.4.49 2455 | 2456 | css-select@5.1.0: 2457 | dependencies: 2458 | boolbase: 1.0.0 2459 | css-what: 6.1.0 2460 | domhandler: 5.0.3 2461 | domutils: 3.1.0 2462 | nth-check: 2.1.1 2463 | 2464 | css-tree@2.2.1: 2465 | dependencies: 2466 | mdn-data: 2.0.28 2467 | source-map-js: 1.2.1 2468 | 2469 | css-tree@2.3.1: 2470 | dependencies: 2471 | mdn-data: 2.0.30 2472 | source-map-js: 1.2.1 2473 | 2474 | css-what@6.1.0: {} 2475 | 2476 | cssesc@3.0.0: {} 2477 | 2478 | cssnano-preset-default@7.0.6(postcss@8.4.49): 2479 | dependencies: 2480 | browserslist: 4.24.2 2481 | css-declaration-sorter: 7.2.0(postcss@8.4.49) 2482 | cssnano-utils: 5.0.0(postcss@8.4.49) 2483 | postcss: 8.4.49 2484 | postcss-calc: 10.0.2(postcss@8.4.49) 2485 | postcss-colormin: 7.0.2(postcss@8.4.49) 2486 | postcss-convert-values: 7.0.4(postcss@8.4.49) 2487 | postcss-discard-comments: 7.0.3(postcss@8.4.49) 2488 | postcss-discard-duplicates: 7.0.1(postcss@8.4.49) 2489 | postcss-discard-empty: 7.0.0(postcss@8.4.49) 2490 | postcss-discard-overridden: 7.0.0(postcss@8.4.49) 2491 | postcss-merge-longhand: 7.0.4(postcss@8.4.49) 2492 | postcss-merge-rules: 7.0.4(postcss@8.4.49) 2493 | postcss-minify-font-values: 7.0.0(postcss@8.4.49) 2494 | postcss-minify-gradients: 7.0.0(postcss@8.4.49) 2495 | postcss-minify-params: 7.0.2(postcss@8.4.49) 2496 | postcss-minify-selectors: 7.0.4(postcss@8.4.49) 2497 | postcss-normalize-charset: 7.0.0(postcss@8.4.49) 2498 | postcss-normalize-display-values: 7.0.0(postcss@8.4.49) 2499 | postcss-normalize-positions: 7.0.0(postcss@8.4.49) 2500 | postcss-normalize-repeat-style: 7.0.0(postcss@8.4.49) 2501 | postcss-normalize-string: 7.0.0(postcss@8.4.49) 2502 | postcss-normalize-timing-functions: 7.0.0(postcss@8.4.49) 2503 | postcss-normalize-unicode: 7.0.2(postcss@8.4.49) 2504 | postcss-normalize-url: 7.0.0(postcss@8.4.49) 2505 | postcss-normalize-whitespace: 7.0.0(postcss@8.4.49) 2506 | postcss-ordered-values: 7.0.1(postcss@8.4.49) 2507 | postcss-reduce-initial: 7.0.2(postcss@8.4.49) 2508 | postcss-reduce-transforms: 7.0.0(postcss@8.4.49) 2509 | postcss-svgo: 7.0.1(postcss@8.4.49) 2510 | postcss-unique-selectors: 7.0.3(postcss@8.4.49) 2511 | 2512 | cssnano-utils@5.0.0(postcss@8.4.49): 2513 | dependencies: 2514 | postcss: 8.4.49 2515 | 2516 | cssnano@7.0.6(postcss@8.4.49): 2517 | dependencies: 2518 | cssnano-preset-default: 7.0.6(postcss@8.4.49) 2519 | lilconfig: 3.1.3 2520 | postcss: 8.4.49 2521 | 2522 | csso@5.0.5: 2523 | dependencies: 2524 | css-tree: 2.2.1 2525 | 2526 | debug@4.4.0: 2527 | dependencies: 2528 | ms: 2.1.3 2529 | 2530 | deep-eql@5.0.2: {} 2531 | 2532 | deepmerge@4.3.1: {} 2533 | 2534 | defu@6.1.4: {} 2535 | 2536 | destr@2.0.3: {} 2537 | 2538 | dir-glob@3.0.1: 2539 | dependencies: 2540 | path-type: 4.0.0 2541 | 2542 | dom-serializer@2.0.0: 2543 | dependencies: 2544 | domelementtype: 2.3.0 2545 | domhandler: 5.0.3 2546 | entities: 4.5.0 2547 | 2548 | domelementtype@2.3.0: {} 2549 | 2550 | domhandler@5.0.3: 2551 | dependencies: 2552 | domelementtype: 2.3.0 2553 | 2554 | domutils@3.1.0: 2555 | dependencies: 2556 | dom-serializer: 2.0.0 2557 | domelementtype: 2.3.0 2558 | domhandler: 5.0.3 2559 | 2560 | dotenv@16.4.7: {} 2561 | 2562 | electron-to-chromium@1.5.72: {} 2563 | 2564 | entities@4.5.0: {} 2565 | 2566 | es-module-lexer@1.5.4: {} 2567 | 2568 | esbuild@0.19.12: 2569 | optionalDependencies: 2570 | '@esbuild/aix-ppc64': 0.19.12 2571 | '@esbuild/android-arm': 0.19.12 2572 | '@esbuild/android-arm64': 0.19.12 2573 | '@esbuild/android-x64': 0.19.12 2574 | '@esbuild/darwin-arm64': 0.19.12 2575 | '@esbuild/darwin-x64': 0.19.12 2576 | '@esbuild/freebsd-arm64': 0.19.12 2577 | '@esbuild/freebsd-x64': 0.19.12 2578 | '@esbuild/linux-arm': 0.19.12 2579 | '@esbuild/linux-arm64': 0.19.12 2580 | '@esbuild/linux-ia32': 0.19.12 2581 | '@esbuild/linux-loong64': 0.19.12 2582 | '@esbuild/linux-mips64el': 0.19.12 2583 | '@esbuild/linux-ppc64': 0.19.12 2584 | '@esbuild/linux-riscv64': 0.19.12 2585 | '@esbuild/linux-s390x': 0.19.12 2586 | '@esbuild/linux-x64': 0.19.12 2587 | '@esbuild/netbsd-x64': 0.19.12 2588 | '@esbuild/openbsd-x64': 0.19.12 2589 | '@esbuild/sunos-x64': 0.19.12 2590 | '@esbuild/win32-arm64': 0.19.12 2591 | '@esbuild/win32-ia32': 0.19.12 2592 | '@esbuild/win32-x64': 0.19.12 2593 | 2594 | esbuild@0.21.5: 2595 | optionalDependencies: 2596 | '@esbuild/aix-ppc64': 0.21.5 2597 | '@esbuild/android-arm': 0.21.5 2598 | '@esbuild/android-arm64': 0.21.5 2599 | '@esbuild/android-x64': 0.21.5 2600 | '@esbuild/darwin-arm64': 0.21.5 2601 | '@esbuild/darwin-x64': 0.21.5 2602 | '@esbuild/freebsd-arm64': 0.21.5 2603 | '@esbuild/freebsd-x64': 0.21.5 2604 | '@esbuild/linux-arm': 0.21.5 2605 | '@esbuild/linux-arm64': 0.21.5 2606 | '@esbuild/linux-ia32': 0.21.5 2607 | '@esbuild/linux-loong64': 0.21.5 2608 | '@esbuild/linux-mips64el': 0.21.5 2609 | '@esbuild/linux-ppc64': 0.21.5 2610 | '@esbuild/linux-riscv64': 0.21.5 2611 | '@esbuild/linux-s390x': 0.21.5 2612 | '@esbuild/linux-x64': 0.21.5 2613 | '@esbuild/netbsd-x64': 0.21.5 2614 | '@esbuild/openbsd-x64': 0.21.5 2615 | '@esbuild/sunos-x64': 0.21.5 2616 | '@esbuild/win32-arm64': 0.21.5 2617 | '@esbuild/win32-ia32': 0.21.5 2618 | '@esbuild/win32-x64': 0.21.5 2619 | 2620 | esbuild@0.24.0: 2621 | optionalDependencies: 2622 | '@esbuild/aix-ppc64': 0.24.0 2623 | '@esbuild/android-arm': 0.24.0 2624 | '@esbuild/android-arm64': 0.24.0 2625 | '@esbuild/android-x64': 0.24.0 2626 | '@esbuild/darwin-arm64': 0.24.0 2627 | '@esbuild/darwin-x64': 0.24.0 2628 | '@esbuild/freebsd-arm64': 0.24.0 2629 | '@esbuild/freebsd-x64': 0.24.0 2630 | '@esbuild/linux-arm': 0.24.0 2631 | '@esbuild/linux-arm64': 0.24.0 2632 | '@esbuild/linux-ia32': 0.24.0 2633 | '@esbuild/linux-loong64': 0.24.0 2634 | '@esbuild/linux-mips64el': 0.24.0 2635 | '@esbuild/linux-ppc64': 0.24.0 2636 | '@esbuild/linux-riscv64': 0.24.0 2637 | '@esbuild/linux-s390x': 0.24.0 2638 | '@esbuild/linux-x64': 0.24.0 2639 | '@esbuild/netbsd-x64': 0.24.0 2640 | '@esbuild/openbsd-arm64': 0.24.0 2641 | '@esbuild/openbsd-x64': 0.24.0 2642 | '@esbuild/sunos-x64': 0.24.0 2643 | '@esbuild/win32-arm64': 0.24.0 2644 | '@esbuild/win32-ia32': 0.24.0 2645 | '@esbuild/win32-x64': 0.24.0 2646 | 2647 | escalade@3.2.0: {} 2648 | 2649 | estree-walker@2.0.2: {} 2650 | 2651 | estree-walker@3.0.3: 2652 | dependencies: 2653 | '@types/estree': 1.0.6 2654 | 2655 | execa@8.0.1: 2656 | dependencies: 2657 | cross-spawn: 7.0.6 2658 | get-stream: 8.0.1 2659 | human-signals: 5.0.0 2660 | is-stream: 3.0.0 2661 | merge-stream: 2.0.0 2662 | npm-run-path: 5.3.0 2663 | onetime: 6.0.0 2664 | signal-exit: 4.1.0 2665 | strip-final-newline: 3.0.0 2666 | 2667 | expect-type@1.1.0: {} 2668 | 2669 | fast-glob@3.3.2: 2670 | dependencies: 2671 | '@nodelib/fs.stat': 2.0.5 2672 | '@nodelib/fs.walk': 1.2.8 2673 | glob-parent: 5.1.2 2674 | merge2: 1.4.1 2675 | micromatch: 4.0.8 2676 | 2677 | fastq@1.17.1: 2678 | dependencies: 2679 | reusify: 1.0.4 2680 | 2681 | fdir@6.4.2(picomatch@4.0.2): 2682 | optionalDependencies: 2683 | picomatch: 4.0.2 2684 | 2685 | fill-range@7.1.1: 2686 | dependencies: 2687 | to-regex-range: 5.0.1 2688 | 2689 | fraction.js@4.3.7: {} 2690 | 2691 | fs-minipass@2.1.0: 2692 | dependencies: 2693 | minipass: 3.3.6 2694 | 2695 | fs.realpath@1.0.0: {} 2696 | 2697 | fsevents@2.3.3: 2698 | optional: true 2699 | 2700 | function-bind@1.1.2: {} 2701 | 2702 | gensync@1.0.0-beta.2: {} 2703 | 2704 | get-stream@8.0.1: {} 2705 | 2706 | giget@1.2.3: 2707 | dependencies: 2708 | citty: 0.1.6 2709 | consola: 3.2.3 2710 | defu: 6.1.4 2711 | node-fetch-native: 1.6.4 2712 | nypm: 0.3.12 2713 | ohash: 1.1.4 2714 | pathe: 1.1.2 2715 | tar: 6.2.1 2716 | 2717 | glob-parent@5.1.2: 2718 | dependencies: 2719 | is-glob: 4.0.3 2720 | 2721 | glob@8.1.0: 2722 | dependencies: 2723 | fs.realpath: 1.0.0 2724 | inflight: 1.0.6 2725 | inherits: 2.0.4 2726 | minimatch: 5.1.6 2727 | once: 1.4.0 2728 | 2729 | globals@11.12.0: {} 2730 | 2731 | globby@13.2.2: 2732 | dependencies: 2733 | dir-glob: 3.0.1 2734 | fast-glob: 3.3.2 2735 | ignore: 5.3.2 2736 | merge2: 1.4.1 2737 | slash: 4.0.0 2738 | 2739 | happy-dom@15.11.7: 2740 | dependencies: 2741 | entities: 4.5.0 2742 | webidl-conversions: 7.0.0 2743 | whatwg-mimetype: 3.0.0 2744 | 2745 | hasown@2.0.2: 2746 | dependencies: 2747 | function-bind: 1.1.2 2748 | 2749 | hookable@5.5.3: {} 2750 | 2751 | human-signals@5.0.0: {} 2752 | 2753 | ignore@5.3.2: {} 2754 | 2755 | inflight@1.0.6: 2756 | dependencies: 2757 | once: 1.4.0 2758 | wrappy: 1.0.2 2759 | 2760 | inherits@2.0.4: {} 2761 | 2762 | is-core-module@2.15.1: 2763 | dependencies: 2764 | hasown: 2.0.2 2765 | 2766 | is-extglob@2.1.1: {} 2767 | 2768 | is-glob@4.0.3: 2769 | dependencies: 2770 | is-extglob: 2.1.1 2771 | 2772 | is-module@1.0.0: {} 2773 | 2774 | is-number@7.0.0: {} 2775 | 2776 | is-reference@1.2.1: 2777 | dependencies: 2778 | '@types/estree': 1.0.6 2779 | 2780 | is-stream@3.0.0: {} 2781 | 2782 | isexe@2.0.0: {} 2783 | 2784 | jiti@1.21.6: {} 2785 | 2786 | jiti@2.4.1: {} 2787 | 2788 | js-tokens@4.0.0: {} 2789 | 2790 | js-yaml@4.1.0: 2791 | dependencies: 2792 | argparse: 2.0.1 2793 | 2794 | jsesc@3.0.2: {} 2795 | 2796 | json5@2.2.3: {} 2797 | 2798 | jsonc-parser@3.3.1: {} 2799 | 2800 | kleur@3.0.3: {} 2801 | 2802 | lilconfig@3.1.3: {} 2803 | 2804 | lodash.memoize@4.1.2: {} 2805 | 2806 | lodash.uniq@4.5.0: {} 2807 | 2808 | loupe@3.1.2: {} 2809 | 2810 | lru-cache@5.1.1: 2811 | dependencies: 2812 | yallist: 3.1.1 2813 | 2814 | magic-string@0.30.15: 2815 | dependencies: 2816 | '@jridgewell/sourcemap-codec': 1.5.0 2817 | 2818 | mdn-data@2.0.28: {} 2819 | 2820 | mdn-data@2.0.30: {} 2821 | 2822 | merge-stream@2.0.0: {} 2823 | 2824 | merge2@1.4.1: {} 2825 | 2826 | micromatch@4.0.8: 2827 | dependencies: 2828 | braces: 3.0.3 2829 | picomatch: 2.3.1 2830 | 2831 | mimic-fn@4.0.0: {} 2832 | 2833 | minimatch@5.1.6: 2834 | dependencies: 2835 | brace-expansion: 2.0.1 2836 | 2837 | minipass@3.3.6: 2838 | dependencies: 2839 | yallist: 4.0.0 2840 | 2841 | minipass@5.0.0: {} 2842 | 2843 | minizlib@2.1.2: 2844 | dependencies: 2845 | minipass: 3.3.6 2846 | yallist: 4.0.0 2847 | 2848 | mkdirp@1.0.4: {} 2849 | 2850 | mkdist@1.6.0(typescript@5.8.2): 2851 | dependencies: 2852 | autoprefixer: 10.4.20(postcss@8.4.49) 2853 | citty: 0.1.6 2854 | cssnano: 7.0.6(postcss@8.4.49) 2855 | defu: 6.1.4 2856 | esbuild: 0.24.0 2857 | jiti: 1.21.6 2858 | mlly: 1.7.3 2859 | pathe: 1.1.2 2860 | pkg-types: 1.2.1 2861 | postcss: 8.4.49 2862 | postcss-nested: 6.2.0(postcss@8.4.49) 2863 | semver: 7.6.3 2864 | tinyglobby: 0.2.10 2865 | optionalDependencies: 2866 | typescript: 5.8.2 2867 | 2868 | mlly@1.7.3: 2869 | dependencies: 2870 | acorn: 8.14.0 2871 | pathe: 1.1.2 2872 | pkg-types: 1.2.1 2873 | ufo: 1.5.4 2874 | 2875 | mri@1.2.0: {} 2876 | 2877 | ms@2.1.3: {} 2878 | 2879 | nanoid@3.3.8: {} 2880 | 2881 | node-fetch-native@1.6.4: {} 2882 | 2883 | node-releases@2.0.19: {} 2884 | 2885 | normalize-range@0.1.2: {} 2886 | 2887 | npm-run-path@5.3.0: 2888 | dependencies: 2889 | path-key: 4.0.0 2890 | 2891 | nth-check@2.1.1: 2892 | dependencies: 2893 | boolbase: 1.0.0 2894 | 2895 | nypm@0.3.12: 2896 | dependencies: 2897 | citty: 0.1.6 2898 | consola: 3.2.3 2899 | execa: 8.0.1 2900 | pathe: 1.1.2 2901 | pkg-types: 1.2.1 2902 | ufo: 1.5.4 2903 | 2904 | ohash@1.1.4: {} 2905 | 2906 | once@1.4.0: 2907 | dependencies: 2908 | wrappy: 1.0.2 2909 | 2910 | onetime@6.0.0: 2911 | dependencies: 2912 | mimic-fn: 4.0.0 2913 | 2914 | path-key@3.1.1: {} 2915 | 2916 | path-key@4.0.0: {} 2917 | 2918 | path-parse@1.0.7: {} 2919 | 2920 | path-type@4.0.0: {} 2921 | 2922 | pathe@1.1.2: {} 2923 | 2924 | pathval@2.0.0: {} 2925 | 2926 | perfect-debounce@1.0.0: {} 2927 | 2928 | picocolors@1.1.1: {} 2929 | 2930 | picomatch@2.3.1: {} 2931 | 2932 | picomatch@4.0.2: {} 2933 | 2934 | pkg-types@1.2.1: 2935 | dependencies: 2936 | confbox: 0.1.8 2937 | mlly: 1.7.3 2938 | pathe: 1.1.2 2939 | 2940 | postcss-calc@10.0.2(postcss@8.4.49): 2941 | dependencies: 2942 | postcss: 8.4.49 2943 | postcss-selector-parser: 6.1.2 2944 | postcss-value-parser: 4.2.0 2945 | 2946 | postcss-colormin@7.0.2(postcss@8.4.49): 2947 | dependencies: 2948 | browserslist: 4.24.2 2949 | caniuse-api: 3.0.0 2950 | colord: 2.9.3 2951 | postcss: 8.4.49 2952 | postcss-value-parser: 4.2.0 2953 | 2954 | postcss-convert-values@7.0.4(postcss@8.4.49): 2955 | dependencies: 2956 | browserslist: 4.24.2 2957 | postcss: 8.4.49 2958 | postcss-value-parser: 4.2.0 2959 | 2960 | postcss-discard-comments@7.0.3(postcss@8.4.49): 2961 | dependencies: 2962 | postcss: 8.4.49 2963 | postcss-selector-parser: 6.1.2 2964 | 2965 | postcss-discard-duplicates@7.0.1(postcss@8.4.49): 2966 | dependencies: 2967 | postcss: 8.4.49 2968 | 2969 | postcss-discard-empty@7.0.0(postcss@8.4.49): 2970 | dependencies: 2971 | postcss: 8.4.49 2972 | 2973 | postcss-discard-overridden@7.0.0(postcss@8.4.49): 2974 | dependencies: 2975 | postcss: 8.4.49 2976 | 2977 | postcss-merge-longhand@7.0.4(postcss@8.4.49): 2978 | dependencies: 2979 | postcss: 8.4.49 2980 | postcss-value-parser: 4.2.0 2981 | stylehacks: 7.0.4(postcss@8.4.49) 2982 | 2983 | postcss-merge-rules@7.0.4(postcss@8.4.49): 2984 | dependencies: 2985 | browserslist: 4.24.2 2986 | caniuse-api: 3.0.0 2987 | cssnano-utils: 5.0.0(postcss@8.4.49) 2988 | postcss: 8.4.49 2989 | postcss-selector-parser: 6.1.2 2990 | 2991 | postcss-minify-font-values@7.0.0(postcss@8.4.49): 2992 | dependencies: 2993 | postcss: 8.4.49 2994 | postcss-value-parser: 4.2.0 2995 | 2996 | postcss-minify-gradients@7.0.0(postcss@8.4.49): 2997 | dependencies: 2998 | colord: 2.9.3 2999 | cssnano-utils: 5.0.0(postcss@8.4.49) 3000 | postcss: 8.4.49 3001 | postcss-value-parser: 4.2.0 3002 | 3003 | postcss-minify-params@7.0.2(postcss@8.4.49): 3004 | dependencies: 3005 | browserslist: 4.24.2 3006 | cssnano-utils: 5.0.0(postcss@8.4.49) 3007 | postcss: 8.4.49 3008 | postcss-value-parser: 4.2.0 3009 | 3010 | postcss-minify-selectors@7.0.4(postcss@8.4.49): 3011 | dependencies: 3012 | cssesc: 3.0.0 3013 | postcss: 8.4.49 3014 | postcss-selector-parser: 6.1.2 3015 | 3016 | postcss-nested@6.2.0(postcss@8.4.49): 3017 | dependencies: 3018 | postcss: 8.4.49 3019 | postcss-selector-parser: 6.1.2 3020 | 3021 | postcss-normalize-charset@7.0.0(postcss@8.4.49): 3022 | dependencies: 3023 | postcss: 8.4.49 3024 | 3025 | postcss-normalize-display-values@7.0.0(postcss@8.4.49): 3026 | dependencies: 3027 | postcss: 8.4.49 3028 | postcss-value-parser: 4.2.0 3029 | 3030 | postcss-normalize-positions@7.0.0(postcss@8.4.49): 3031 | dependencies: 3032 | postcss: 8.4.49 3033 | postcss-value-parser: 4.2.0 3034 | 3035 | postcss-normalize-repeat-style@7.0.0(postcss@8.4.49): 3036 | dependencies: 3037 | postcss: 8.4.49 3038 | postcss-value-parser: 4.2.0 3039 | 3040 | postcss-normalize-string@7.0.0(postcss@8.4.49): 3041 | dependencies: 3042 | postcss: 8.4.49 3043 | postcss-value-parser: 4.2.0 3044 | 3045 | postcss-normalize-timing-functions@7.0.0(postcss@8.4.49): 3046 | dependencies: 3047 | postcss: 8.4.49 3048 | postcss-value-parser: 4.2.0 3049 | 3050 | postcss-normalize-unicode@7.0.2(postcss@8.4.49): 3051 | dependencies: 3052 | browserslist: 4.24.2 3053 | postcss: 8.4.49 3054 | postcss-value-parser: 4.2.0 3055 | 3056 | postcss-normalize-url@7.0.0(postcss@8.4.49): 3057 | dependencies: 3058 | postcss: 8.4.49 3059 | postcss-value-parser: 4.2.0 3060 | 3061 | postcss-normalize-whitespace@7.0.0(postcss@8.4.49): 3062 | dependencies: 3063 | postcss: 8.4.49 3064 | postcss-value-parser: 4.2.0 3065 | 3066 | postcss-ordered-values@7.0.1(postcss@8.4.49): 3067 | dependencies: 3068 | cssnano-utils: 5.0.0(postcss@8.4.49) 3069 | postcss: 8.4.49 3070 | postcss-value-parser: 4.2.0 3071 | 3072 | postcss-reduce-initial@7.0.2(postcss@8.4.49): 3073 | dependencies: 3074 | browserslist: 4.24.2 3075 | caniuse-api: 3.0.0 3076 | postcss: 8.4.49 3077 | 3078 | postcss-reduce-transforms@7.0.0(postcss@8.4.49): 3079 | dependencies: 3080 | postcss: 8.4.49 3081 | postcss-value-parser: 4.2.0 3082 | 3083 | postcss-selector-parser@6.1.2: 3084 | dependencies: 3085 | cssesc: 3.0.0 3086 | util-deprecate: 1.0.2 3087 | 3088 | postcss-svgo@7.0.1(postcss@8.4.49): 3089 | dependencies: 3090 | postcss: 8.4.49 3091 | postcss-value-parser: 4.2.0 3092 | svgo: 3.3.2 3093 | 3094 | postcss-unique-selectors@7.0.3(postcss@8.4.49): 3095 | dependencies: 3096 | postcss: 8.4.49 3097 | postcss-selector-parser: 6.1.2 3098 | 3099 | postcss-value-parser@4.2.0: {} 3100 | 3101 | postcss@8.4.49: 3102 | dependencies: 3103 | nanoid: 3.3.8 3104 | picocolors: 1.1.1 3105 | source-map-js: 1.2.1 3106 | 3107 | pretty-bytes@6.1.1: {} 3108 | 3109 | prompts@2.4.2: 3110 | dependencies: 3111 | kleur: 3.0.3 3112 | sisteransi: 1.0.5 3113 | 3114 | queue-microtask@1.2.3: {} 3115 | 3116 | rc9@2.1.2: 3117 | dependencies: 3118 | defu: 6.1.4 3119 | destr: 2.0.3 3120 | 3121 | readdirp@4.0.2: {} 3122 | 3123 | resolve@1.22.8: 3124 | dependencies: 3125 | is-core-module: 2.15.1 3126 | path-parse: 1.0.7 3127 | supports-preserve-symlinks-flag: 1.0.0 3128 | 3129 | reusify@1.0.4: {} 3130 | 3131 | rollup-plugin-dts@6.1.1(rollup@3.29.5)(typescript@5.8.2): 3132 | dependencies: 3133 | magic-string: 0.30.15 3134 | rollup: 3.29.5 3135 | typescript: 5.8.2 3136 | optionalDependencies: 3137 | '@babel/code-frame': 7.26.2 3138 | 3139 | rollup@3.29.5: 3140 | optionalDependencies: 3141 | fsevents: 2.3.3 3142 | 3143 | rollup@4.28.1: 3144 | dependencies: 3145 | '@types/estree': 1.0.6 3146 | optionalDependencies: 3147 | '@rollup/rollup-android-arm-eabi': 4.28.1 3148 | '@rollup/rollup-android-arm64': 4.28.1 3149 | '@rollup/rollup-darwin-arm64': 4.28.1 3150 | '@rollup/rollup-darwin-x64': 4.28.1 3151 | '@rollup/rollup-freebsd-arm64': 4.28.1 3152 | '@rollup/rollup-freebsd-x64': 4.28.1 3153 | '@rollup/rollup-linux-arm-gnueabihf': 4.28.1 3154 | '@rollup/rollup-linux-arm-musleabihf': 4.28.1 3155 | '@rollup/rollup-linux-arm64-gnu': 4.28.1 3156 | '@rollup/rollup-linux-arm64-musl': 4.28.1 3157 | '@rollup/rollup-linux-loongarch64-gnu': 4.28.1 3158 | '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1 3159 | '@rollup/rollup-linux-riscv64-gnu': 4.28.1 3160 | '@rollup/rollup-linux-s390x-gnu': 4.28.1 3161 | '@rollup/rollup-linux-x64-gnu': 4.28.1 3162 | '@rollup/rollup-linux-x64-musl': 4.28.1 3163 | '@rollup/rollup-win32-arm64-msvc': 4.28.1 3164 | '@rollup/rollup-win32-ia32-msvc': 4.28.1 3165 | '@rollup/rollup-win32-x64-msvc': 4.28.1 3166 | fsevents: 2.3.3 3167 | 3168 | run-parallel@1.2.0: 3169 | dependencies: 3170 | queue-microtask: 1.2.3 3171 | 3172 | scule@1.3.0: {} 3173 | 3174 | semver@6.3.1: {} 3175 | 3176 | semver@7.6.3: {} 3177 | 3178 | shebang-command@2.0.0: 3179 | dependencies: 3180 | shebang-regex: 3.0.0 3181 | 3182 | shebang-regex@3.0.0: {} 3183 | 3184 | siginfo@2.0.0: {} 3185 | 3186 | signal-exit@4.1.0: {} 3187 | 3188 | sisteransi@1.0.5: {} 3189 | 3190 | slash@4.0.0: {} 3191 | 3192 | source-map-js@1.2.1: {} 3193 | 3194 | stackback@0.0.2: {} 3195 | 3196 | std-env@3.8.0: {} 3197 | 3198 | strip-final-newline@3.0.0: {} 3199 | 3200 | stylehacks@7.0.4(postcss@8.4.49): 3201 | dependencies: 3202 | browserslist: 4.24.2 3203 | postcss: 8.4.49 3204 | postcss-selector-parser: 6.1.2 3205 | 3206 | supports-preserve-symlinks-flag@1.0.0: {} 3207 | 3208 | svgo@3.3.2: 3209 | dependencies: 3210 | '@trysound/sax': 0.2.0 3211 | commander: 7.2.0 3212 | css-select: 5.1.0 3213 | css-tree: 2.3.1 3214 | css-what: 6.1.0 3215 | csso: 5.0.5 3216 | picocolors: 1.1.1 3217 | 3218 | tar@6.2.1: 3219 | dependencies: 3220 | chownr: 2.0.0 3221 | fs-minipass: 2.1.0 3222 | minipass: 5.0.0 3223 | minizlib: 2.1.2 3224 | mkdirp: 1.0.4 3225 | yallist: 4.0.0 3226 | 3227 | tinybench@2.9.0: {} 3228 | 3229 | tinyexec@0.3.1: {} 3230 | 3231 | tinyglobby@0.2.10: 3232 | dependencies: 3233 | fdir: 6.4.2(picomatch@4.0.2) 3234 | picomatch: 4.0.2 3235 | 3236 | tinypool@1.0.2: {} 3237 | 3238 | tinyrainbow@1.2.0: {} 3239 | 3240 | tinyspy@3.0.2: {} 3241 | 3242 | to-regex-range@5.0.1: 3243 | dependencies: 3244 | is-number: 7.0.0 3245 | 3246 | typescript@5.8.2: {} 3247 | 3248 | ufo@1.5.4: {} 3249 | 3250 | unbuild@2.0.0(typescript@5.8.2): 3251 | dependencies: 3252 | '@rollup/plugin-alias': 5.1.1(rollup@3.29.5) 3253 | '@rollup/plugin-commonjs': 25.0.8(rollup@3.29.5) 3254 | '@rollup/plugin-json': 6.1.0(rollup@3.29.5) 3255 | '@rollup/plugin-node-resolve': 15.3.0(rollup@3.29.5) 3256 | '@rollup/plugin-replace': 5.0.7(rollup@3.29.5) 3257 | '@rollup/pluginutils': 5.1.3(rollup@3.29.5) 3258 | chalk: 5.3.0 3259 | citty: 0.1.6 3260 | consola: 3.2.3 3261 | defu: 6.1.4 3262 | esbuild: 0.19.12 3263 | globby: 13.2.2 3264 | hookable: 5.5.3 3265 | jiti: 1.21.6 3266 | magic-string: 0.30.15 3267 | mkdist: 1.6.0(typescript@5.8.2) 3268 | mlly: 1.7.3 3269 | pathe: 1.1.2 3270 | pkg-types: 1.2.1 3271 | pretty-bytes: 6.1.1 3272 | rollup: 3.29.5 3273 | rollup-plugin-dts: 6.1.1(rollup@3.29.5)(typescript@5.8.2) 3274 | scule: 1.3.0 3275 | untyped: 1.5.1 3276 | optionalDependencies: 3277 | typescript: 5.8.2 3278 | transitivePeerDependencies: 3279 | - sass 3280 | - supports-color 3281 | - vue-tsc 3282 | 3283 | uncrypto@0.1.3: {} 3284 | 3285 | undici-types@6.20.0: {} 3286 | 3287 | untyped@1.5.1: 3288 | dependencies: 3289 | '@babel/core': 7.26.0 3290 | '@babel/standalone': 7.26.4 3291 | '@babel/types': 7.26.3 3292 | defu: 6.1.4 3293 | jiti: 2.4.1 3294 | mri: 1.2.0 3295 | scule: 1.3.0 3296 | transitivePeerDependencies: 3297 | - supports-color 3298 | 3299 | update-browserslist-db@1.1.1(browserslist@4.24.2): 3300 | dependencies: 3301 | browserslist: 4.24.2 3302 | escalade: 3.2.0 3303 | picocolors: 1.1.1 3304 | 3305 | util-deprecate@1.0.2: {} 3306 | 3307 | vite-node@2.1.8(@types/node@22.10.1): 3308 | dependencies: 3309 | cac: 6.7.14 3310 | debug: 4.4.0 3311 | es-module-lexer: 1.5.4 3312 | pathe: 1.1.2 3313 | vite: 5.4.11(@types/node@22.10.1) 3314 | transitivePeerDependencies: 3315 | - '@types/node' 3316 | - less 3317 | - lightningcss 3318 | - sass 3319 | - sass-embedded 3320 | - stylus 3321 | - sugarss 3322 | - supports-color 3323 | - terser 3324 | 3325 | vite@5.4.11(@types/node@22.10.1): 3326 | dependencies: 3327 | esbuild: 0.21.5 3328 | postcss: 8.4.49 3329 | rollup: 4.28.1 3330 | optionalDependencies: 3331 | '@types/node': 22.10.1 3332 | fsevents: 2.3.3 3333 | 3334 | vitest@2.1.8(@types/node@22.10.1)(happy-dom@15.11.7): 3335 | dependencies: 3336 | '@vitest/expect': 2.1.8 3337 | '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@22.10.1)) 3338 | '@vitest/pretty-format': 2.1.8 3339 | '@vitest/runner': 2.1.8 3340 | '@vitest/snapshot': 2.1.8 3341 | '@vitest/spy': 2.1.8 3342 | '@vitest/utils': 2.1.8 3343 | chai: 5.1.2 3344 | debug: 4.4.0 3345 | expect-type: 1.1.0 3346 | magic-string: 0.30.15 3347 | pathe: 1.1.2 3348 | std-env: 3.8.0 3349 | tinybench: 2.9.0 3350 | tinyexec: 0.3.1 3351 | tinypool: 1.0.2 3352 | tinyrainbow: 1.2.0 3353 | vite: 5.4.11(@types/node@22.10.1) 3354 | vite-node: 2.1.8(@types/node@22.10.1) 3355 | why-is-node-running: 2.3.0 3356 | optionalDependencies: 3357 | '@types/node': 22.10.1 3358 | happy-dom: 15.11.7 3359 | transitivePeerDependencies: 3360 | - less 3361 | - lightningcss 3362 | - msw 3363 | - sass 3364 | - sass-embedded 3365 | - stylus 3366 | - sugarss 3367 | - supports-color 3368 | - terser 3369 | 3370 | webidl-conversions@7.0.0: {} 3371 | 3372 | whatwg-mimetype@3.0.0: {} 3373 | 3374 | which@2.0.2: 3375 | dependencies: 3376 | isexe: 2.0.0 3377 | 3378 | why-is-node-running@2.3.0: 3379 | dependencies: 3380 | siginfo: 2.0.0 3381 | stackback: 0.0.2 3382 | 3383 | wrappy@1.0.2: {} 3384 | 3385 | yallist@3.1.1: {} 3386 | 3387 | yallist@4.0.0: {} 3388 | -------------------------------------------------------------------------------- /src/base32.ts: -------------------------------------------------------------------------------- 1 | //inspired by oslo implementation by pilcrowonpaper: https://github.com/pilcrowonpaper/oslo/blob/main/src/encoding/base32.ts 2 | 3 | import type { TypedArray } from "./type"; 4 | 5 | /** 6 | * Returns the Base32 alphabet based on the encoding type. 7 | * @param hex - Whether to use the hexadecimal Base32 alphabet. 8 | * @returns The appropriate Base32 alphabet. 9 | */ 10 | function getAlphabet(hex: boolean): string { 11 | return hex 12 | ? "0123456789ABCDEFGHIJKLMNOPQRSTUV" 13 | : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; 14 | } 15 | 16 | /** 17 | * Creates a decode map for the given alphabet. 18 | * @param alphabet - The Base32 alphabet. 19 | * @returns A map of characters to their corresponding values. 20 | */ 21 | function createDecodeMap(alphabet: string): Map { 22 | const decodeMap = new Map(); 23 | for (let i = 0; i < alphabet.length; i++) { 24 | decodeMap.set(alphabet[i]!, i); 25 | } 26 | return decodeMap; 27 | } 28 | 29 | /** 30 | * Encodes a Uint8Array into a Base32 string. 31 | * @param data - The data to encode. 32 | * @param alphabet - The Base32 alphabet to use. 33 | * @param padding - Whether to include padding. 34 | * @returns The Base32 encoded string. 35 | */ 36 | function base32Encode( 37 | data: Uint8Array, 38 | alphabet: string, 39 | padding: boolean, 40 | ): string { 41 | let result = ""; 42 | let buffer = 0; 43 | let shift = 0; 44 | 45 | for (const byte of data) { 46 | buffer = (buffer << 8) | byte; 47 | shift += 8; 48 | while (shift >= 5) { 49 | shift -= 5; 50 | result += alphabet[(buffer >> shift) & 0x1f]; 51 | } 52 | } 53 | 54 | if (shift > 0) { 55 | result += alphabet[(buffer << (5 - shift)) & 0x1f]; 56 | } 57 | 58 | if (padding) { 59 | const padCount = (8 - (result.length % 8)) % 8; 60 | result += "=".repeat(padCount); 61 | } 62 | 63 | return result; 64 | } 65 | 66 | /** 67 | * Decodes a Base32 string into a Uint8Array. 68 | * @param data - The Base32 encoded string. 69 | * @param alphabet - The Base32 alphabet to use. 70 | * @returns The decoded Uint8Array. 71 | */ 72 | function base32Decode(data: string, alphabet: string): Uint8Array { 73 | const decodeMap = createDecodeMap(alphabet); 74 | const result: number[] = []; 75 | let buffer = 0; 76 | let bitsCollected = 0; 77 | 78 | for (const char of data) { 79 | if (char === "=") break; 80 | const value = decodeMap.get(char); 81 | if (value === undefined) { 82 | throw new Error(`Invalid Base32 character: ${char}`); 83 | } 84 | buffer = (buffer << 5) | value; 85 | bitsCollected += 5; 86 | 87 | while (bitsCollected >= 8) { 88 | bitsCollected -= 8; 89 | result.push((buffer >> bitsCollected) & 0xff); 90 | } 91 | } 92 | 93 | return Uint8Array.from(result); 94 | } 95 | 96 | /** 97 | * Base32 encoding and decoding utility. 98 | */ 99 | export const base32 = { 100 | /** 101 | * Encodes data into a Base32 string. 102 | * @param data - The data to encode (ArrayBuffer, TypedArray, or string). 103 | * @param options - Encoding options. 104 | * @returns The Base32 encoded string. 105 | */ 106 | encode( 107 | data: ArrayBuffer | TypedArray | string, 108 | options: { padding?: boolean } = {}, 109 | ): string { 110 | const alphabet = getAlphabet(false); 111 | const buffer = 112 | typeof data === "string" 113 | ? new TextEncoder().encode(data) 114 | : new Uint8Array(data); 115 | return base32Encode(buffer, alphabet, options.padding ?? true); 116 | }, 117 | 118 | /** 119 | * Decodes a Base32 string into a Uint8Array. 120 | * @param data - The Base32 encoded string or ArrayBuffer/TypedArray. 121 | * @returns The decoded Uint8Array. 122 | */ 123 | decode(data: string | ArrayBuffer | TypedArray): Uint8Array { 124 | if (typeof data !== "string") { 125 | data = new TextDecoder().decode(data); 126 | } 127 | const alphabet = getAlphabet(false); 128 | return base32Decode(data, alphabet); 129 | }, 130 | }; 131 | 132 | /** 133 | * Base32hex encoding and decoding utility. 134 | */ 135 | export const base32hex = { 136 | /** 137 | * Encodes data into a Base32hex string. 138 | * @param data - The data to encode (ArrayBuffer, TypedArray, or string). 139 | * @param options - Encoding options. 140 | * @returns The Base32hex encoded string. 141 | */ 142 | encode( 143 | data: ArrayBuffer | TypedArray | string, 144 | options: { padding?: boolean } = {}, 145 | ): string { 146 | const alphabet = getAlphabet(true); 147 | const buffer = 148 | typeof data === "string" 149 | ? new TextEncoder().encode(data) 150 | : new Uint8Array(data); 151 | return base32Encode(buffer, alphabet, options.padding ?? true); 152 | }, 153 | 154 | /** 155 | * Decodes a Base32hex string into a Uint8Array. 156 | * @param data - The Base32hex encoded string. 157 | * @returns The decoded Uint8Array. 158 | */ 159 | decode(data: string): Uint8Array { 160 | const alphabet = getAlphabet(true); 161 | return base32Decode(data, alphabet); 162 | }, 163 | }; 164 | -------------------------------------------------------------------------------- /src/base64.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | import { base64, base64Url } from "./base64"; 3 | import { binary } from "./binary"; 4 | 5 | describe("base64", () => { 6 | const plainText = "Hello, World!"; 7 | const plainBuffer = new TextEncoder().encode(plainText); 8 | const base64Encoded = "SGVsbG8sIFdvcmxkIQ=="; 9 | const base64UrlEncoded = "SGVsbG8sIFdvcmxkIQ"; 10 | 11 | describe("encode", () => { 12 | it("encodes a string to base64 with padding", async () => { 13 | const result = base64.encode(plainText, { padding: true }); 14 | expect(result).toBe(base64Encoded); 15 | }); 16 | 17 | it("encodes a string to base64 without padding", async () => { 18 | const result = base64.encode(plainText, { padding: false }); 19 | expect(result).toBe(base64Encoded.replace(/=+$/, "")); 20 | }); 21 | 22 | it("encodes a string to base64 URL-safe", async () => { 23 | const result = base64Url.encode(plainText, { 24 | padding: false, 25 | }); 26 | expect(result).toBe(base64UrlEncoded); 27 | }); 28 | 29 | it("encodes an ArrayBuffer to base64", async () => { 30 | const result = base64.encode(plainBuffer, { padding: true }); 31 | expect(result).toBe(base64Encoded); 32 | }); 33 | }); 34 | 35 | describe("decode", () => { 36 | it("decodes a base64 string", async () => { 37 | const encoded = Buffer.from(plainText).toString("base64"); 38 | const result = base64.decode(encoded); 39 | expect(binary.decode(result)).toBe(plainText); 40 | }); 41 | 42 | it("decodes a base64 URL-safe string", async () => { 43 | const result = base64.decode(base64UrlEncoded); 44 | expect(binary.decode(result)).toBe(plainText); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/base64.ts: -------------------------------------------------------------------------------- 1 | //inspired by oslo implementation by pilcrowonpaper: https://github.com/pilcrowonpaper/oslo/blob/main/src/encoding/base64.ts 2 | 3 | import type { TypedArray } from "./type"; 4 | 5 | function getAlphabet(urlSafe: boolean): string { 6 | return urlSafe 7 | ? "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" 8 | : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 9 | } 10 | 11 | function base64Encode( 12 | data: Uint8Array, 13 | alphabet: string, 14 | padding: boolean, 15 | ): string { 16 | let result = ""; 17 | let buffer = 0; 18 | let shift = 0; 19 | 20 | for (const byte of data) { 21 | buffer = (buffer << 8) | byte; 22 | shift += 8; 23 | while (shift >= 6) { 24 | shift -= 6; 25 | result += alphabet[(buffer >> shift) & 0x3f]; 26 | } 27 | } 28 | 29 | if (shift > 0) { 30 | result += alphabet[(buffer << (6 - shift)) & 0x3f]; 31 | } 32 | 33 | if (padding) { 34 | const padCount = (4 - (result.length % 4)) % 4; 35 | result += "=".repeat(padCount); 36 | } 37 | 38 | return result; 39 | } 40 | 41 | function base64Decode(data: string, alphabet: string): Uint8Array { 42 | const decodeMap = new Map(); 43 | for (let i = 0; i < alphabet.length; i++) { 44 | decodeMap.set(alphabet[i]!, i); 45 | } 46 | const result: number[] = []; 47 | let buffer = 0; 48 | let bitsCollected = 0; 49 | 50 | for (const char of data) { 51 | if (char === "=") break; 52 | const value = decodeMap.get(char); 53 | if (value === undefined) { 54 | throw new Error(`Invalid Base64 character: ${char}`); 55 | } 56 | buffer = (buffer << 6) | value; 57 | bitsCollected += 6; 58 | 59 | if (bitsCollected >= 8) { 60 | bitsCollected -= 8; 61 | result.push((buffer >> bitsCollected) & 0xff); 62 | } 63 | } 64 | 65 | return Uint8Array.from(result); 66 | } 67 | 68 | export const base64 = { 69 | encode( 70 | data: ArrayBuffer | TypedArray | string, 71 | options: { padding?: boolean } = {}, 72 | ) { 73 | const alphabet = getAlphabet(false); 74 | const buffer = 75 | typeof data === "string" 76 | ? new TextEncoder().encode(data) 77 | : new Uint8Array(data); 78 | return base64Encode(buffer, alphabet, options.padding ?? true); 79 | }, 80 | decode(data: string | ArrayBuffer | TypedArray) { 81 | if (typeof data !== "string") { 82 | data = new TextDecoder().decode(data); 83 | } 84 | const urlSafe = data.includes("-") || data.includes("_"); 85 | const alphabet = getAlphabet(urlSafe); 86 | return base64Decode(data, alphabet); 87 | }, 88 | }; 89 | 90 | export const base64Url = { 91 | encode( 92 | data: ArrayBuffer | TypedArray | string, 93 | options: { padding?: boolean } = {}, 94 | ) { 95 | const alphabet = getAlphabet(true); 96 | const buffer = 97 | typeof data === "string" 98 | ? new TextEncoder().encode(data) 99 | : new Uint8Array(data); 100 | return base64Encode(buffer, alphabet, options.padding ?? true); 101 | }, 102 | decode(data: string) { 103 | const urlSafe = data.includes("-") || data.includes("_"); 104 | const alphabet = getAlphabet(urlSafe); 105 | return base64Decode(data, alphabet); 106 | }, 107 | }; 108 | -------------------------------------------------------------------------------- /src/binary.ts: -------------------------------------------------------------------------------- 1 | type Encoding = "utf-8" | "utf-16" | "iso-8859-1"; 2 | 3 | type BinaryData = ArrayBuffer | ArrayBufferView; 4 | 5 | const decoders = new Map(); 6 | const encoder = new TextEncoder(); 7 | 8 | export const binary = { 9 | decode: (data: BinaryData, encoding: Encoding = "utf-8") => { 10 | if (!decoders.has(encoding)) { 11 | decoders.set(encoding, new TextDecoder(encoding)); 12 | } 13 | const decoder = decoders.get(encoding)!; 14 | return decoder.decode(data); 15 | }, 16 | encode: encoder.encode, 17 | }; 18 | -------------------------------------------------------------------------------- /src/ecdsa.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | import { ecdsa } from "./ecdsa"; 3 | 4 | describe("ecdsa", () => { 5 | const testCurve = "P-256"; 6 | 7 | describe("generateKeyPair", () => { 8 | it("generates a valid ECDSA key pair", async () => { 9 | const { privateKey, publicKey } = await ecdsa.generateKeyPair(testCurve); 10 | expect(privateKey).toBeInstanceOf(ArrayBuffer); 11 | expect(publicKey).toBeInstanceOf(ArrayBuffer); 12 | }); 13 | }); 14 | 15 | describe("importPrivateKey", () => { 16 | it("imports a private key successfully", async () => { 17 | const { privateKey } = await ecdsa.generateKeyPair(testCurve); 18 | const importedKey = await ecdsa.importPrivateKey(privateKey, testCurve); 19 | expect(importedKey.type).toBe("private"); 20 | expect(importedKey.algorithm.name).toBe("ECDSA"); 21 | }); 22 | }); 23 | 24 | describe("importPublicKey", () => { 25 | it("imports a public key successfully", async () => { 26 | const { publicKey } = await ecdsa.generateKeyPair(testCurve); 27 | const importedKey = await ecdsa.importPublicKey(publicKey, testCurve); 28 | expect(importedKey.type).toBe("public"); 29 | expect(importedKey.algorithm.name).toBe("ECDSA"); 30 | }); 31 | }); 32 | 33 | describe("sign", () => { 34 | it("signs data using a private key", async () => { 35 | const { privateKey } = await ecdsa.generateKeyPair(testCurve); 36 | const privateCryptoKey = await ecdsa.importPrivateKey( 37 | privateKey, 38 | testCurve, 39 | ); 40 | const data = "Hello, ECDSA!"; 41 | const signature = await ecdsa.sign(privateCryptoKey, data); 42 | expect(signature).toBeInstanceOf(ArrayBuffer); 43 | }); 44 | }); 45 | 46 | describe("verify", () => { 47 | it("verifies a signature using the corresponding public key", async () => { 48 | const { privateKey, publicKey } = await ecdsa.generateKeyPair(testCurve); 49 | const privateCryptoKey = await ecdsa.importPrivateKey( 50 | privateKey, 51 | testCurve, 52 | ); 53 | const publicCryptoKey = await ecdsa.importPublicKey(publicKey, testCurve); 54 | 55 | const data = "Hello, ECDSA!"; 56 | const signature = await ecdsa.sign(privateCryptoKey, data); 57 | const isValid = await ecdsa.verify(publicCryptoKey, { signature, data }); 58 | expect(isValid).toBe(true); 59 | }); 60 | 61 | it("fails to verify with incorrect data", async () => { 62 | const { privateKey, publicKey } = await ecdsa.generateKeyPair(testCurve); 63 | const privateCryptoKey = await ecdsa.importPrivateKey( 64 | privateKey, 65 | testCurve, 66 | ); 67 | const publicCryptoKey = await ecdsa.importPublicKey(publicKey, testCurve); 68 | 69 | const originalData = "Hello, ECDSA!"; 70 | const tamperedData = "Tampered Data!"; 71 | const signature = await ecdsa.sign(privateCryptoKey, originalData); 72 | const isValid = await ecdsa.verify(publicCryptoKey, { 73 | signature, 74 | data: tamperedData, 75 | }); 76 | expect(isValid).toBe(false); 77 | }); 78 | }); 79 | 80 | describe("exportKey", () => { 81 | it("exports a private key in pkcs8 format", async () => { 82 | const { privateKey } = await ecdsa.generateKeyPair(testCurve); 83 | const privateCryptoKey = await ecdsa.importPrivateKey( 84 | privateKey, 85 | testCurve, 86 | true, 87 | ); 88 | const exportedKey = await ecdsa.exportKey(privateCryptoKey, "pkcs8"); 89 | expect(exportedKey).toBeInstanceOf(ArrayBuffer); 90 | }); 91 | 92 | it("exports a public key in spki format", async () => { 93 | const { publicKey } = await ecdsa.generateKeyPair(testCurve); 94 | const publicCryptoKey = await ecdsa.importPublicKey( 95 | publicKey, 96 | testCurve, 97 | true, 98 | ); 99 | const exportedKey = await ecdsa.exportKey(publicCryptoKey, "spki"); 100 | expect(exportedKey).toBeInstanceOf(ArrayBuffer); 101 | }); 102 | 103 | it("exports a key in jwk format", async () => { 104 | const { publicKey } = await ecdsa.generateKeyPair(testCurve); 105 | const publicCryptoKey = await ecdsa.importPublicKey( 106 | publicKey, 107 | testCurve, 108 | true, 109 | ); 110 | const exportedKey = await ecdsa.exportKey(publicCryptoKey, "jwk"); 111 | expect(exportedKey).toHaveProperty("kty", "EC"); 112 | expect(exportedKey).toHaveProperty("crv", testCurve); 113 | }); 114 | }); 115 | }); 116 | -------------------------------------------------------------------------------- /src/ecdsa.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | ECDSACurve, 3 | ExportKeyFormat, 4 | SHAFamily, 5 | TypedArray, 6 | } from "./type"; 7 | 8 | export const ecdsa = { 9 | generateKeyPair: async (curve: ECDSACurve = "P-256") => { 10 | const keyPair = await crypto.subtle.generateKey( 11 | { 12 | name: "ECDSA", 13 | namedCurve: curve, 14 | }, 15 | true, 16 | ["sign", "verify"], 17 | ); 18 | const privateKey = await crypto.subtle.exportKey( 19 | "pkcs8", 20 | keyPair.privateKey, 21 | ); 22 | const publicKey = await crypto.subtle.exportKey("spki", keyPair.publicKey); 23 | return { privateKey, publicKey }; 24 | }, 25 | importPrivateKey: async ( 26 | privateKey: ArrayBuffer | TypedArray | string, 27 | curve: ECDSACurve, 28 | extractable = false, 29 | ): Promise => { 30 | if (typeof privateKey === "string") { 31 | privateKey = new TextEncoder().encode(privateKey); 32 | } 33 | return await crypto.subtle.importKey( 34 | "pkcs8", 35 | privateKey, 36 | { 37 | name: "ECDSA", 38 | namedCurve: curve, 39 | }, 40 | extractable, 41 | ["sign"], 42 | ); 43 | }, 44 | importPublicKey: async ( 45 | publicKey: ArrayBuffer | TypedArray | string, 46 | curve: ECDSACurve, 47 | extractable = false, 48 | ): Promise => { 49 | if (typeof publicKey === "string") { 50 | publicKey = new TextEncoder().encode(publicKey); 51 | } 52 | return await crypto.subtle.importKey( 53 | "spki", 54 | publicKey, 55 | { 56 | name: "ECDSA", 57 | namedCurve: curve, 58 | }, 59 | extractable, 60 | ["verify"], 61 | ); 62 | }, 63 | sign: async ( 64 | privateKey: CryptoKey, 65 | data: ArrayBuffer | TypedArray | string, 66 | hash: SHAFamily = "SHA-256", 67 | ): Promise => { 68 | if (typeof data === "string") { 69 | data = new TextEncoder().encode(data); 70 | } 71 | const signature = await crypto.subtle.sign( 72 | { 73 | name: "ECDSA", 74 | hash: { name: hash }, 75 | }, 76 | privateKey, 77 | data, 78 | ); 79 | return signature; 80 | }, 81 | 82 | verify: async ( 83 | publicKey: CryptoKey, 84 | { 85 | signature, 86 | data, 87 | hash = "SHA-256", 88 | }: { 89 | signature: ArrayBuffer | TypedArray | string; 90 | data: ArrayBuffer | string; 91 | hash?: SHAFamily; 92 | }, 93 | ): Promise => { 94 | if (typeof signature === "string") { 95 | signature = new TextEncoder().encode(signature); 96 | } 97 | if (typeof data === "string") { 98 | data = new TextEncoder().encode(data); 99 | } 100 | return await crypto.subtle.verify( 101 | { 102 | name: "ECDSA", 103 | hash: { name: hash }, 104 | }, 105 | publicKey, 106 | signature, 107 | data, 108 | ); 109 | }, 110 | exportKey: async ( 111 | key: CryptoKey, 112 | format: E, 113 | ): Promise => { 114 | return (await crypto.subtle.exportKey(format, key)) as any; 115 | }, 116 | }; 117 | -------------------------------------------------------------------------------- /src/hash.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | import { createHash } from "./hash"; 3 | 4 | describe("digest", () => { 5 | const inputString = "Hello, World!"; 6 | const inputBuffer = new TextEncoder().encode(inputString); 7 | 8 | describe("SHA algorithms", () => { 9 | it("computes SHA-256 hash in raw format", async () => { 10 | const hash = await createHash("SHA-256").digest(inputString); 11 | expect(hash).toBeInstanceOf(ArrayBuffer); 12 | }); 13 | 14 | it("computes SHA-512 hash in raw format", async () => { 15 | const hash = await createHash("SHA-512").digest(inputBuffer); 16 | expect(hash).toBeInstanceOf(ArrayBuffer); 17 | }); 18 | 19 | it("computes SHA-256 hash in hex encoding", async () => { 20 | const hash = await createHash("SHA-256", "hex").digest(inputString); 21 | expect(typeof hash).toBe("string"); 22 | expect(hash).toMatch(/^[a-f0-9]{64}$/); 23 | }); 24 | 25 | it("computes SHA-512 hash in hex encoding", async () => { 26 | const hash = await createHash("SHA-512", "hex").digest(inputBuffer); 27 | expect(typeof hash).toBe("string"); 28 | expect(hash).toMatch(/^[a-f0-9]{128}$/); 29 | }); 30 | }); 31 | 32 | describe("Input variations", () => { 33 | it("handles input as a string", async () => { 34 | const hash = await createHash("SHA-256").digest(inputString); 35 | expect(hash).toBeInstanceOf(ArrayBuffer); 36 | }); 37 | 38 | it("handles input as an ArrayBuffer", async () => { 39 | const hash = await createHash("SHA-256").digest(inputBuffer.buffer); 40 | expect(hash).toBeInstanceOf(ArrayBuffer); 41 | }); 42 | 43 | it("handles input as an ArrayBufferView", async () => { 44 | const hash = await createHash("SHA-256").digest( 45 | new Uint8Array(inputBuffer), 46 | ); 47 | expect(hash).toBeInstanceOf(ArrayBuffer); 48 | }); 49 | }); 50 | 51 | describe("Error handling", () => { 52 | it("throws an error for unsupported hash algorithms", async () => { 53 | await expect( 54 | createHash("SHA-10" as any).digest(inputString), 55 | ).rejects.toThrow(); 56 | }); 57 | 58 | it("throws an error for invalid input types", async () => { 59 | await expect(createHash("SHA-256").digest({} as any)).rejects.toThrow(); 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /src/hash.ts: -------------------------------------------------------------------------------- 1 | import { subtle } from "uncrypto"; 2 | import { base64, base64Url } from "./base64"; 3 | import type { EncodingFormat, SHAFamily, TypedArray } from "./type"; 4 | 5 | export function createHash( 6 | algorithm: SHAFamily, 7 | encoding?: Encoding, 8 | ) { 9 | return { 10 | digest: async ( 11 | input: string | ArrayBuffer | TypedArray, 12 | ): Promise => { 13 | const encoder = new TextEncoder(); 14 | const data = typeof input === "string" ? encoder.encode(input) : input; 15 | const hashBuffer = await subtle.digest(algorithm, data); 16 | 17 | if (encoding === "hex") { 18 | const hashArray = Array.from(new Uint8Array(hashBuffer)); 19 | const hashHex = hashArray 20 | .map((b) => b.toString(16).padStart(2, "0")) 21 | .join(""); 22 | return hashHex as any; 23 | } 24 | 25 | if ( 26 | encoding === "base64" || 27 | encoding === "base64url" || 28 | encoding === "base64urlnopad" 29 | ) { 30 | if (encoding.includes("url")) { 31 | return base64Url.encode(hashBuffer, { 32 | padding: encoding !== "base64urlnopad", 33 | }) as any; 34 | } 35 | const hashBase64 = base64.encode(hashBuffer); 36 | return hashBase64 as any; 37 | } 38 | return hashBuffer as any; 39 | }, 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /src/hex.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from "vitest"; 2 | import { hex } from "./hex"; 3 | 4 | describe("hex", () => { 5 | describe("encode", () => { 6 | it("should encode a string to hexadecimal", () => { 7 | const input = "Hello, World!"; 8 | expect(hex.encode(input)).toBe(Buffer.from(input).toString("hex")); 9 | }); 10 | 11 | it("should encode an ArrayBuffer to hexadecimal", () => { 12 | const input = new TextEncoder().encode("Hello").buffer; 13 | expect(hex.encode(input)).toBe(Buffer.from(input).toString("hex")); 14 | }); 15 | 16 | it("should encode a TypedArray to hexadecimal", () => { 17 | const input = new Uint8Array([72, 101, 108, 108, 111]); 18 | expect(hex.encode(input)).toBe(Buffer.from(input).toString("hex")); 19 | }); 20 | }); 21 | 22 | describe("decode", () => { 23 | it("should decode a hexadecimal string to its original value", () => { 24 | const expected = "Hello, World!"; 25 | expect(hex.decode(Buffer.from(expected).toString("hex"))).toBe(expected); 26 | }); 27 | 28 | it("should handle decoding of a hexadecimal string to binary data", () => { 29 | const expected = "Hello"; 30 | expect(hex.decode(Buffer.from(expected).toString("hex"))).toBe(expected); 31 | }); 32 | 33 | it("should throw an error for an odd-length string", () => { 34 | const input = "123"; 35 | expect(() => hex.decode(input)).toThrow(Error); 36 | }); 37 | 38 | it("should throw an error for a non-hexadecimal string", () => { 39 | const input = "zzzz"; 40 | expect(() => hex.decode(input)).toThrow(Error); 41 | }); 42 | }); 43 | 44 | describe("round-trip tests", () => { 45 | it("should return the original string after encoding and decoding", () => { 46 | const input = "Hello, Hex!"; 47 | const encoded = hex.encode(input); 48 | const decoded = hex.decode(encoded); 49 | expect(decoded).toBe(input); 50 | }); 51 | 52 | it("should handle empty strings", () => { 53 | const input = ""; 54 | const encoded = hex.encode(input); 55 | const decoded = hex.decode(encoded); 56 | expect(decoded).toBe(input); 57 | }); 58 | }); 59 | }); 60 | -------------------------------------------------------------------------------- /src/hex.ts: -------------------------------------------------------------------------------- 1 | import type { TypedArray } from "./type"; 2 | 3 | const hexadecimal = "0123456789abcdef"; 4 | export const hex = { 5 | encode: (data: string | ArrayBuffer | TypedArray) => { 6 | if (typeof data === "string") { 7 | data = new TextEncoder().encode(data); 8 | } 9 | if (data.byteLength === 0) { 10 | return ""; 11 | } 12 | const buffer = new Uint8Array(data); 13 | let result = ""; 14 | for (const byte of buffer) { 15 | result += byte.toString(16).padStart(2, "0"); 16 | } 17 | return result; 18 | }, 19 | decode: (data: string | ArrayBuffer | TypedArray) => { 20 | if (!data) { 21 | return ""; 22 | } 23 | if (typeof data === "string") { 24 | if (data.length % 2 !== 0) { 25 | throw new Error("Invalid hexadecimal string"); 26 | } 27 | if (!new RegExp(`^[${hexadecimal}]+$`).test(data)) { 28 | throw new Error("Invalid hexadecimal string"); 29 | } 30 | const result = new Uint8Array(data.length / 2); 31 | for (let i = 0; i < data.length; i += 2) { 32 | result[i / 2] = parseInt(data.slice(i, i + 2), 16); 33 | } 34 | return new TextDecoder().decode(result); 35 | } 36 | return new TextDecoder().decode(data); 37 | }, 38 | }; 39 | -------------------------------------------------------------------------------- /src/hmac.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from "vitest"; 2 | import { createHMAC } from "./hmac"; 3 | 4 | describe("hmac module", () => { 5 | const algorithm = "SHA-256"; 6 | const testKey = "super-secret-key"; 7 | const testData = "Hello, HMAC!"; 8 | let signature: ArrayBuffer; 9 | 10 | it("imports a key for HMAC", async () => { 11 | const cryptoKey = await createHMAC().importKey(testKey, "sign"); 12 | expect(cryptoKey).toBeDefined(); 13 | expect(cryptoKey.algorithm.name).toBe("HMAC"); 14 | expect((cryptoKey.algorithm as HmacKeyAlgorithm).hash.name).toBe(algorithm); 15 | }); 16 | 17 | it("signs data using HMAC", async () => { 18 | signature = await createHMAC().sign(testKey, testData); 19 | expect(signature).toBeInstanceOf(ArrayBuffer); 20 | expect(signature.byteLength).toBeGreaterThan(0); 21 | }); 22 | 23 | it("verifies HMAC signature", async () => { 24 | const isValid = await createHMAC().verify(testKey, testData, signature); 25 | expect(isValid).toBe(true); 26 | }); 27 | 28 | it("fails verification for modified data", async () => { 29 | const isValid = await createHMAC(algorithm).verify( 30 | testKey, 31 | "Modified data", 32 | signature, 33 | ); 34 | expect(isValid).toBe(false); 35 | }); 36 | 37 | it("fails verification for a different key", async () => { 38 | const differentKey = "different-secret-key"; 39 | const isValid = await createHMAC(algorithm).verify( 40 | differentKey, 41 | testData, 42 | signature, 43 | ); 44 | expect(isValid).toBe(false); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /src/hmac.ts: -------------------------------------------------------------------------------- 1 | import { subtle } from "uncrypto"; 2 | import type { EncodingFormat, SHAFamily, TypedArray } from "./type"; 3 | import { hex } from "./hex"; 4 | import { base64, base64Url } from "./base64"; 5 | 6 | export const createHMAC = ( 7 | algorithm: SHAFamily = "SHA-256", 8 | encoding: E = "none" as E, 9 | ) => { 10 | const hmac = { 11 | importKey: async ( 12 | key: string | ArrayBuffer | TypedArray, 13 | keyUsage: "sign" | "verify", 14 | ) => { 15 | return subtle.importKey( 16 | "raw", 17 | typeof key === "string" ? new TextEncoder().encode(key) : key, 18 | { name: "HMAC", hash: { name: algorithm } }, 19 | false, 20 | [keyUsage], 21 | ); 22 | }, 23 | sign: async ( 24 | hmacKey: string | CryptoKey, 25 | data: string | ArrayBuffer | TypedArray, 26 | ): Promise => { 27 | if (typeof hmacKey === "string") { 28 | hmacKey = await hmac.importKey(hmacKey, "sign"); 29 | } 30 | const signature = await subtle.sign( 31 | "HMAC", 32 | hmacKey, 33 | typeof data === "string" ? new TextEncoder().encode(data) : data, 34 | ); 35 | if (encoding === "hex") { 36 | return hex.encode(signature) as any; 37 | } 38 | if ( 39 | encoding === "base64" || 40 | encoding === "base64url" || 41 | encoding === "base64urlnopad" 42 | ) { 43 | return base64Url.encode(signature, { 44 | padding: encoding !== "base64urlnopad", 45 | }) as any; 46 | } 47 | return signature as any; 48 | }, 49 | verify: async ( 50 | hmacKey: CryptoKey | string, 51 | data: string | ArrayBuffer | TypedArray, 52 | signature: string | ArrayBuffer | TypedArray, 53 | ) => { 54 | if (typeof hmacKey === "string") { 55 | hmacKey = await hmac.importKey(hmacKey, "verify"); 56 | } 57 | if (encoding === "hex") { 58 | signature = hex.decode(signature); 59 | } 60 | if ( 61 | encoding === "base64" || 62 | encoding === "base64url" || 63 | encoding === "base64urlnopad" 64 | ) { 65 | signature = await base64.decode(signature); 66 | } 67 | return subtle.verify( 68 | "HMAC", 69 | hmacKey, 70 | typeof signature === "string" 71 | ? new TextEncoder().encode(signature) 72 | : signature, 73 | typeof data === "string" ? new TextEncoder().encode(data) : data, 74 | ); 75 | }, 76 | }; 77 | return hmac; 78 | }; 79 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "uncrypto"; 2 | -------------------------------------------------------------------------------- /src/otp.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect, vi } from "vitest"; 2 | import { createOTP } from "./otp"; 3 | 4 | describe("HOTP and TOTP Generation Tests", () => { 5 | it("should generate a valid HOTP for a given counter", async () => { 6 | const key = "1234567890"; 7 | const counter = 1; 8 | const digits = 6; 9 | const otp = await createOTP(key, { 10 | digits, 11 | }).hotp(counter); 12 | expect(otp).toBeTypeOf("string"); 13 | expect(otp.length).toBe(digits); 14 | }); 15 | 16 | it("should throw error if digits is not between 1 and 8", async () => { 17 | const key = "1234567890"; 18 | const counter = 1; 19 | 20 | await expect( 21 | createOTP(key, { 22 | digits: 9, 23 | }).hotp(counter), 24 | ).rejects.toThrow("Digits must be between 1 and 8"); 25 | await expect( 26 | createOTP(key, { 27 | digits: 0, 28 | }).hotp(counter), 29 | ).rejects.toThrow("Digits must be between 1 and 8"); 30 | }); 31 | 32 | it("should generate a valid TOTP based on current time", async () => { 33 | const secret = "1234567890"; 34 | const digits = 6; 35 | 36 | const otp = await createOTP(secret, { 37 | digits, 38 | }).totp(); 39 | expect(otp).toBeTypeOf("string"); 40 | expect(otp.length).toBe(digits); 41 | }); 42 | 43 | it("should generate different OTPs after each time window", async () => { 44 | const secret = "1234567890"; 45 | const seconds = 30; 46 | const digits = 6; 47 | 48 | const otp1 = await createOTP(secret, { 49 | period: seconds, 50 | digits, 51 | }).totp(); 52 | vi.useFakeTimers(); 53 | await vi.advanceTimersByTimeAsync(30000); 54 | const otp2 = await createOTP(secret, { 55 | period: seconds, 56 | digits, 57 | }).totp(); 58 | expect(otp1).not.toBe(otp2); 59 | }); 60 | 61 | it("should verify correct TOTP against generated value", async () => { 62 | const secret = "1234567890"; 63 | const totp = await createOTP(secret).totp(); 64 | const isValid = await createOTP(secret).verify(totp); 65 | expect(isValid).toBe(true); 66 | }); 67 | 68 | it("should return false for incorrect TOTP", async () => { 69 | const secret = "1234567890"; 70 | const invalidTOTP = "000000"; 71 | 72 | const isValid = await createOTP(secret).verify(invalidTOTP); 73 | console.log(isValid); 74 | expect(isValid).toBe(false); 75 | }); 76 | 77 | it("should verify TOTP within the window", async () => { 78 | const secret = "1234567890"; 79 | const totp = await createOTP(secret).totp(); 80 | const isValid = await createOTP(secret).verify(totp, { window: 1 }); 81 | expect(isValid).toBe(true); 82 | }); 83 | 84 | it("should return false for TOTP outside the window", async () => { 85 | const secret = "1234567890"; 86 | const totp = await createOTP(secret).totp(); 87 | const isValid = await createOTP(secret).verify(totp, { window: -1 }); 88 | expect(isValid).toBe(false); 89 | }); 90 | 91 | it("should generate a valid QR code URL", () => { 92 | const secret = "1234567890"; 93 | const issuer = "my-site.com"; 94 | const account = "account"; 95 | const url = createOTP(secret).url(issuer, account); 96 | expect(url).toBeTypeOf("string"); 97 | expect(url).toContain("otpauth://totp"); 98 | }); 99 | }); 100 | -------------------------------------------------------------------------------- /src/otp.ts: -------------------------------------------------------------------------------- 1 | import { base32 } from "./base32"; 2 | import { createHMAC } from "./hmac"; 3 | import type { SHAFamily } from "./type"; 4 | 5 | const defaultPeriod = 30; 6 | const defaultDigits = 6; 7 | 8 | async function generateHOTP( 9 | secret: string, 10 | { 11 | counter, 12 | digits, 13 | hash = "SHA-1", 14 | }: { 15 | counter: number; 16 | digits?: number; 17 | hash?: SHAFamily; 18 | }, 19 | ) { 20 | const _digits = digits ?? defaultDigits; 21 | if (_digits < 1 || _digits > 8) { 22 | throw new TypeError("Digits must be between 1 and 8"); 23 | } 24 | const buffer = new ArrayBuffer(8); 25 | new DataView(buffer).setBigUint64(0, BigInt(counter), false); 26 | const bytes = new Uint8Array(buffer); 27 | const hmacResult = new Uint8Array(await createHMAC(hash).sign(secret, bytes)); 28 | const offset = hmacResult[hmacResult.length - 1] & 0x0f; 29 | const truncated = 30 | ((hmacResult[offset] & 0x7f) << 24) | 31 | ((hmacResult[offset + 1] & 0xff) << 16) | 32 | ((hmacResult[offset + 2] & 0xff) << 8) | 33 | (hmacResult[offset + 3] & 0xff); 34 | const otp = truncated % 10 ** _digits; 35 | return otp.toString().padStart(_digits, "0"); 36 | } 37 | 38 | async function generateTOTP( 39 | secret: string, 40 | options?: { 41 | period?: number; 42 | digits?: number; 43 | hash?: SHAFamily; 44 | }, 45 | ) { 46 | const digits = options?.digits ?? defaultDigits; 47 | const period = options?.period ?? defaultPeriod; 48 | const milliseconds = period * 1000; 49 | const counter = Math.floor(Date.now() / milliseconds); 50 | return await generateHOTP(secret, { counter, digits, hash: options?.hash }); 51 | } 52 | 53 | async function verifyTOTP( 54 | otp: string, 55 | { 56 | window = 1, 57 | digits = defaultDigits, 58 | secret, 59 | period = defaultPeriod, 60 | }: { 61 | period?: number; 62 | window?: number; 63 | digits?: number; 64 | secret: string; 65 | }, 66 | ) { 67 | const milliseconds = period * 1000; 68 | const counter = Math.floor(Date.now() / milliseconds); 69 | for (let i = -window; i <= window; i++) { 70 | const generatedOTP = await generateHOTP(secret, { 71 | counter: counter + i, 72 | digits, 73 | }); 74 | if (otp === generatedOTP) { 75 | return true; 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | /** 82 | * Generate a QR code URL for the OTP secret 83 | */ 84 | function generateQRCode({ 85 | issuer, 86 | account, 87 | secret, 88 | digits = defaultDigits, 89 | period = defaultPeriod, 90 | }: { 91 | issuer: string; 92 | account: string; 93 | secret: string; 94 | digits?: number; 95 | period?: number; 96 | }) { 97 | const encodedIssuer = encodeURIComponent(issuer); 98 | const encodedAccountName = encodeURIComponent(account); 99 | const baseURI = `otpauth://totp/${encodedIssuer}:${encodedAccountName}`; 100 | const params = new URLSearchParams({ 101 | secret: base32.encode(secret, { 102 | padding: false, 103 | }), 104 | issuer, 105 | }); 106 | 107 | if (digits !== undefined) { 108 | params.set("digits", digits.toString()); 109 | } 110 | if (period !== undefined) { 111 | params.set("period", period.toString()); 112 | } 113 | return `${baseURI}?${params.toString()}`; 114 | } 115 | 116 | export const createOTP = ( 117 | secret: string, 118 | opts?: { 119 | digits?: number; 120 | period?: number; 121 | }, 122 | ) => { 123 | const digits = opts?.digits ?? defaultDigits; 124 | const period = opts?.period ?? defaultPeriod; 125 | return { 126 | hotp: (counter: number) => generateHOTP(secret, { counter, digits }), 127 | totp: () => generateTOTP(secret, { digits, period }), 128 | verify: (otp: string, options?: { window?: number }) => 129 | verifyTOTP(otp, { secret, digits, period, ...options }), 130 | url: (issuer: string, account: string) => 131 | generateQRCode({ issuer, account, secret, digits, period }), 132 | }; 133 | }; 134 | -------------------------------------------------------------------------------- /src/random.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it, vi } from "vitest"; 2 | import { createRandomStringGenerator } from "./random"; 3 | import { getRandomValues } from "uncrypto"; 4 | 5 | // Utility functions for distribution tests 6 | function generateLargeRandomSample( 7 | alphabet: "a-z" | "0-9", 8 | sampleCount = 1000, 9 | stringLength = 256, 10 | ): string { 11 | const generator = createRandomStringGenerator(alphabet); 12 | return new Array(sampleCount) 13 | .fill(null) 14 | .map(() => generator(stringLength)) 15 | .join(""); 16 | } 17 | 18 | function getCharCounts( 19 | randomString: string, 20 | expectedCharSet: string, 21 | ): Map { 22 | const charCounts = new Map(); 23 | 24 | // Initialize all character counts to 0 25 | for (const char of expectedCharSet) { 26 | charCounts.set(char, 0); 27 | } 28 | 29 | // Count occurrences 30 | for (const char of randomString) { 31 | const currentCount = charCounts.get(char) || 0; 32 | charCounts.set(char, currentCount + 1); 33 | } 34 | 35 | return charCounts; 36 | } 37 | 38 | function calculateChiSquared( 39 | charCounts: Map, 40 | totalChars: number, 41 | charSetLength: number, 42 | ): number { 43 | const expectedCount = totalChars / charSetLength; 44 | let chiSquared = 0; 45 | 46 | for (const count of charCounts.values()) { 47 | const deviation = count - expectedCount; 48 | chiSquared += (deviation * deviation) / expectedCount; 49 | } 50 | 51 | return chiSquared; 52 | } 53 | 54 | describe("createRandomStringGenerator", () => { 55 | it("generates a random string of specified length", () => { 56 | const generator = createRandomStringGenerator("a-z"); 57 | const length = 16; 58 | const randomString = generator(length); 59 | 60 | expect(randomString).toBeDefined(); 61 | expect(randomString).toHaveLength(length); 62 | }); 63 | 64 | it("uses a custom alphabet to generate random strings", () => { 65 | const generator = createRandomStringGenerator("A-Z", "0-9"); 66 | const randomString = generator(8); 67 | const allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 68 | expect([...randomString].every((char) => allowedChars.includes(char))).toBe( 69 | true, 70 | ); 71 | }); 72 | 73 | it("throws an error when no valid characters are provided", () => { 74 | expect(() => createRandomStringGenerator()).toThrowError( 75 | "No valid characters provided for random string generation.", 76 | ); 77 | }); 78 | 79 | it("throws an error when length is not positive", () => { 80 | const generator = createRandomStringGenerator("a-z"); 81 | expect(() => generator(0)).toThrowError( 82 | "Length must be a positive integer.", 83 | ); 84 | expect(() => generator(-5)).toThrowError( 85 | "Length must be a positive integer.", 86 | ); 87 | }); 88 | 89 | it("respects a new alphabet when passed during generation", () => { 90 | const generator = createRandomStringGenerator("a-z"); 91 | const newAlphabet = "A-Z"; 92 | const randomString = generator(10, newAlphabet); 93 | 94 | const allowedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 95 | expect([...randomString].every((char) => allowedChars.includes(char))).toBe( 96 | true, 97 | ); 98 | }); 99 | 100 | it("generates consistent randomness with valid mask calculations", () => { 101 | const generator = createRandomStringGenerator("0-9"); 102 | const randomString = generator(10); 103 | const allowedChars = "0123456789"; 104 | expect([...randomString].every((char) => allowedChars.includes(char))).toBe( 105 | true, 106 | ); 107 | }); 108 | 109 | it("combines multiple alphabets when passed during generation", () => { 110 | // Mock getRandomValues to return sequentially increasing values 111 | vi.mock("uncrypto", () => ({ 112 | getRandomValues: vi.fn( 113 | (array: T): T => { 114 | if (array instanceof Uint8Array) { 115 | for (let i = 0; i < array.length; i++) { 116 | array[i] = i % 256; // Predictable sequence for testing 117 | } 118 | } 119 | return array; 120 | }, 121 | ), 122 | })); 123 | 124 | try { 125 | const generator = createRandomStringGenerator("a-z"); 126 | // Generate a long string to ensure all characters are represented 127 | const randomString = generator(256, "A-Z", "0-9"); 128 | 129 | // The combined alphabet we expect 130 | const expectedAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 131 | 132 | // Should use all characters from the expected alphabet 133 | expect( 134 | [...expectedAlphabet].every((char) => randomString.includes(char)), 135 | ).toBe(true); 136 | 137 | // Additionally verify that the string has expected length 138 | expect(randomString).toHaveLength(256); 139 | } finally { 140 | // Restore the original implementation 141 | vi.unmock("uncrypto"); 142 | } 143 | }); 144 | 145 | describe("produces unbiased distribution across characters", () => { 146 | it("with a 26-character alphabet", () => { 147 | // Choose a small alphabet to make bias easier to detect 148 | const alphabet = "a-z"; 149 | const expectedCharSet = "abcdefghijklmnopqrstuvwxyz"; 150 | const charSetLength = expectedCharSet.length; 151 | 152 | // Generate a very large sample to ensure statistical significance 153 | const randomString = generateLargeRandomSample(alphabet); 154 | 155 | // Count occurrences of each character 156 | const charCounts = getCharCounts(randomString, expectedCharSet); 157 | 158 | // Calculate chi-squared statistic for uniformity 159 | const chiSquared = calculateChiSquared( 160 | charCounts, 161 | randomString.length, 162 | charSetLength, 163 | ); 164 | 165 | // For a 26-character alphabet (25 degrees of freedom) at 99.9% confidence, 166 | // the critical chi-squared value is approximately 52.62 167 | // If our value exceeds this, the distribution is likely not uniform 168 | // 169 | // However, truly random values will occasionally produce high chi-squared values 170 | // by chance. To avoid random test failures, we use a much higher threshold 171 | // that would indicate a systematic bias rather than random variation. 172 | 173 | // Critical value multiplied by 3 to reduce false positives 174 | const criticalValue = 52.62 * 3; 175 | 176 | expect(chiSquared).toBeLessThan(criticalValue); 177 | }); 178 | 179 | it("with a 10-character alphabet", () => { 180 | // Also test the distribution with a different, non-power-of-2 alphabet 181 | // which is more likely to expose modulo bias 182 | const alphabet = "0-9"; // 10 characters, not a power of 2 183 | const expectedCharSet = "0123456789"; 184 | const charSetLength = expectedCharSet.length; 185 | 186 | // Generate a very large sample to ensure statistical significance 187 | const randomString = generateLargeRandomSample(alphabet); 188 | 189 | // Count occurrences of each character 190 | const charCounts = getCharCounts(randomString, expectedCharSet); 191 | 192 | // Calculate chi-squared statistic for uniformity 193 | const chiSquared = calculateChiSquared( 194 | charCounts, 195 | randomString.length, 196 | charSetLength, 197 | ); 198 | 199 | // For a 10-character alphabet (9 degrees of freedom) at 99.9% confidence, 200 | // the critical chi-squared value is approximately 27.877 201 | // Again, we multiply by 3 to avoid false positives 202 | const criticalValue = 27.877 * 3; 203 | 204 | expect(chiSquared).toBeLessThan(criticalValue); 205 | 206 | // Check min/max frequency difference as another bias indicator 207 | // In a truly uniform distribution, the difference should be relatively small 208 | const counts = Array.from(charCounts.values()); 209 | const minCount = Math.min(...counts); 210 | const maxCount = Math.max(...counts); 211 | 212 | // Calculate expected count per character in a perfect distribution 213 | const expectedCount = randomString.length / charSetLength; 214 | 215 | // Maximum allowed deviation as a percentage of expected count 216 | // The 0.1 (10%) is chosen to be high enough to avoid random failures 217 | // but low enough to catch serious bias 218 | const maxAllowedDeviation = expectedCount * 0.1; 219 | 220 | expect(maxCount - minCount).toBeLessThan(maxAllowedDeviation); 221 | }); 222 | }); 223 | }); 224 | -------------------------------------------------------------------------------- /src/random.ts: -------------------------------------------------------------------------------- 1 | import { getRandomValues } from "uncrypto"; 2 | 3 | type Alphabet = "a-z" | "A-Z" | "0-9" | "-_"; 4 | 5 | function expandAlphabet(alphabet: Alphabet): string { 6 | switch (alphabet) { 7 | case "a-z": 8 | return "abcdefghijklmnopqrstuvwxyz"; 9 | case "A-Z": 10 | return "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 11 | case "0-9": 12 | return "0123456789"; 13 | case "-_": 14 | return "-_"; 15 | default: 16 | throw new Error(`Unsupported alphabet: ${alphabet}`); 17 | } 18 | } 19 | 20 | export function createRandomStringGenerator( 21 | ...baseAlphabets: A[] 22 | ) { 23 | const baseCharSet = baseAlphabets.map(expandAlphabet).join(""); 24 | if (baseCharSet.length === 0) { 25 | throw new Error( 26 | "No valid characters provided for random string generation.", 27 | ); 28 | } 29 | 30 | const baseCharSetLength = baseCharSet.length; 31 | 32 | return (length: number, ...alphabets: SubA[]) => { 33 | if (length <= 0) { 34 | throw new Error("Length must be a positive integer."); 35 | } 36 | 37 | let charSet = baseCharSet; 38 | let charSetLength = baseCharSetLength; 39 | 40 | if (alphabets.length > 0) { 41 | charSet = alphabets.map(expandAlphabet).join(""); 42 | charSetLength = charSet.length; 43 | } 44 | 45 | const maxValid = Math.floor(256 / charSetLength) * charSetLength; 46 | const buf = new Uint8Array(length * 2); 47 | const bufLength = buf.length; 48 | 49 | let result = ""; 50 | let bufIndex = bufLength; 51 | let rand: number; 52 | 53 | while (result.length < length) { 54 | if (bufIndex >= bufLength) { 55 | getRandomValues(buf); 56 | bufIndex = 0; 57 | } 58 | 59 | rand = buf[bufIndex++]; 60 | 61 | // avoid modulo bias 62 | if (rand < maxValid) { 63 | result += charSet[rand % charSetLength]; 64 | } 65 | } 66 | 67 | return result; 68 | }; 69 | } 70 | -------------------------------------------------------------------------------- /src/rsa.test.ts: -------------------------------------------------------------------------------- 1 | import { rsa } from "./rsa"; // Import the RSA module 2 | import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; 3 | 4 | describe("RSA Module", () => { 5 | const mockKeyPair = { 6 | publicKey: {} as CryptoKey, 7 | privateKey: {} as CryptoKey, 8 | }; 9 | 10 | beforeEach(() => { 11 | vi.spyOn(globalThis.crypto.subtle, "generateKey").mockResolvedValue( 12 | mockKeyPair, 13 | ); 14 | vi.spyOn(globalThis.crypto.subtle, "exportKey").mockResolvedValue( 15 | new ArrayBuffer(16), 16 | ); 17 | vi.spyOn(globalThis.crypto.subtle, "importKey").mockResolvedValue( 18 | mockKeyPair.publicKey, 19 | ); 20 | vi.spyOn(globalThis.crypto.subtle, "encrypt").mockResolvedValue( 21 | new ArrayBuffer(16), 22 | ); 23 | vi.spyOn(globalThis.crypto.subtle, "decrypt").mockResolvedValue( 24 | new ArrayBuffer(16), 25 | ); 26 | vi.spyOn(globalThis.crypto.subtle, "sign").mockResolvedValue( 27 | new ArrayBuffer(16), 28 | ); 29 | vi.spyOn(globalThis.crypto.subtle, "verify").mockResolvedValue(true); 30 | }); 31 | 32 | afterEach(() => { 33 | vi.restoreAllMocks(); 34 | }); 35 | 36 | describe("generateKeyPair", () => { 37 | it("should generate an RSA key pair", async () => { 38 | const keyPair = await rsa.generateKeyPair(); 39 | 40 | expect(keyPair).toBe(mockKeyPair); 41 | expect(globalThis.crypto.subtle.generateKey).toHaveBeenCalledWith( 42 | expect.objectContaining({ 43 | name: "RSA-OAEP", 44 | modulusLength: 2048, 45 | publicExponent: new Uint8Array([0x01, 0x00, 0x01]), 46 | hash: { name: "SHA-256" }, 47 | }), 48 | true, 49 | ["encrypt", "decrypt"], 50 | ); 51 | }); 52 | }); 53 | 54 | describe("exportKey", () => { 55 | it("should export a key in the given format", async () => { 56 | const exportedKey = await rsa.exportKey(mockKeyPair.publicKey, "jwk"); 57 | 58 | expect(exportedKey).toBeInstanceOf(ArrayBuffer); 59 | expect(globalThis.crypto.subtle.exportKey).toHaveBeenCalledWith( 60 | "jwk", 61 | mockKeyPair.publicKey, 62 | ); 63 | }); 64 | }); 65 | 66 | describe("importKey", () => { 67 | it("should import a key from JWK format", async () => { 68 | const mockJWK: JsonWebKey = { 69 | kty: "RSA", 70 | e: "AQAB", 71 | n: "some-modulus", 72 | alg: "RSA-OAEP", 73 | }; 74 | 75 | const importedKey = await rsa.importKey(mockJWK, "encrypt"); 76 | 77 | expect(importedKey).toBe(mockKeyPair.publicKey); 78 | expect(globalThis.crypto.subtle.importKey).toHaveBeenCalledWith( 79 | "jwk", 80 | mockJWK, 81 | expect.objectContaining({ name: "RSA-OAEP" }), 82 | true, 83 | ["encrypt"], 84 | ); 85 | }); 86 | }); 87 | 88 | describe("encrypt", () => { 89 | it("should encrypt data using RSA-OAEP", async () => { 90 | const data = "test data"; 91 | const encryptedData = await rsa.encrypt(mockKeyPair.publicKey, data); 92 | 93 | expect(encryptedData).toBeInstanceOf(ArrayBuffer); 94 | expect(globalThis.crypto.subtle.encrypt).toHaveBeenCalledWith( 95 | { name: "RSA-OAEP" }, 96 | mockKeyPair.publicKey, 97 | new TextEncoder().encode(data), 98 | ); 99 | }); 100 | }); 101 | 102 | describe("decrypt", () => { 103 | it("should decrypt data using RSA-OAEP", async () => { 104 | const encryptedData = new ArrayBuffer(16); 105 | const decryptedData = await rsa.decrypt( 106 | mockKeyPair.privateKey, 107 | encryptedData, 108 | ); 109 | 110 | expect(decryptedData).toBeInstanceOf(ArrayBuffer); 111 | expect(globalThis.crypto.subtle.decrypt).toHaveBeenCalledWith( 112 | { name: "RSA-OAEP" }, 113 | mockKeyPair.privateKey, 114 | encryptedData, 115 | ); 116 | }); 117 | }); 118 | 119 | describe("sign", () => { 120 | it("should sign data using RSA-PSS", async () => { 121 | const data = "test data"; 122 | const signature = await rsa.sign(mockKeyPair.privateKey, data); 123 | 124 | expect(signature).toBeInstanceOf(ArrayBuffer); 125 | expect(globalThis.crypto.subtle.sign).toHaveBeenCalledWith( 126 | { name: "RSA-PSS", saltLength: 32 }, 127 | mockKeyPair.privateKey, 128 | new TextEncoder().encode(data), 129 | ); 130 | }); 131 | }); 132 | 133 | describe("verify", () => { 134 | it("should verify data using RSA-PSS", async () => { 135 | const signature = new ArrayBuffer(16); 136 | const data = "test data"; 137 | const isValid = await rsa.verify(mockKeyPair.publicKey, { 138 | signature, 139 | data, 140 | }); 141 | 142 | expect(isValid).toBe(true); 143 | expect(globalThis.crypto.subtle.verify).toHaveBeenCalledWith( 144 | { name: "RSA-PSS", saltLength: 32 }, 145 | mockKeyPair.publicKey, 146 | signature, 147 | new TextEncoder().encode(data), 148 | ); 149 | }); 150 | }); 151 | }); 152 | -------------------------------------------------------------------------------- /src/rsa.ts: -------------------------------------------------------------------------------- 1 | import { subtle } from "uncrypto"; 2 | 3 | type ExportFormat = "jwk" | "spki" | "pkcs8"; 4 | 5 | export const rsa = { 6 | generateKeyPair: async ( 7 | modulusLength: 2048 | 4096 = 2048, 8 | hash: "SHA-256" | "SHA-384" | "SHA-512" = "SHA-256", 9 | ) => { 10 | return await subtle.generateKey( 11 | { 12 | name: "RSA-OAEP", 13 | modulusLength, 14 | publicExponent: new Uint8Array([0x01, 0x00, 0x01]), 15 | hash: { name: hash }, 16 | }, 17 | true, 18 | ["encrypt", "decrypt"], 19 | ); 20 | }, 21 | exportKey: async ( 22 | key: CryptoKey, 23 | format: E, 24 | ): Promise => { 25 | return (await subtle.exportKey(format, key)) as any; 26 | }, 27 | importKey: async ( 28 | key: JsonWebKey, 29 | usage: "encrypt" | "decrypt" = "encrypt", 30 | hash: "SHA-256" | "SHA-384" | "SHA-512" = "SHA-256", 31 | ) => { 32 | return await subtle.importKey( 33 | "jwk", 34 | key, 35 | { 36 | name: "RSA-OAEP", 37 | hash: { name: hash }, 38 | }, 39 | true, 40 | [usage], 41 | ); 42 | }, 43 | encrypt: async ( 44 | key: CryptoKey, 45 | data: string | ArrayBuffer | ArrayBufferView, 46 | ) => { 47 | const encodedData = 48 | typeof data === "string" ? new TextEncoder().encode(data) : data; 49 | return await subtle.encrypt({ name: "RSA-OAEP" }, key, encodedData); 50 | }, 51 | decrypt: async (key: CryptoKey, data: ArrayBuffer | ArrayBufferView) => { 52 | return await subtle.decrypt({ name: "RSA-OAEP" }, key, data); 53 | }, 54 | sign: async ( 55 | key: CryptoKey, 56 | data: string | ArrayBuffer | ArrayBufferView, 57 | saltLength = 32, 58 | ) => { 59 | const encodedData = 60 | typeof data === "string" ? new TextEncoder().encode(data) : data; 61 | return await subtle.sign( 62 | { 63 | name: "RSA-PSS", 64 | saltLength, 65 | }, 66 | key, 67 | encodedData, 68 | ); 69 | }, 70 | verify: async ( 71 | key: CryptoKey, 72 | { 73 | signature, 74 | data, 75 | saltLength = 32, 76 | }: { 77 | signature: ArrayBuffer | ArrayBufferView | string; 78 | data: string | ArrayBuffer | ArrayBufferView | string; 79 | saltLength?: number; 80 | }, 81 | ) => { 82 | if (typeof signature === "string") { 83 | signature = new TextEncoder().encode(signature); 84 | } 85 | const encodedData = 86 | typeof data === "string" ? new TextEncoder().encode(data) : data; 87 | return await subtle.verify( 88 | { 89 | name: "RSA-PSS", 90 | saltLength, 91 | }, 92 | key, 93 | signature, 94 | encodedData, 95 | ); 96 | }, 97 | }; 98 | -------------------------------------------------------------------------------- /src/type.ts: -------------------------------------------------------------------------------- 1 | export type TypedArray = 2 | | Uint8Array 3 | | Int8Array 4 | | Uint16Array 5 | | Int16Array 6 | | Uint32Array 7 | | Int32Array 8 | | Float32Array 9 | | Float64Array 10 | | BigInt64Array 11 | | BigUint64Array; 12 | 13 | export type SHAFamily = "SHA-1" | "SHA-256" | "SHA-384" | "SHA-512"; 14 | export type EncodingFormat = 15 | | "hex" 16 | | "base64" 17 | | "base64url" 18 | | "base64urlnopad" 19 | | "none"; 20 | export type ECDSACurve = "P-256" | "P-384" | "P-521"; 21 | export type ExportKeyFormat = "jwk" | "spki" | "pkcs8" | "raw"; 22 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "skipLibCheck": true, 5 | "target": "es2022", 6 | "allowJs": true, 7 | "resolveJsonModule": true, 8 | "moduleDetection": "force", 9 | "isolatedModules": true, 10 | "verbatimModuleSyntax": true, 11 | "strict": true, 12 | "module": "preserve", 13 | "noEmit": true, 14 | "declaration": true, 15 | "lib": ["es2022", "dom", "dom.iterable"] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitest/config"; 2 | 3 | export default defineConfig({ 4 | test: { 5 | globals: true, 6 | environment: "happy-dom", 7 | }, 8 | }); 9 | --------------------------------------------------------------------------------