diff --git a/examples/demo-vue-books/package.json b/examples/demo-vue-books/package.json index 12d1112d..04c850b6 100644 --- a/examples/demo-vue-books/package.json +++ b/examples/demo-vue-books/package.json @@ -17,10 +17,9 @@ "vue": "^3.5.13" }, "devDependencies": { - "@vitejs/plugin-vue": "^5.2.3", + "@vitejs/plugin-vue": "^6.0.0", "typescript": "^5.7.3", - "vite": "^6.2.0", + "vite": "^8.0.0", "vue-tsc": "^2.2.0" } } - diff --git a/examples/demo-zk-books/pom.xml b/examples/demo-zk-books/pom.xml index 23f28cb5..cf3c6c70 100644 --- a/examples/demo-zk-books/pom.xml +++ b/examples/demo-zk-books/pom.xml @@ -47,7 +47,7 @@ ${maven.build.timestamp} yyyyMMdd - 26.5.1 + 26.5.2 diff --git a/extensions/dashboard/sources/pom.xml b/extensions/dashboard/sources/pom.xml index e5540895..fd560126 100644 --- a/extensions/dashboard/sources/pom.xml +++ b/extensions/dashboard/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml @@ -38,12 +38,12 @@ tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.saas.api - 26.5.1 + 26.5.2 diff --git a/extensions/email-sms/sources/core/pom.xml b/extensions/email-sms/sources/core/pom.xml index aea065c7..240cb44b 100644 --- a/extensions/email-sms/sources/core/pom.xml +++ b/extensions/email-sms/sources/core/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules.email.parent tools.dynamia.modules - 26.5.1 + 26.5.2 tools.dynamia.modules.email @@ -50,12 +50,12 @@ tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.templates - 26.5.1 + 26.5.2 org.springframework diff --git a/extensions/email-sms/sources/pom.xml b/extensions/email-sms/sources/pom.xml index bf2bf723..c027865c 100644 --- a/extensions/email-sms/sources/pom.xml +++ b/extensions/email-sms/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml @@ -85,7 +85,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.5.1 + 26.5.2 diff --git a/extensions/email-sms/sources/ui/pom.xml b/extensions/email-sms/sources/ui/pom.xml index d0ac8639..52152b7a 100644 --- a/extensions/email-sms/sources/ui/pom.xml +++ b/extensions/email-sms/sources/ui/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules.email.parent tools.dynamia.modules - 26.5.1 + 26.5.2 DynamiaModules - Email UI @@ -34,12 +34,12 @@ tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.email - 26.5.1 + 26.5.2 tools.dynamia.zk.addons diff --git a/extensions/entity-files/packages/files-sdk/package.json b/extensions/entity-files/packages/files-sdk/package.json index 2bd9e653..50094a6d 100644 --- a/extensions/entity-files/packages/files-sdk/package.json +++ b/extensions/entity-files/packages/files-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/files-sdk", - "version": "26.5.1", + "version": "26.5.2", "website": "https://dynamia.tools", "description": "TypeScript/JavaScript client SDK for the Dynamia Entity Files extension REST API", "keywords": [ @@ -65,11 +65,14 @@ }, "devDependencies": { "@dynamia-tools/sdk": "workspace:*", - "@types/node": "^22.0.0", + "@types/node": "^24.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", - "vitest": "^3.0.0", - "@vitest/coverage-v8": "^3.0.0" + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", + "vitest": "^4.0.0", + "@vitest/coverage-v8": "^4.0.0" + }, + "engines": { + "node": ">=24" } } diff --git a/extensions/entity-files/packages/simple-file-server/README.md b/extensions/entity-files/packages/simple-file-server/README.md deleted file mode 100644 index 910d4dea..00000000 --- a/extensions/entity-files/packages/simple-file-server/README.md +++ /dev/null @@ -1,369 +0,0 @@ -# simple-file-server (SFS) - -A standalone filesystem-native file server with a minimal S3-style API optimized for secure server-to-server file operations. - -## Overview - -SFS is designed as the backend for `RemoteSimpleEntityFileStorage` in EntityFiles and optimized for: - -- ERP systems and multi-tenant applications -- Internal services and hybrid infrastructure -- Large file streaming with constant memory usage -- Low operational complexity (no database, no external dependencies) - -## Quick Start - -### Installation - -```bash -npm install -g @dynamia-tools/simple-file-server -``` - -### Initialize and configure - -```bash -# Create a bucket -sfs create bucket documents /mnt/storage/documents - -# Create an identity -sfs create identity erp-prod my-secret-password - -# Grant permissions -sfs grant erp-prod documents --read --write --delete --prefix /tenant-a/ - -# Start the server -sfs serve --host 0.0.0.0 --port 8080 -``` - -## API - -All requests require authentication via `X-SFS-Identity` + `X-SFS-Secret` headers, or HTTP Basic Auth. - -### Download a file -```http -GET /:bucket/:key -X-SFS-Identity: erp-prod -X-SFS-Secret: my-secret-password -``` - -### Download a thumbnail -```http -GET /:bucket/:key?w=300&h=300&fit=cover&format=webp -``` - -### List a directory -```http -GET /:bucket/:path/ -``` - -### List bucket contents (paginated) -```http -GET /:bucket?limit=100&cursor=... -``` - -### Upload a file -```http -PUT /:bucket/:key -Content-Type: application/octet-stream -[body: file stream] -``` - -### Delete a file -```http -DELETE /:bucket/:key -``` - -### Health check -```http -GET /health -``` - -## curl Examples - -All examples assume the server is running at `http://localhost:8080` with identity `erp-prod` and secret `my-secret-password`. - -### Health check - -```bash -curl http://localhost:8080/health -``` - -### Upload a file - -```bash -curl -X PUT http://localhost:8080/documents/tenant-a/invoice.pdf \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @/path/to/invoice.pdf -``` - -### Upload a file using HTTP Basic Auth - -```bash -curl -X PUT http://localhost:8080/documents/tenant-a/report.xlsx \ - -u "erp-prod:my-secret-password" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @/path/to/report.xlsx -``` - -### Download a file - -```bash -curl http://localhost:8080/documents/tenant-a/invoice.pdf \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" \ - -o invoice.pdf -``` - -### Download a thumbnail (image resize on the fly) - -```bash -# 300×300 WebP thumbnail with cover fit -curl "http://localhost:8080/documents/tenant-a/photo.jpg?w=300&h=300&fit=cover&format=webp" \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" \ - -o thumbnail.webp -``` - -### List a directory - -```bash -curl http://localhost:8080/documents/tenant-a/ \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" -``` - -### List bucket contents (paginated) - -```bash -# First page -curl "http://localhost:8080/documents?limit=50" \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" - -# Next page using the cursor returned from the previous response -curl "http://localhost:8080/documents?limit=50&cursor=" \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" -``` - -### Delete a file - -```bash -curl -X DELETE http://localhost:8080/documents/tenant-a/invoice.pdf \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" -``` - -### Pretty-print JSON responses - -Pipe responses through `jq` for readable output: - -```bash -curl -s "http://localhost:8080/documents/tenant-a/" \ - -H "X-SFS-Identity: erp-prod" \ - -H "X-SFS-Secret: my-secret-password" | jq -``` - -## CLI Reference - -### Tab Completion - -SFS supports tab completion for Bash, Zsh and Fish. - -```bash -# Bash — add to ~/.bashrc -eval "$(sfs completion bash)" - -# Zsh — add to ~/.zshrc (compinit must already be loaded) -eval "$(sfs completion zsh)" - -# Fish — save to completions directory -sfs completion fish > ~/.config/fish/completions/sfs.fish -``` - -Completion is dynamic: bucket names and identity names are resolved at completion time by querying the local SFS runtime. - -```bash -# Server -sfs serve [--host ] [--port ] [--data-dir ] [--log-level ] - -# Buckets -sfs create bucket -sfs list buckets -sfs remove bucket - -# Identities -sfs create identity -sfs list identities -sfs remove identity - -# Permissions -sfs grant --read --write --delete --prefix -sfs revoke - -# Files -sfs list files [path] # List files in a bucket or directory -sfs upload # Upload a local file to a bucket -sfs copy # Copy a file between buckets - -# Provisioning (auto-generate identity + secret + grant in one step) -sfs provision [--identity ] [--prefix ] [--read] [--write] [--delete] -``` - -## Data Directory Structure - -SFS stores all runtime configuration under a `.sfs/` directory in the working directory: - -``` -.sfs/ - ├── config/ # Server configuration - ├── identities/ # Identity definitions + hashed secrets + grants - ├── buckets/ # Bucket definitions - ├── logs/ # Operational logs (JSONL format) - │ ├── access.log.jsonl - │ └── error.log.jsonl - ├── runtime/ # Runtime metadata - └── cache/ # (reserved) -``` - -Each bucket also contains an internal `.sfs/` directory: - -``` -/path/to/bucket/ - └── .sfs/ - ├── staging/ # Upload staging area - ├── thumbs/ # Thumbnail cache - └── runtime/ # Temporary artifacts -``` - -## Security - -- **Private by default**: every request requires authentication -- **Argon2id password hashing**: secrets are never stored in plain text -- **Prefix-based authorization**: access restricted by bucket and path prefix -- **Path traversal protection**: canonical path validation on every request -- **No public access**: no anonymous or public bucket support - -## Requirements - -| Requirement | Minimum version | -|---|---| -| Node.js | **18.17.0** | -| npm | 9+ (or pnpm 8+) | - -> **Why 18.17.0?** The `sharp` native image-processing library requires exactly `^18.17.0` as the lowest Node 18 patch that ships a compatible binary. All other dependencies support Node ≥ 18. - -## Embedded Usage - -You can start SFS programmatically inside your own Node.js application — no CLI needed. - -### Installation - -```bash -npm install @dynamia-tools/simple-file-server -``` - -### Minimal example - -```js -// index.js (type: "module") -import { startServer } from '@dynamia-tools/simple-file-server' - -// Reads configuration from the .sfs/ directory in process.cwd(). -// Provision buckets and identities first with the CLI, or do it -// programmatically (see "Full programmatic setup" below). -startServer({ - host: process.env.SFS_HOST ?? '0.0.0.0', - port: parseInt(process.env.SFS_PORT ?? '8080', 10), -}).catch((err) => { - console.error('Fatal error during startup:', err) - process.exit(1) -}) -``` - -### Full programmatic setup - -Use `createRuntime` to bootstrap services and configure buckets/identities entirely in code: - -```js -import path from 'node:path' -import { createRuntime, createServer } from '@dynamia-tools/simple-file-server' - -const runtime = await createRuntime({ - dataDir: path.join(process.cwd(), '.sfs'), - host: '0.0.0.0', - port: 8080, - logLevel: 'info', -}) - -const { config, bucketService, storageService, thumbnailService, - identityService, operationalLogger } = runtime - -// Create a bucket (idempotent pattern) -if (!await bucketService.find('documents')) { - await bucketService.create('documents', '/mnt/storage/documents') -} - -// Create an identity (idempotent pattern) -if (!await identityService.find('app-user')) { - await identityService.create('app-user', process.env.APP_SECRET ?? 'changeme') -} - -// Grant permissions -await identityService.grant('app-user', { - bucket: 'documents', - prefixes: ['/'], // entire bucket - permissions: ['read', 'write', 'delete'], -}) - -// Validate buckets and start the server -await bucketService.validateStartup() - -const server = await createServer({ - config, bucketService, storageService, - thumbnailService, identityService, operationalLogger, -}) - -process.on('SIGTERM', async () => { await server.close(); process.exit(0) }) -process.on('SIGINT', async () => { await server.close(); process.exit(0) }) - -await server.listen({ host: config.host, port: config.port }) -``` - -### Available exports - -| Export | Description | -|---|---| -| `startServer(overrides?)` | One-call bootstrap: creates runtime + server + starts listening | -| `createRuntime(overrides?)` | Initialises services and data dirs, returns the `SFSRuntime` object | -| `createServer(runtime)` | Builds and returns the Fastify instance (does not call `.listen`) | -| `BucketService` | Manage bucket definitions | -| `IdentityService` | Manage identities and grants | -| `StorageService` | Low-level file upload / download / list | -| `ThumbnailService` | On-the-fly image thumbnails via Sharp | -| `OperationalLogger` | Structured JSONL access + error logs | - -### Environment variables - -| Variable | Default | Description | -|---|---|---| -| `SFS_DATA_DIR` | `/.sfs` | Where SFS stores config, identities and buckets | -| `SFS_HOST` | `0.0.0.0` | Bind host | -| `SFS_PORT` | `8080` | Bind port | -| `SFS_LOG_LEVEL` | `info` | Pino log level (`trace` `debug` `info` `warn` `error`) | - -## Technology Stack - -- **Node.js 18.17+** with TypeScript (strict mode) -- **Fastify** for high-throughput HTTP -- **Pino** for structured JSON logging -- **Sharp** for efficient thumbnail generation -- **Argon2** for password hashing -- **file-type** for MIME detection via magic bytes - -## License - -Apache-2.0 © Dynamia Soluciones IT SAS - diff --git a/extensions/entity-files/packages/simple-file-server/examples/embedded/index.js b/extensions/entity-files/packages/simple-file-server/examples/embedded/index.js deleted file mode 100644 index 44db7473..00000000 --- a/extensions/entity-files/packages/simple-file-server/examples/embedded/index.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * simple-file-server — Embedded Mode Example - * - * Starts the server using the configuration already present in the - * current working directory (.sfs/ folder). No extra setup is done - * here — use the CLI (`sfs create bucket …`, `sfs create identity …`) - * to provision buckets and identities beforehand. - * - * Configuration via environment variables (all optional): - * SFS_HOST – bind host (default: 0.0.0.0) - * SFS_PORT – bind port (default: 8500) - * SFS_LOG_LEVEL – log level (default: info) - * - * Usage: - * npm install - * npm start - */ -import { startServer } from '@dynamia-tools/simple-file-server' - -const PORT = parseInt(process.env.SFS_PORT ?? '8500', 10) -const HOST = process.env.SFS_HOST ?? '0.0.0.0' - -startServer({ port: PORT, host: HOST }).catch((err) => { - console.error('Fatal error during startup:', err) - process.exit(1) -}) diff --git a/extensions/entity-files/packages/simple-file-server/examples/embedded/package.json b/extensions/entity-files/packages/simple-file-server/examples/embedded/package.json deleted file mode 100644 index aaa6f98a..00000000 --- a/extensions/entity-files/packages/simple-file-server/examples/embedded/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "sfs-embedded-example", - "version": "1.0.0", - "description": "Example: using simple-file-server in embedded mode (programmatic API)", - "type": "module", - "scripts": { - "start": "node index.js", - "start:debug": "node --inspect index.js" - }, - "dependencies": { - "@dynamia-tools/simple-file-server": "^26.5.0" - }, - "engines": { - "node": ">=18.17.0" - } -} - diff --git a/extensions/entity-files/packages/simple-file-server/package-lock.json b/extensions/entity-files/packages/simple-file-server/package-lock.json deleted file mode 100644 index 5a6f304e..00000000 --- a/extensions/entity-files/packages/simple-file-server/package-lock.json +++ /dev/null @@ -1,3808 +0,0 @@ -{ - "name": "@dynamia-tools/simple-file-server", - "version": "26.5.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@dynamia-tools/simple-file-server", - "version": "26.5.1", - "license": "Apache-2.0", - "dependencies": { - "@fastify/sensible": "^6.0.4", - "argon2": "^0.43.0", - "commander": "^13.1.0", - "fastify": "^5.3.0", - "fastify-plugin": "^5.1.0", - "file-type": "^20.0.0", - "pino": "^9.7.0", - "pino-pretty": "^13.0.0", - "sharp": "^0.34.1", - "zod": "^3.24.0" - }, - "bin": { - "sfs": "dist/cli/index.js", - "sfs-test": "dist/cli/index.js" - }, - "devDependencies": { - "@types/node": "^22.0.0", - "@types/sharp": "^0.31.0", - "tsx": "^4.19.0", - "typescript": "^5.7.0", - "vitest": "^3.0.0" - }, - "engines": { - "node": ">=18.17.0" - } - }, - "node_modules/@borewit/text-codec": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", - "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", - "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", - "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", - "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", - "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", - "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", - "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", - "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", - "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", - "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", - "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", - "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", - "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", - "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", - "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", - "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", - "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", - "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", - "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", - "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", - "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", - "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", - "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", - "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", - "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", - "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", - "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@fastify/ajv-compiler": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@fastify/ajv-compiler/-/ajv-compiler-4.0.5.tgz", - "integrity": "sha512-KoWKW+MhvfTRWL4qrhUwAAZoaChluo0m0vbiJlGMt2GXvL4LVPQEjt8kSpHI3IBq5Rez8fg+XeH3cneztq+C7A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "fast-uri": "^3.0.0" - } - }, - "node_modules/@fastify/error": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@fastify/error/-/error-4.2.0.tgz", - "integrity": "sha512-RSo3sVDXfHskiBZKBPRgnQTtIqpi/7zhJOEmAxCiBcM7d0uwdGdxLlsCaLzGs8v8NnxIRlfG0N51p5yFaOentQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/@fastify/fast-json-stringify-compiler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-5.0.3.tgz", - "integrity": "sha512-uik7yYHkLr6fxd8hJSZ8c+xF4WafPK+XzneQDPU+D10r5X19GW8lJcom2YijX2+qtFF1ENJlHXKFM9ouXNJYgQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "fast-json-stringify": "^6.0.0" - } - }, - "node_modules/@fastify/forwarded": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@fastify/forwarded/-/forwarded-3.0.1.tgz", - "integrity": "sha512-JqDochHFqXs3C3Ml3gOY58zM7OqO9ENqPo0UqAjAjH8L01fRZqwX9iLeX34//kiJubF7r2ZQHtBRU36vONbLlw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/@fastify/merge-json-schemas": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@fastify/merge-json-schemas/-/merge-json-schemas-0.2.1.tgz", - "integrity": "sha512-OA3KGBCy6KtIvLf8DINC5880o5iBlDX4SxzLQS8HorJAbqluzLRn80UXU0bxZn7UOFhFgpRJDasfwn9nG4FG4A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/@fastify/proxy-addr": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@fastify/proxy-addr/-/proxy-addr-5.1.0.tgz", - "integrity": "sha512-INS+6gh91cLUjB+PVHfu1UqcB76Sqtpyp7bnL+FYojhjygvOPA9ctiD/JDKsyD9Xgu4hUhCSJBPig/w7duNajw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/forwarded": "^3.0.0", - "ipaddr.js": "^2.1.0" - } - }, - "node_modules/@fastify/sensible": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@fastify/sensible/-/sensible-6.0.4.tgz", - "integrity": "sha512-1vxcCUlPMew6WroK8fq+LVOwbsLtX+lmuRuqpcp6eYqu6vmkLwbKTdBWAZwbeaSgCfW4tzUpTIHLLvTiQQ1BwQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@lukeed/ms": "^2.0.2", - "dequal": "^2.0.3", - "fastify-plugin": "^5.0.0", - "forwarded": "^0.2.0", - "http-errors": "^2.0.0", - "type-is": "^2.0.1", - "vary": "^1.1.2" - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@lukeed/ms": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", - "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@phc/format": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", - "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/@pinojs/redact": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", - "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", - "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", - "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", - "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", - "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", - "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", - "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", - "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", - "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", - "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", - "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", - "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", - "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", - "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", - "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", - "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", - "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", - "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", - "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", - "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", - "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", - "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", - "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", - "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", - "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", - "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@tokenizer/inflate": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.2.7.tgz", - "integrity": "sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==", - "license": "MIT", - "dependencies": { - "debug": "^4.4.0", - "fflate": "^0.8.2", - "token-types": "^6.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/@tokenizer/token": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", - "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", - "license": "MIT" - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "22.19.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.19.tgz", - "integrity": "sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/sharp": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.1.tgz", - "integrity": "sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@vitest/expect": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", - "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", - "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.2.4", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", - "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", - "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "3.2.4", - "pathe": "^2.0.3", - "strip-literal": "^3.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", - "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.4", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", - "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^4.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", - "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.2.4", - "loupe": "^3.1.4", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/abstract-logging": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz", - "integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==", - "license": "MIT" - }, - "node_modules/ajv": { - "version": "8.20.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", - "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/argon2": { - "version": "0.43.1", - "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.43.1.tgz", - "integrity": "sha512-TfOzvDWUaQPurCT1hOwIeFNkgrAJDpbBGBGWDgzDsm11nNhImc13WhdGdCU6K7brkp8VpeY07oGtSex0Wmhg8w==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@phc/format": "^1.0.0", - "node-addon-api": "^8.4.0", - "node-gyp-build": "^4.8.4" - }, - "engines": { - "node": ">=16.17.0" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/atomic-sleep": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", - "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/avvio": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-9.2.0.tgz", - "integrity": "sha512-2t/sy01ArdHHE0vRH5Hsay+RtCZt3dLPji7W7/MMOCEgze5b7SNDC4j5H6FnVgPkI1MTNFGzHdHrVXDDl7QSSQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/error": "^4.0.0", - "fastq": "^1.17.1" - } - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/check-error": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", - "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "license": "MIT" - }, - "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/content-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", - "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/dateformat": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", - "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", - "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.0", - "@esbuild/android-arm": "0.28.0", - "@esbuild/android-arm64": "0.28.0", - "@esbuild/android-x64": "0.28.0", - "@esbuild/darwin-arm64": "0.28.0", - "@esbuild/darwin-x64": "0.28.0", - "@esbuild/freebsd-arm64": "0.28.0", - "@esbuild/freebsd-x64": "0.28.0", - "@esbuild/linux-arm": "0.28.0", - "@esbuild/linux-arm64": "0.28.0", - "@esbuild/linux-ia32": "0.28.0", - "@esbuild/linux-loong64": "0.28.0", - "@esbuild/linux-mips64el": "0.28.0", - "@esbuild/linux-ppc64": "0.28.0", - "@esbuild/linux-riscv64": "0.28.0", - "@esbuild/linux-s390x": "0.28.0", - "@esbuild/linux-x64": "0.28.0", - "@esbuild/netbsd-arm64": "0.28.0", - "@esbuild/netbsd-x64": "0.28.0", - "@esbuild/openbsd-arm64": "0.28.0", - "@esbuild/openbsd-x64": "0.28.0", - "@esbuild/openharmony-arm64": "0.28.0", - "@esbuild/sunos-x64": "0.28.0", - "@esbuild/win32-arm64": "0.28.0", - "@esbuild/win32-ia32": "0.28.0", - "@esbuild/win32-x64": "0.28.0" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fast-copy": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.3.tgz", - "integrity": "sha512-58apWr0GUiDFM8+3afrO6eYwJBn9ZAhDOzG3L+/9llab/haCARS2UIfffmOurYLwbgDRs8n0rfr6qAAPEAuAQw==", - "license": "MIT" - }, - "node_modules/fast-decode-uri-component": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", - "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-json-stringify": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-6.4.0.tgz", - "integrity": "sha512-ibRCQ0GZKJIQ+P3Et1h0LhPgp3PMTYk0MH8O+kW3lNYsvmaQww5Nn3f1jf73Q0jR1Yz3a1CDP4/NZD3vOajWJQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/merge-json-schemas": "^0.2.0", - "ajv": "^8.12.0", - "ajv-formats": "^3.0.1", - "fast-uri": "^3.0.0", - "json-schema-ref-resolver": "^3.0.0", - "rfdc": "^1.2.0" - } - }, - "node_modules/fast-querystring": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", - "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", - "license": "MIT", - "dependencies": { - "fast-decode-uri-component": "^1.0.1" - } - }, - "node_modules/fast-safe-stringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", - "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastify": { - "version": "5.8.5", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-5.8.5.tgz", - "integrity": "sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "@fastify/ajv-compiler": "^4.0.5", - "@fastify/error": "^4.0.0", - "@fastify/fast-json-stringify-compiler": "^5.0.0", - "@fastify/proxy-addr": "^5.0.0", - "abstract-logging": "^2.0.1", - "avvio": "^9.0.0", - "fast-json-stringify": "^6.0.0", - "find-my-way": "^9.0.0", - "light-my-request": "^6.0.0", - "pino": "^9.14.0 || ^10.1.0", - "process-warning": "^5.0.0", - "rfdc": "^1.3.1", - "secure-json-parse": "^4.0.0", - "semver": "^7.6.0", - "toad-cache": "^3.7.0" - } - }, - "node_modules/fastify-plugin": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/fastify-plugin/-/fastify-plugin-5.1.0.tgz", - "integrity": "sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fflate": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", - "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", - "license": "MIT" - }, - "node_modules/file-type": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-20.5.0.tgz", - "integrity": "sha512-BfHZtG/l9iMm4Ecianu7P8HRD2tBHLtjXinm4X62XBOYzi7CYA7jyqfJzOvXHqzVrVPYqBo2/GvbARMaaJkKVg==", - "license": "MIT", - "dependencies": { - "@tokenizer/inflate": "^0.2.6", - "strtok3": "^10.2.0", - "token-types": "^6.0.0", - "uint8array-extras": "^1.4.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/file-type?sponsor=1" - } - }, - "node_modules/find-my-way": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-9.6.0.tgz", - "integrity": "sha512-Zf4Xve4RymLl7NgaavNebZ01joJ8MfVerOG43wy7SHLO+r+K0C6d/SE0BiR7AV5V1VOCFlOP7ecdo+I4qmiHrQ==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-querystring": "^1.0.0", - "safe-regex2": "^5.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/help-me": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", - "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", - "license": "MIT" - }, - "node_modules/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", - "license": "MIT", - "dependencies": { - "depd": "~2.0.0", - "inherits": "~2.0.4", - "setprototypeof": "~1.2.0", - "statuses": "~2.0.2", - "toidentifier": "~1.0.1" - }, - "engines": { - "node": ">= 0.8" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ipaddr.js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", - "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/joycon": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", - "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/js-tokens": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", - "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-ref-resolver": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-3.0.0.tgz", - "integrity": "sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/light-my-request": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", - "integrity": "sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause", - "dependencies": { - "cookie": "^1.0.1", - "process-warning": "^4.0.0", - "set-cookie-parser": "^2.6.0" - } - }, - "node_modules/light-my-request/node_modules/process-warning": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-4.0.1.tgz", - "integrity": "sha512-3c2LzQ3rY9d0hc1emcsHhfT9Jwz0cChib/QN89oME2R451w5fy3f0afAhERFZAwrbDU43wk12d0ORBpDVME50Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", - "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", - "license": "MIT", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-addon-api": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.7.0.tgz", - "integrity": "sha512-9MdFxmkKaOYVTV+XVRG8ArDwwQ77XIgIPyKASB1k3JPq3M8fGQQQE3YpMOrKm6g//Ktx8ivZr8xo1Qmtqub+GA==", - "license": "MIT", - "engines": { - "node": "^18 || ^20 || >= 21" - } - }, - "node_modules/node-gyp-build": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", - "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", - "license": "MIT", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/on-exit-leak-free": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", - "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pino": { - "version": "9.14.0", - "resolved": "https://registry.npmjs.org/pino/-/pino-9.14.0.tgz", - "integrity": "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w==", - "license": "MIT", - "dependencies": { - "@pinojs/redact": "^0.4.0", - "atomic-sleep": "^1.0.0", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^2.0.0", - "pino-std-serializers": "^7.0.0", - "process-warning": "^5.0.0", - "quick-format-unescaped": "^4.0.3", - "real-require": "^0.2.0", - "safe-stable-stringify": "^2.3.1", - "sonic-boom": "^4.0.1", - "thread-stream": "^3.0.0" - }, - "bin": { - "pino": "bin.js" - } - }, - "node_modules/pino-abstract-transport": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz", - "integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/pino-pretty": { - "version": "13.1.3", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz", - "integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==", - "license": "MIT", - "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^4.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^5.0.0", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^3.0.0", - "pump": "^3.0.0", - "secure-json-parse": "^4.0.0", - "sonic-boom": "^4.0.1", - "strip-json-comments": "^5.0.2" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/pino-pretty/node_modules/pino-abstract-transport": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", - "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", - "license": "MIT", - "dependencies": { - "split2": "^4.0.0" - } - }, - "node_modules/pino-std-serializers": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", - "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", - "license": "MIT" - }, - "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/process-warning": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", - "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/quick-format-unescaped": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", - "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", - "license": "MIT" - }, - "node_modules/real-require": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", - "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", - "license": "MIT", - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ret": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.5.0.tgz", - "integrity": "sha512-I1XxrZSQ+oErkRR4jYbAyEEu2I0avBvvMM5JN+6EBprOGRCs63ENqZ3vjavq8fBw2+62G5LF5XelKwuJpcvcxw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "license": "MIT" - }, - "node_modules/rollup": { - "version": "4.60.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", - "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.60.4", - "@rollup/rollup-android-arm64": "4.60.4", - "@rollup/rollup-darwin-arm64": "4.60.4", - "@rollup/rollup-darwin-x64": "4.60.4", - "@rollup/rollup-freebsd-arm64": "4.60.4", - "@rollup/rollup-freebsd-x64": "4.60.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", - "@rollup/rollup-linux-arm-musleabihf": "4.60.4", - "@rollup/rollup-linux-arm64-gnu": "4.60.4", - "@rollup/rollup-linux-arm64-musl": "4.60.4", - "@rollup/rollup-linux-loong64-gnu": "4.60.4", - "@rollup/rollup-linux-loong64-musl": "4.60.4", - "@rollup/rollup-linux-ppc64-gnu": "4.60.4", - "@rollup/rollup-linux-ppc64-musl": "4.60.4", - "@rollup/rollup-linux-riscv64-gnu": "4.60.4", - "@rollup/rollup-linux-riscv64-musl": "4.60.4", - "@rollup/rollup-linux-s390x-gnu": "4.60.4", - "@rollup/rollup-linux-x64-gnu": "4.60.4", - "@rollup/rollup-linux-x64-musl": "4.60.4", - "@rollup/rollup-openbsd-x64": "4.60.4", - "@rollup/rollup-openharmony-arm64": "4.60.4", - "@rollup/rollup-win32-arm64-msvc": "4.60.4", - "@rollup/rollup-win32-ia32-msvc": "4.60.4", - "@rollup/rollup-win32-x64-gnu": "4.60.4", - "@rollup/rollup-win32-x64-msvc": "4.60.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/safe-regex2": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-5.1.1.tgz", - "integrity": "sha512-mOSBvHGDZMuIEZMdOz/aCEYDCv0E7nfcNsIhUF+/P+xC7Hyf3FkvymqgPbg9D1EdSGu+uKbJgy09K/RKKc7kJA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT", - "dependencies": { - "ret": "~0.5.0" - }, - "bin": { - "safe-regex2": "bin/safe-regex2.js" - } - }, - "node_modules/safe-stable-stringify": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", - "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/secure-json-parse": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", - "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/semver": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", - "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" - }, - "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/sonic-boom": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", - "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", - "license": "MIT", - "dependencies": { - "atomic-sleep": "^1.0.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/statuses": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", - "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", - "dev": true, - "license": "MIT" - }, - "node_modules/strip-json-comments": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", - "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-literal": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", - "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^9.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/antfu" - } - }, - "node_modules/strtok3": { - "version": "10.3.5", - "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz", - "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==", - "license": "MIT", - "dependencies": { - "@tokenizer/token": "^0.3.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/thread-stream": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz", - "integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==", - "license": "MIT", - "dependencies": { - "real-require": "^0.2.0" - } - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", - "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/toad-cache": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/toad-cache/-/toad-cache-3.7.0.tgz", - "integrity": "sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==", - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/token-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", - "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", - "license": "MIT", - "dependencies": { - "@borewit/text-codec": "^0.2.1", - "@tokenizer/token": "^0.3.0", - "ieee754": "^1.2.1" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Borewit" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true - }, - "node_modules/tsx": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.0.tgz", - "integrity": "sha512-8ccZMPD69s1AbKXx0C5ddTNZfNjwV04iIKgjZmKfKxMynEtSYcK0Lh7iQFh53fI5Yu4pb9usgAiqyPmEONaALg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-is": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.1.0.tgz", - "integrity": "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==", - "license": "MIT", - "dependencies": { - "content-type": "^2.0.0", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uint8array-extras": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", - "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/vite": { - "version": "7.3.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.3.tgz", - "integrity": "sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", - "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.1", - "es-module-lexer": "^1.7.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vite/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" - } - }, - "node_modules/vitest": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", - "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/chai": "^5.2.2", - "@vitest/expect": "3.2.4", - "@vitest/mocker": "3.2.4", - "@vitest/pretty-format": "^3.2.4", - "@vitest/runner": "3.2.4", - "@vitest/snapshot": "3.2.4", - "@vitest/spy": "3.2.4", - "@vitest/utils": "3.2.4", - "chai": "^5.2.0", - "debug": "^4.4.1", - "expect-type": "^1.2.1", - "magic-string": "^0.30.17", - "pathe": "^2.0.3", - "picomatch": "^4.0.2", - "std-env": "^3.9.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinyglobby": "^0.2.14", - "tinypool": "^1.1.1", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", - "vite-node": "3.2.4", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.2.4", - "@vitest/ui": "3.2.4", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/debug": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - } - } -} diff --git a/extensions/entity-files/packages/simple-file-server/package.json b/extensions/entity-files/packages/simple-file-server/package.json deleted file mode 100644 index 19520154..00000000 --- a/extensions/entity-files/packages/simple-file-server/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "@dynamia-tools/simple-file-server", - "version": "26.5.1", - "description": "Standalone filesystem-native file server with a minimal S3-style API for secure server-to-server file operations", - "keywords": [ - "dynamia", - "entity-files", - "file-server", - "storage", - "s3-like", - "streaming" - ], - "homepage": "https://dynamia.tools", - "bugs": { - "url": "https://github.com/dynamiatools/framework/issues" - }, - "repository": { - "type": "git", - "url": "https://github.com/dynamiatools/framework.git", - "directory": "extensions/entity-files/packages/simple-file-server" - }, - "license": "Apache-2.0", - "author": "Dynamia Soluciones IT SAS", - "type": "module", - "bin": { - "sfs": "./dist/cli/index.js", - "sfs-test": "./dist/cli/index.js" - }, - "main": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - } - } - }, - "files": [ - "dist", - "README.md", - "LICENSE" - ], - "scripts": { - "build": "tsc -p tsconfig.build.json", - "rebuild": "tsc -p tsconfig.build.json && echo '✅ sfs-test actualizado'", - "dev": "tsx watch src/cli/index.ts serve", - "start": "node dist/cli/index.js serve", - "test": "vitest run", - "test:watch": "vitest", - "typecheck": "tsc --noEmit", - "clean": "rm -rf dist" - }, - "dependencies": { - "@fastify/sensible": "^6.0.4", - "argon2": "^0.43.0", - "commander": "^13.1.0", - "fastify": "^5.3.0", - "fastify-plugin": "^5.1.0", - "file-type": "^20.0.0", - "pino": "^9.7.0", - "pino-pretty": "^13.0.0", - "sharp": "^0.34.1", - "zod": "^3.24.0" - }, - "devDependencies": { - "@types/node": "^22.0.0", - "@types/sharp": "^0.31.0", - "tsx": "^4.19.0", - "typescript": "^5.7.0", - "vitest": "^3.0.0" - }, - "engines": { - "node": ">=18.17.0" - } -} diff --git a/extensions/entity-files/packages/simple-file-server/simple-file-server-full-plan.md b/extensions/entity-files/packages/simple-file-server/simple-file-server-full-plan.md deleted file mode 100644 index 52a73528..00000000 --- a/extensions/entity-files/packages/simple-file-server/simple-file-server-full-plan.md +++ /dev/null @@ -1,842 +0,0 @@ -# simple-file-server (SFS) - -`simple-file-server` (SFS) is a standalone filesystem-native file server with a minimal S3-style API designed for secure server-to-server file operations. - -The system is intentionally simple: - -- Private by default -- No anonymous access -- No public buckets -- No JWT -- No object metadata database -- No distributed storage features -- No S3 compatibility goals beyond basic object semantics - -SFS is designed as the backend for `RemoteSimpleEntityFileStorage` in EntityFiles and optimized for: - -- ERP systems -- Multi-tenant applications -- Internal services -- Hybrid infrastructure -- Large file streaming -- Low operational complexity - ---- - -# Core Principles - -1. Filesystem-native storage -2. All access requires authentication -3. Streaming-first architecture -4. No persistent object metadata -5. Predictable and portable deployment -6. Minimal operational complexity -7. Standalone runtime and CLI -8. JSON-only operational API - ---- - -# Main Goals - -Implement a standalone service that supports: - -- Upload -- Download -- Listing -- Deletion -- Thumbnail generation -- Permission-based access control -- Persistent operational logging - -using a simple JSON API and direct filesystem storage. - ---- - -# Security Model - -SFS is strictly private. - -Every request requires authentication using: - -- `identity` -- `secret` - -Without valid credentials: -- no access -- no listing -- no downloads -- no uploads -- no metadata access - -The server is intended exclusively for trusted backend/server-to-server communication. - ---- - -# Authentication - -Authentication uses: - -- HTTP Basic Auth -or -- custom headers - -Example: - -```http -X-SFS-Identity: erp-prod -X-SFS-Secret: xxxxxxxxx -``` - -Secrets are never stored in plain text. - -Requirements: - -- Argon2id password hashing -- Timing-safe secret comparison -- Identity-based permission resolution - ---- - -# Authorization Model - -Each identity may have access to one or more buckets. - -Permissions are granted per bucket and restricted by path prefixes. - -Supported permissions: - -- `read` -- `write` -- `delete` - -Example grant: - -```json -{ - "bucket": "documents", - "prefixes": [ - "/tenant-a/", - "/tenant-a/public/" - ], - "permissions": ["read", "write"] -} -``` - -Rules: - -- Access outside allowed prefixes is denied -- Prefix validation is mandatory for every operation -- Authorization is evaluated after path normalization - ---- - -# Bucket Model - -A bucket is a logical alias mapped to an absolute filesystem path. - -Example: - -```bash -sfs create bucket documents /mnt/storage/documents -``` - -Internal example: - -```text -documents -> /mnt/storage/documents -``` - -Buckets may point to any valid filesystem location. - -Requirements: - -- Absolute paths only -- Canonical path normalization -- Path traversal protection -- Writable validation during startup - ---- - -# Local Configuration Persistence - -All runtime configuration and metadata are stored in the server working directory. - -Default structure: - -```text -./sfs/ - ├── config/ - ├── identities/ - ├── buckets/ - ├── logs/ - ├── runtime/ - └── cache/ -``` - -Requirements: - -- Self-contained deployment -- Portable runtime -- No external database -- No external configuration dependency by default - -Persisted data includes: - -- identities -- grants -- bucket definitions -- runtime metadata -- operational logs - -Object/file metadata is never persisted. - ---- - -# Filesystem Layout - -Each bucket internally contains a reserved `.sfs` directory. - -Example: - -```text -/mnt/storage/documents/ - └── .sfs/ - ├── staging/ - ├── thumbs/ - └── runtime/ -``` - -Purpose: - -- staging uploads -- thumbnail cache -- temporary runtime artifacts - -Rules: - -- `.sfs` is internal and inaccessible through the API -- users cannot upload or access `.sfs` paths - ---- - -# API Design - -## Object Download - -```http -GET /:bucket/*key -``` - -Behavior: - -- Streams file directly -- Supports large files -- Requires `read` permission - -Responses: - -- file stream -- JSON error on failure - ---- - -## Folder Listing - -```http -GET /:bucket/*key-folder/ -``` - -Behavior: - -- Lists directory contents -- Returns JSON response -- Requires `read` permission - -If target: -- does not exist → `404` -- is not a directory → `404` - ---- - -## Bucket Listing - -```http -GET /:bucket -``` - -Returns: - -- paginated object listing -- JSON response only - -Supported query parameters: - -```http -?limit=100 -&cursor=... -``` - -Purpose: - -- prevent excessive memory usage -- support large directories - ---- - -## File Upload - -```http -PUT /:bucket/*key -``` - -Requirements: - -- streaming upload -- overwrite support -- mandatory staging -- requires `write` permission - -Upload flow: - -1. Stream upload into bucket-local staging directory -2. Validate successful write completion -3. fsync temporary file -4. Atomically move file into final destination when possible -5. Cleanup staging artifact - -Rules: - -- Never write directly into final destination -- Upload must not leave partial target files -- Upload failures must be logged -- Existing files may be overwritten by default - -Optional future header: - -```http -If-Not-Exists: true -``` - ---- - -## File Delete - -```http -DELETE /:bucket/*key -``` - -Behavior: - -- Deletes exact file only -- Non-recursive -- Requires `delete` permission - -Rules: - -- Directories cannot be recursively removed -- Missing targets return JSON error - ---- - -# Path Safety - -Path traversal protection is mandatory. - -The server must: - -- normalize paths -- resolve canonical paths -- validate bucket boundaries - -Invalid examples: - -```text -../../../etc/passwd -..%2F..%2F -``` - -After resolution: - -- final path must remain inside bucket root -- otherwise request is denied - ---- - -# Streaming Requirements - -All file operations must support streaming. - -Requirements: - -- constant memory usage -- support for large files -- no full-file buffering - -Applies to: - -- uploads -- downloads -- thumbnail generation - ---- - -# Thumbnail System - -Thumbnail generation is lazy and cache-based. - -Supported request: - -```http -GET /bucket/image.jpg?w=300&h=300 -``` - -Behavior: - -1. Detect image file -2. Generate thumbnail on first request -3. Persist thumbnail into local cache -4. Reuse cached thumbnail on subsequent requests - -Requirements: - -- generation only on demand -- cached thumbnails stored in `.sfs/thumbs` -- thumbnail cache keys based on: - - original file - - width - - height - - resize mode - - output format - ---- - -# MIME Detection - -MIME type detection must not rely exclusively on file extension. - -Preferred detection: - -- magic bytes -- content sniffing - -Purpose: - -- correct content type responses -- safer file handling - ---- - -# Logging - -SFS persists operational logs only. - -No persistent object catalog exists. - -Recommended format: - -- JSON Lines (`.jsonl`) - -Supported events: - -- `upload_started` -- `upload_staged` -- `upload_committed` -- `upload_failed` -- `download` -- `list` -- `delete` -- `auth_failed` -- `permission_denied` - -Example: - -```json -{ - "ts": "2026-05-16T12:00:00Z", - "event": "upload_committed", - "identity": "erp-prod", - "bucket": "documents", - "key": "tenant-a/invoice.pdf", - "size": 204812, - "elapsedMs": 42 -} -``` - -Recommended files: - -```text -logs/access.log.jsonl -logs/error.log.jsonl -``` - ---- - -# JSON Response Format - -## Success - -```json -{ - "ok": true, - "data": {} -} -``` - -## Error - -```json -{ - "ok": false, - "error": { - "code": "SFS_ERROR_CODE", - "message": "Human readable message", - "details": {} - } -} -``` - ---- - -# CLI (`sfs`) - -The server includes a standalone CLI. - -All CLI output must use JSON. - ---- - -# Bucket Commands - -Create bucket: - -```bash -sfs create bucket -``` - -List buckets: - -```bash -sfs list buckets -``` - -Remove bucket (optional policy): - -```bash -sfs remove bucket -``` - ---- - -# Identity Commands - -Create identity: - -```bash -sfs create identity -``` - -Grant permissions: - -```bash -sfs grant \ - --read \ - --write \ - --delete \ - --prefix -``` - -List identities: - -```bash -sfs list identities -``` - -Revoke permissions: - -```bash -sfs revoke -``` - ---- - -# Runtime Commands - -Start server: - -```bash -sfs serve --host 0.0.0.0 --port 8080 -``` - -Optional future flags: - -```bash ---data-dir ---config-dir ---log-level -``` - ---- - -# Startup Validation - -During startup the server validates: - -- bucket existence -- writable staging directories -- writable cache directories -- configuration integrity -- orphan staging cleanup - -Old temporary staging files may be cleaned automatically. - ---- - -# Recommended Node.js Technology Stack - -SFS is designed to be implemented as an ultra-fast streaming-first backend optimized for filesystem IO and server-to-server communication. - -## Runtime - -- Node.js 22+ -- TypeScript (strict mode) -- ESM modules - -## HTTP Framework - -Recommended framework: - -- Fastify - -Reasons: - -- Very high throughput -- Low overhead -- Excellent streaming support -- Native schema integration -- Lightweight plugin system -- Efficient request lifecycle - -## Validation - -Recommended options: - -- TypeBox + AJV (maximum performance) -or -- Zod (better developer experience) - -## Logging - -Recommended logger: - -- Pino - -Reasons: - -- Extremely fast JSON logging -- Native Fastify integration -- Perfect for `.jsonl` operational logs - -## Password Hashing - -Recommended: - -- Argon2id - -Requirements: - -- No plain text secret storage -- Timing-safe comparisons - -## Thumbnail Processing - -Recommended: - -- Sharp - -Reasons: - -- Very fast image processing -- Low memory usage -- Based on libvips -- Efficient thumbnail generation - -## MIME Detection - -Recommended: - -- file-type - -Purpose: - -- Detect MIME types using magic bytes -- Avoid extension-only detection - -## CLI - -Recommended: - -- CAC -or -- Commander.js - -## Development - -Recommended tools: - -- TSX -- Vitest - -## Streaming Requirements - -The implementation must use native streaming APIs: - -- stream.pipeline -- fs.createReadStream -- fs.createWriteStream - -The server must avoid: - -- full-file buffering -- readFile/writeFile for large files -- heavy multipart parsers - -## Upload Strategy - -Uploads should use raw streaming requests. - -Recommended request style: - -```http -PUT /bucket/key -Content-Type: application/octet-stream -``` - -This avoids multipart overhead and improves performance. - -## Recommended Internal Structure - -```text -src/ - ├── app/ - ├── auth/ - ├── bucket/ - ├── cli/ - ├── config/ - ├── errors/ - ├── http/ - ├── logging/ - ├── storage/ - ├── thumbnail/ - ├── utils/ - └── types/ -``` - -## Non-Recommended Frameworks - -SFS intentionally avoids large abstraction-heavy backend frameworks such as: - -- NestJS - -Reason: - -- unnecessary overhead -- excessive abstraction -- lower streaming control -- less predictable IO behavior - -## Final Recommended Stack - -```text -Node.js 24 -TypeScript -Fastify -Pino -Sharp -TypeBox -AJV -Argon2 -Vitest -TSX -``` - ---- - -# Proposed Internal Structure - -```text -src/ - ├── auth/ - ├── cli/ - ├── config/ - ├── http/ - ├── logging/ - ├── storage/ - ├── thumbnail/ - └── runtime/ -``` - ---- - -# Non-Goals - -SFS intentionally does NOT implement: - -- distributed storage -- clustering -- replication -- eventual consistency -- object versioning -- multipart upload -- public URLs -- anonymous access -- JWT authentication -- full S3 compatibility -- metadata indexing database - -The goal is simplicity, predictability, and operational efficiency. - ---- - -# Acceptance Criteria - -1. Buckets map to arbitrary absolute filesystem paths -2. Identities authenticate using `identity + secret` -3. Permissions are bucket and prefix based -4. PUT operations use mandatory staging -5. Uploads and downloads support streaming -6. DELETE removes exact files only -7. Bucket and folder listing return paginated JSON -8. Thumbnail generation is lazy and cached -9. No persistent object metadata exists -10. Operational logs are persisted -11. Everything runs standalone through `sfs` -12. All runtime configuration persists locally in the working directory -13. All access requires authentication -14. Path traversal attacks are prevented - ---- - -# Next Phase: EntityFiles Integration - -Implement: - -```text -RemoteSimpleEntityFileStorage -``` - -Responsibilities: - -- upload -- download -- delete -- list -- thumbnail access - -using SFS endpoints. - -Additional goals: - -- remote thumbnail strategy -- public URL abstraction layer -- transparent storage backend switching -- multi-storage support in EntityFiles diff --git a/extensions/entity-files/packages/simple-file-server/src/auth/identity.service.ts b/extensions/entity-files/packages/simple-file-server/src/auth/identity.service.ts deleted file mode 100644 index b5b0786a..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/auth/identity.service.ts +++ /dev/null @@ -1,131 +0,0 @@ -import path from 'node:path' -import fsp from 'node:fs/promises' -import * as argon2 from 'argon2' -import { resolveDataPaths, readJsonFile, writeJsonFile } from '../config/config.service.js' -import type { Identity, Grant, Permission } from '../types/index.js' -import { SFSError, SFSErrorCode, notFound } from '../errors/index.js' - -function conflict(message: string, code: SFSErrorCode): SFSError { - return new SFSError(code, message, 409) -} - -export class IdentityService { - private identitiesDir: string - - constructor(dataDir: string) { - this.identitiesDir = resolveDataPaths(dataDir).identitiesDir - } - - private identityPath(identity: string): string { - const safe = identity.replace(/[^a-zA-Z0-9_\-\.]/g, '_') - return path.join(this.identitiesDir, `${safe}.json`) - } - - async create(identity: string, secret: string): Promise { - const existing = await this.find(identity) - if (existing) { - throw conflict(`Identity '${identity}' already exists`, SFSErrorCode.IDENTITY_ALREADY_EXISTS) - } - - const hashedSecret = await argon2.hash(secret, { - type: argon2.argon2id, - memoryCost: 65536, - timeCost: 3, - parallelism: 4, - }) - - const now = new Date().toISOString() - const id: Identity = { - identity, - hashedSecret, - grants: [], - createdAt: now, - updatedAt: now, - } - - await writeJsonFile(this.identityPath(identity), id) - return id - } - - async find(identity: string): Promise { - return readJsonFile(this.identityPath(identity)) - } - - async get(identity: string): Promise { - const id = await this.find(identity) - if (!id) { - throw notFound(`Identity '${identity}'`, SFSErrorCode.IDENTITY_NOT_FOUND) - } - return id - } - - async list(): Promise { - try { - const files = await fsp.readdir(this.identitiesDir) - const identities: Identity[] = [] - for (const file of files) { - if (!file.endsWith('.json')) continue - const id = await readJsonFile(path.join(this.identitiesDir, file)) - if (id) identities.push(id) - } - return identities - } catch { - return [] - } - } - - async verify(identity: string, secret: string): Promise { - const id = await this.find(identity) - if (!id) return null - try { - const valid = await argon2.verify(id.hashedSecret, secret) - return valid ? id : null - } catch { - return null - } - } - - async grant(identity: string, grant: Grant): Promise { - const id = await this.get(identity) - id.grants = id.grants.filter(g => g.bucket !== grant.bucket) - id.grants.push(grant) - id.updatedAt = new Date().toISOString() - await writeJsonFile(this.identityPath(identity), id) - return id - } - - async revoke(identity: string, bucket: string): Promise { - const id = await this.get(identity) - id.grants = id.grants.filter(g => g.bucket !== bucket) - id.updatedAt = new Date().toISOString() - await writeJsonFile(this.identityPath(identity), id) - return id - } - - async delete(identity: string): Promise { - const filePath = this.identityPath(identity) - try { - await fsp.unlink(filePath) - } catch { - throw notFound(`Identity '${identity}'`, SFSErrorCode.IDENTITY_NOT_FOUND) - } - } - - checkPermission(id: Identity, bucket: string, key: string, permission: Permission): Grant | null { - for (const grant of id.grants) { - if (grant.bucket !== bucket) continue - if (!grant.permissions.includes(permission)) continue - - if (grant.prefixes.length === 0) return grant - - const normalizedKey = key.startsWith('/') ? key : `/${key}` - for (const prefix of grant.prefixes) { - const normalizedPrefix = prefix.startsWith('/') ? prefix : `/${prefix}` - if (normalizedKey.startsWith(normalizedPrefix) || normalizedPrefix === '/') { - return grant - } - } - } - return null - } -} diff --git a/extensions/entity-files/packages/simple-file-server/src/cli/completion.ts b/extensions/entity-files/packages/simple-file-server/src/cli/completion.ts deleted file mode 100644 index 0a8c6415..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/cli/completion.ts +++ /dev/null @@ -1,375 +0,0 @@ -/** - * Shell tab-completion script generators for SFS CLI. - * - * Usage: - * # Bash — add to ~/.bashrc - * eval "$(sfs completion bash)" - * - * # Zsh — add to ~/.zshrc (compinit must already be loaded) - * eval "$(sfs completion zsh)" - * - * # Fish — save to completions dir - * sfs completion fish > ~/.config/fish/completions/sfs.fish - * - * Dynamic completion: bucket and identity names are resolved at completion - * time by calling `sfs list buckets` / `sfs list identities`, so they always - * reflect the current runtime state. - */ - -export function bashCompletion(): string { - return ` -_sfs_buckets() { - sfs list buckets 2>/dev/null | grep '"name"' | awk -F'"' '{print $4}' -} - -_sfs_identities() { - sfs list identities 2>/dev/null | grep '"identity"' | awk -F'"' '{print $4}' -} - -_sfs_complete() { - local cur prev words cword - _init_completion 2>/dev/null || { - COMPREPLY=() - cur="\${COMP_WORDS[COMP_CWORD]}" - prev="\${COMP_WORDS[COMP_CWORD-1]}" - words=("\${COMP_WORDS[@]}") - cword=\$COMP_CWORD - } - - local top_commands="serve create list remove grant revoke upload copy provision completion" - - # Handle --data-dir path completion - if [[ "\$prev" == "--data-dir" ]]; then - COMPREPLY=( $(compgen -d -- "\$cur") ) - return - fi - - case "\${words[1]}" in - serve) - COMPREPLY=( $(compgen -W "--host --port --data-dir --log-level" -- "\$cur") ) - ;; - create) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "bucket identity" -- "\$cur") ) ;; - esac - ;; - list) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "buckets identities files" -- "\$cur") ) ;; - 3) - if [[ "\${words[2]}" == "files" ]]; then - COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) - fi - ;; - 4) - # path inside bucket — fall back to filesystem - if [[ "\${words[2]}" == "files" ]]; then - COMPREPLY=( $(compgen -f -- "\$cur") ) - fi - ;; - esac - ;; - remove) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "bucket identity" -- "\$cur") ) ;; - 3) - if [[ "\${words[2]}" == "bucket" ]]; then - COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) - elif [[ "\${words[2]}" == "identity" ]]; then - COMPREPLY=( $(compgen -W "$(_sfs_identities)" -- "\$cur") ) - fi - ;; - esac - ;; - grant) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "$(_sfs_identities)" -- "\$cur") ) ;; - 3) COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) ;; - *) COMPREPLY=( $(compgen -W "--read --write --delete --prefix --data-dir" -- "\$cur") ) ;; - esac - ;; - revoke) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "$(_sfs_identities)" -- "\$cur") ) ;; - 3) COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) ;; - esac - ;; - upload) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) ;; - 4) COMPREPLY=( $(compgen -f -- "\$cur") ) ;; # local file - *) COMPREPLY=( $(compgen -W "--overwrite --data-dir" -- "\$cur") ) ;; - esac - ;; - copy) - case "\$cword" in - 2|4) COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) ;; - *) COMPREPLY=( $(compgen -W "--overwrite --data-dir" -- "\$cur") ) ;; - esac - ;; - provision) - case "\$cword" in - 2) COMPREPLY=( $(compgen -W "$(_sfs_buckets)" -- "\$cur") ) ;; - *) COMPREPLY=( $(compgen -W "--identity --prefix --read --write --delete --data-dir" -- "\$cur") ) ;; - esac - ;; - completion) - COMPREPLY=( $(compgen -W "bash zsh fish" -- "\$cur") ) - ;; - *) - COMPREPLY=( $(compgen -W "\$top_commands" -- "\$cur") ) - ;; - esac -} - -complete -F _sfs_complete sfs -complete -F _sfs_complete sfs-test -`.trim() -} - -export function zshCompletion(): string { - return ` -#compdef sfs sfs-test - -_sfs_buckets() { - local -a buckets - buckets=( \${(f)"$(sfs list buckets 2>/dev/null | grep '"name"' | awk -F'"' '{print $4}')"} ) - echo "\${buckets[@]}" -} - -_sfs_identities() { - local -a ids - ids=( \${(f)"$(sfs list identities 2>/dev/null | grep '"identity"' | awk -F'"' '{print $4}')"} ) - echo "\${ids[@]}" -} - -_sfs() { - local state line - typeset -A opt_args - - _arguments -C \\ - '1: :->command' \\ - '*:: :->args' - - case \$state in - command) - local commands - commands=( - 'serve:Start the SFS HTTP server' - 'create:Create a bucket or identity' - 'list:List buckets, identities or files' - 'remove:Remove a bucket or identity' - 'grant:Grant permissions to an identity on a bucket' - 'revoke:Revoke permissions from an identity on a bucket' - 'upload:Upload a local file to a bucket' - 'copy:Copy a file between buckets' - 'provision:Auto-generate identity + secret and grant access to a bucket' - 'completion:Print shell completion script' - ) - _describe 'command' commands - ;; - args) - case \$line[1] in - serve) - _arguments \\ - '--host[Host to listen on]:host' \\ - '--port[Port to listen on]:port' \\ - '--data-dir[Data directory]:dir:_files -/' \\ - '--log-level[Log level]:level:(trace debug info warn error)' - ;; - create) - case \$line[2] in - bucket) - _arguments \\ - '2:bucket name' \\ - '3:absolute path:_files -/' - ;; - identity) - _arguments \\ - '2:identity name' \\ - '3:secret' - ;; - *) - local subcmds; subcmds=('bucket:Create a bucket' 'identity:Create an identity') - _describe 'subcommand' subcmds - ;; - esac - ;; - list) - case \$line[2] in - files) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments \\ - '2:bucket:(\${buckets[@]})' \\ - '3:path:_files' - ;; - *) - local subcmds; subcmds=('buckets:List all buckets' 'identities:List all identities' 'files:List files in a bucket') - _describe 'subcommand' subcmds - ;; - esac - ;; - remove) - case \$line[2] in - bucket) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments '3:bucket name:(\${buckets[@]})' - ;; - identity) - local ids; ids=( \$(_sfs_identities) ) - _arguments '3:identity:(\${ids[@]})' - ;; - *) - local subcmds; subcmds=('bucket:Remove a bucket' 'identity:Remove an identity') - _describe 'subcommand' subcmds - ;; - esac - ;; - grant) - local ids; ids=( \$(_sfs_identities) ) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments \\ - '2:identity:(\${ids[@]})' \\ - '3:bucket:(\${buckets[@]})' \\ - '--read[Grant read]' \\ - '--write[Grant write]' \\ - '--delete[Grant delete]' \\ - '--prefix[Path prefix]:prefix' \\ - '--data-dir[Data directory]:dir:_files -/' - ;; - revoke) - local ids; ids=( \$(_sfs_identities) ) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments \\ - '2:identity:(\${ids[@]})' \\ - '3:bucket:(\${buckets[@]})' \\ - '--data-dir[Data directory]:dir:_files -/' - ;; - upload) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments \\ - '2:bucket:(\${buckets[@]})' \\ - '3:key' \\ - '4:local file:_files' \\ - '--overwrite[Overwrite existing file]' \\ - '--data-dir[Data directory]:dir:_files -/' - ;; - copy) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments \\ - '2:source bucket:(\${buckets[@]})' \\ - '3:source key' \\ - '4:destination bucket:(\${buckets[@]})' \\ - '5:destination key' \\ - '--overwrite[Overwrite existing file]' \\ - '--data-dir[Data directory]:dir:_files -/' - ;; - provision) - local buckets; buckets=( \$(_sfs_buckets) ) - _arguments \\ - '2:bucket:(\${buckets[@]})' \\ - '--identity[Identity name]:name' \\ - '--prefix[Path prefix]:prefix' \\ - '--read[Grant read]' \\ - '--write[Grant write]' \\ - '--delete[Grant delete]' \\ - '--data-dir[Data directory]:dir:_files -/' - ;; - completion) - _arguments '2:shell:(bash zsh fish)' - ;; - esac - ;; - esac -} - -_sfs -`.trim() -} - -export function fishCompletion(): string { - return ` -# Fish completion for sfs / sfs-test -# Install: sfs completion fish > ~/.config/fish/completions/sfs.fish - -function __sfs_buckets - sfs list buckets 2>/dev/null | string match -r '"name": "([^"]+)"' | string replace -r '.*"name": "([^"]+)".*' '$1' -end - -function __sfs_identities - sfs list identities 2>/dev/null | string match -r '"identity": "([^"]+)"' | string replace -r '.*"identity": "([^"]+)".*' '$1' -end - -function __sfs_using_command - set cmd (commandline -opc) - if test (count $cmd) -eq 1 - return 0 - end - return 1 -end - -function __sfs_using_subcommand - set cmd (commandline -opc) - if test (count $cmd) -ge 2; and test $cmd[2] = $argv[1] - return 0 - end - return 1 -end - -# Top-level commands -complete -c sfs -f -n '__sfs_using_command' -a serve -d 'Start the SFS HTTP server' -complete -c sfs -f -n '__sfs_using_command' -a create -d 'Create a bucket or identity' -complete -c sfs -f -n '__sfs_using_command' -a list -d 'List resources' -complete -c sfs -f -n '__sfs_using_command' -a remove -d 'Remove a resource' -complete -c sfs -f -n '__sfs_using_command' -a grant -d 'Grant permissions' -complete -c sfs -f -n '__sfs_using_command' -a revoke -d 'Revoke permissions' -complete -c sfs -f -n '__sfs_using_command' -a upload -d 'Upload a local file' -complete -c sfs -f -n '__sfs_using_command' -a copy -d 'Copy a file between buckets' -complete -c sfs -f -n '__sfs_using_command' -a provision -d 'Auto-generate identity and grant access' -complete -c sfs -f -n '__sfs_using_command' -a completion -d 'Print shell completion script' - -# serve options -complete -c sfs -f -n '__sfs_using_subcommand serve' -l host -d 'Host to listen on' -complete -c sfs -f -n '__sfs_using_subcommand serve' -l port -d 'Port to listen on' -complete -c sfs -f -n '__sfs_using_subcommand serve' -l data-dir -d 'Data directory' -complete -c sfs -f -n '__sfs_using_subcommand serve' -l log-level -a 'trace debug info warn error' -d 'Log level' - -# create subcommands -complete -c sfs -f -n '__sfs_using_subcommand create' -a bucket -d 'Create a bucket' -complete -c sfs -f -n '__sfs_using_subcommand create' -a identity -d 'Create an identity' - -# list subcommands -complete -c sfs -f -n '__sfs_using_subcommand list' -a buckets -d 'List all buckets' -complete -c sfs -f -n '__sfs_using_subcommand list' -a identities -d 'List all identities' -complete -c sfs -f -n '__sfs_using_subcommand list' -a files -d 'List files in a bucket' - -# remove subcommands -complete -c sfs -f -n '__sfs_using_subcommand remove' -a bucket -d 'Remove a bucket' -complete -c sfs -f -n '__sfs_using_subcommand remove' -a identity -d 'Remove an identity' - -# grant / revoke options -complete -c sfs -f -n '__sfs_using_subcommand grant' -l read -d 'Grant read' -complete -c sfs -f -n '__sfs_using_subcommand grant' -l write -d 'Grant write' -complete -c sfs -f -n '__sfs_using_subcommand grant' -l delete -d 'Grant delete' -complete -c sfs -f -n '__sfs_using_subcommand grant' -l prefix -d 'Path prefix' - -# provision options -complete -c sfs -f -n '__sfs_using_subcommand provision' -l identity -d 'Identity name' -complete -c sfs -f -n '__sfs_using_subcommand provision' -l prefix -d 'Path prefix' -complete -c sfs -f -n '__sfs_using_subcommand provision' -l read -d 'Grant read' -complete -c sfs -f -n '__sfs_using_subcommand provision' -l write -d 'Grant write' -complete -c sfs -f -n '__sfs_using_subcommand provision' -l delete -d 'Grant delete' - -# completion shells -complete -c sfs -f -n '__sfs_using_subcommand completion' -a 'bash zsh fish' - -# Dynamic bucket completions -complete -c sfs -f -n '__sfs_using_subcommand provision' -a '(__sfs_buckets)' -complete -c sfs -f -n '__sfs_using_subcommand upload' -a '(__sfs_buckets)' -complete -c sfs -f -n '__sfs_using_subcommand copy' -a '(__sfs_buckets)' - -# Also apply to sfs-test alias -complete -c sfs-test --wraps sfs -`.trim() -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/cli/index.ts b/extensions/entity-files/packages/simple-file-server/src/cli/index.ts deleted file mode 100644 index 88308cf9..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/cli/index.ts +++ /dev/null @@ -1,437 +0,0 @@ -#!/usr/bin/env node - -import { Command } from 'commander' -import { createReadStream } from 'node:fs' -import { stat } from 'node:fs/promises' -import { randomBytes } from 'node:crypto' -import os from 'node:os' -import { createRuntime, startServer } from '../runtime/index.js' -import { getDataDir } from '../config/config.service.js' -import { bashCompletion, zshCompletion, fishCompletion } from './completion.js' -import type { Permission, Bucket, Identity } from '../types/index.js' - -const program = new Command() - -program - .name('sfs') - .description('Simple File Server - filesystem-native file server with S3-style API') - .version('26.5.1') - -// ────────────────────────────────────────────────────────── -// sfs serve -// ────────────────────────────────────────────────────────── -program - .command('serve') - .description('Start the SFS server') - .option('--host ', 'Host to listen on', process.env.SFS_HOST ?? '0.0.0.0') - .option('--port ', 'Port to listen on', process.env.SFS_PORT ?? '8080') - .option('--data-dir ', 'Data directory', getDataDir()) - .option('--log-level ', 'Log level (trace|debug|info|warn|error)', 'info') - .action(async (opts) => { - printEnvInfo() - const runtime = await startServer({ - host: opts.host, - port: parseInt(opts.port, 10), - dataDir: opts.dataDir, - logLevel: opts.logLevel, - }) - await printServerSummary(runtime) - }) - -// ────────────────────────────────────────────────────────── -// sfs create -// ────────────────────────────────────────────────────────── -const create = program.command('create').description('Create resources') - -create - .command('bucket ') - .description('Create a new bucket mapped to an absolute filesystem path') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (name: string, absolutePath: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const bucket = await runtime.bucketService.create(name, absolutePath) - console.log(JSON.stringify({ ok: true, data: bucket }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -create - .command('identity ') - .description('Create a new identity with the given secret') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (identity: string, secret: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const id = await runtime.identityService.create(identity, secret) - const safeId = { ...id, hashedSecret: '[REDACTED]' } - console.log(JSON.stringify({ ok: true, data: safeId }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs list -// ────────────────────────────────────────────────────────── -const list = program.command('list').description('List resources') - -list - .command('buckets') - .description('List all buckets') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const buckets = await runtime.bucketService.list() - console.log(JSON.stringify({ ok: true, data: buckets }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -list - .command('identities') - .description('List all identities') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const ids = await runtime.identityService.list() - const safeIds = ids.map(id => ({ ...id, hashedSecret: '[REDACTED]' })) - console.log(JSON.stringify({ ok: true, data: safeIds }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -list - .command('files [path]') - .description('List files in a bucket or directory path') - .option('--data-dir ', 'Data directory', getDataDir()) - .option('--limit ', 'Max entries to return (bucket root only)', '100') - .option('--cursor ', 'Pagination cursor (bucket root only)') - .action(async (bucketName: string, keyPath: string | undefined, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const bucket = await runtime.bucketService.get(bucketName) - let result - if (keyPath) { - result = await runtime.storageService.listDirectory(bucket, keyPath) - } else { - result = await runtime.storageService.listBucket(bucket, parseInt(opts.limit, 10), opts.cursor) - } - console.log(JSON.stringify({ ok: true, data: result }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs remove -// ────────────────────────────────────────────────────────── -const remove = program.command('remove').description('Remove resources') - -remove - .command('bucket ') - .description('Remove a bucket definition (does not delete files)') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (name: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - await runtime.bucketService.delete(name) - console.log(JSON.stringify({ ok: true, data: { removed: name } }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -remove - .command('identity ') - .description('Remove an identity') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (identity: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - await runtime.identityService.delete(identity) - console.log(JSON.stringify({ ok: true, data: { removed: identity } }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs grant -// ────────────────────────────────────────────────────────── -program - .command('grant ') - .description('Grant permissions to an identity on a bucket') - .option('--read', 'Grant read permission') - .option('--write', 'Grant write permission') - .option('--delete', 'Grant delete permission') - .option('--prefix ', 'Restrict to path prefix (can be used multiple times)', collect, [] as string[]) - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (identity: string, bucket: string, opts) => { - const permissions: Permission[] = [] - if (opts.read) permissions.push('read') - if (opts.write) permissions.push('write') - if (opts.delete) permissions.push('delete') - - if (permissions.length === 0) { - console.error(JSON.stringify({ ok: false, error: { code: 'SFS_INVALID_ARGS', message: 'At least one permission (--read, --write, --delete) must be specified' } })) - process.exit(1) - } - - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const id = await runtime.identityService.grant(identity, { - bucket, - prefixes: opts.prefix as string[], - permissions, - }) - const safeId = { ...id, hashedSecret: '[REDACTED]' } - console.log(JSON.stringify({ ok: true, data: safeId }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs revoke -// ────────────────────────────────────────────────────────── -program - .command('revoke ') - .description('Revoke all permissions from an identity on a bucket') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (identity: string, bucket: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const id = await runtime.identityService.revoke(identity, bucket) - const safeId = { ...id, hashedSecret: '[REDACTED]' } - console.log(JSON.stringify({ ok: true, data: safeId }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs upload -// ────────────────────────────────────────────────────────── -program - .command('upload ') - .description('Upload a local file to a bucket') - .option('--data-dir ', 'Data directory', getDataDir()) - .option('--overwrite', 'Overwrite existing file', false) - .action(async (bucketName: string, key: string, localFile: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - await stat(localFile) - const bucket = await runtime.bucketService.get(bucketName) - const stream = createReadStream(localFile) - const result = await runtime.storageService.upload(bucket, key, stream, { overwrite: opts.overwrite }) - console.log(JSON.stringify({ ok: true, data: { bucket: bucketName, key, ...result } }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs copy -// ────────────────────────────────────────────────────────── -program - .command('copy ') - .description('Copy a file from one bucket/key to another') - .option('--data-dir ', 'Data directory', getDataDir()) - .option('--overwrite', 'Overwrite existing file', false) - .action(async (srcBucketName: string, srcKey: string, dstBucketName: string, dstKey: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - const srcBucket = await runtime.bucketService.get(srcBucketName) - const dstBucket = await runtime.bucketService.get(dstBucketName) - const { stream } = await runtime.storageService.download(srcBucket, srcKey) - const result = await runtime.storageService.upload(dstBucket, dstKey, stream, { overwrite: opts.overwrite }) - console.log(JSON.stringify({ ok: true, data: { from: `${srcBucketName}/${srcKey}`, to: `${dstBucketName}/${dstKey}`, ...result } }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs provision -// ────────────────────────────────────────────────────────── -program - .command('provision ') - .description('Auto-generate an identity + secret, grant permissions on a bucket, and print the credentials') - .option('--identity ', 'Identity name (auto-generated if omitted)') - .option('--prefix ', 'Restrict access to a path prefix (can be repeated)', collect, [] as string[]) - .option('--read', 'Grant read permission (default: all permissions)') - .option('--write', 'Grant write permission (default: all permissions)') - .option('--delete', 'Grant delete permission (default: all permissions)') - .option('--data-dir ', 'Data directory', getDataDir()) - .action(async (bucketName: string, opts) => { - const runtime = await createRuntime({ dataDir: opts.dataDir }) - try { - // Resolve identity name - const identity: string = opts.identity ?? `sfs-${randomBytes(4).toString('hex')}` - // Generate a secure random secret (32 hex chars) - const secret: string = randomBytes(24).toString('base64url') - - // Determine permissions (default to all three if none specified) - const permissions: Permission[] = [] - if (opts.read) permissions.push('read') - if (opts.write) permissions.push('write') - if (opts.delete) permissions.push('delete') - if (permissions.length === 0) permissions.push('read', 'write', 'delete') - - // Ensure bucket exists - await runtime.bucketService.get(bucketName) - - // Create identity and grant - await runtime.identityService.create(identity, secret) - await runtime.identityService.grant(identity, { - bucket: bucketName, - prefixes: opts.prefix as string[], - permissions, - }) - - console.log(JSON.stringify({ - ok: true, - data: { - identity, - secret, - bucket: bucketName, - permissions, - prefixes: opts.prefix as string[], - note: 'Save the secret now — it will not be shown again.', - }, - }, null, 2)) - } catch (err: unknown) { - printError(err) - } finally { - await runtime.operationalLogger.close() - } - }) - -// ────────────────────────────────────────────────────────── -// sfs completion -// ────────────────────────────────────────────────────────── -program - .command('completion ') - .description('Print shell tab-completion script (bash | zsh | fish)') - .addHelpText('after', ` -Examples: - # Bash — add to ~/.bashrc - eval "$(sfs completion bash)" - - # Zsh — add to ~/.zshrc (compinit must already be loaded) - eval "$(sfs completion zsh)" - - # Fish — save to completions dir - sfs completion fish > ~/.config/fish/completions/sfs.fish -`) - .action((shell: string) => { - switch (shell.toLowerCase()) { - case 'bash': - console.log(bashCompletion()) - break - case 'zsh': - console.log(zshCompletion()) - break - case 'fish': - console.log(fishCompletion()) - break - default: - console.error(JSON.stringify({ ok: false, error: { code: 'SFS_INVALID_ARGS', message: `Unsupported shell '${shell}'. Use: bash | zsh | fish` } })) - process.exit(1) - } - }) - -// ────────────────────────────────────────────────────────── -// Helpers -// ────────────────────────────────────────────────────────── -async function printServerSummary(runtime: Awaited>): Promise { - try { - const [buckets, identities] = await Promise.all([ - runtime.bucketService.list() as Promise, - runtime.identityService.list() as Promise, - ]) - - const bucketLines = buckets.length - ? buckets.map(b => `│ · ${b.name} → ${b.path}`) - : ['│ (none)'] - - const identityLines = identities.length - ? identities.map(id => `│ · ${id.identity} (grants: ${id.grants.map(g => g.bucket).join(', ') || 'none'})`) - : ['│ (none)'] - - const lines = [ - '┌─────────────────────────────────────────────', - '│ Buckets', - '├─────────────────────────────────────────────', - ...bucketLines, - '├─────────────────────────────────────────────', - '│ Identities', - '├─────────────────────────────────────────────', - ...identityLines, - '└─────────────────────────────────────────────', - ] - console.log(lines.join('\n')) - } catch { - // Non-fatal — server is already running - } -} -function printEnvInfo(): void { - const cpus = os.cpus() - const lines = [ - - 'Simple File Server — Environment', - '─────────────────────────────────────────────', - ` OS : ${os.type()} ${os.release()} (${os.platform()}/${os.arch()})`, - ` Node.js : ${process.version}`, - ` V8 : ${process.versions.v8}`, - ` CPUs : ${cpus.length}x ${cpus[0]?.model ?? 'unknown'}`, - ` Memory : ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(1)} GB total`, - ` Hostname : ${os.hostname()}`, - ` User : ${os.userInfo().username}`, - ` PID : ${process.pid}` - ] - console.log(lines.join('\n')) -} -function collect(value: string, previous: string[]): string[] { - return previous.concat([value]) -} - -function printError(err: unknown): void { - if (err && typeof err === 'object' && 'toJSON' in err && typeof (err as { toJSON: unknown }).toJSON === 'function') { - console.error(JSON.stringify((err as { toJSON: () => unknown }).toJSON(), null, 2)) - } else { - console.error(JSON.stringify({ ok: false, error: { code: 'SFS_ERROR', message: String(err) } }, null, 2)) - } - process.exit(1) -} - -program.parse(process.argv) - diff --git a/extensions/entity-files/packages/simple-file-server/src/config/config.service.ts b/extensions/entity-files/packages/simple-file-server/src/config/config.service.ts deleted file mode 100644 index 999f8941..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/config/config.service.ts +++ /dev/null @@ -1,77 +0,0 @@ -import path from 'node:path' -import fs from 'node:fs' -import fsp from 'node:fs/promises' -import type { SFSConfig } from '../types/index.js' - -// Default data directory relative to CWD -const DEFAULT_DATA_DIR = path.join(process.cwd(), '.sfs') - -export function getDataDir(): string { - return process.env.SFS_DATA_DIR ?? DEFAULT_DATA_DIR -} - -export function getDefaultConfig(): SFSConfig { - return { - dataDir: getDataDir(), - host: process.env.SFS_HOST ?? '0.0.0.0', - port: parseInt(process.env.SFS_PORT ?? '8080', 10), - logLevel: process.env.SFS_LOG_LEVEL ?? 'info', - } -} - -export function resolveDataPaths(dataDir: string) { - return { - dataDir, - configDir: path.join(dataDir, 'config'), - identitiesDir: path.join(dataDir, 'identities'), - bucketsDir: path.join(dataDir, 'buckets'), - logsDir: path.join(dataDir, 'logs'), - runtimeDir: path.join(dataDir, 'runtime'), - cacheDir: path.join(dataDir, 'cache'), - } -} - -export async function ensureDataDirs(dataDir: string): Promise { - const paths = resolveDataPaths(dataDir) - for (const dir of Object.values(paths)) { - await fsp.mkdir(dir, { recursive: true }) - } -} - -export function ensureDataDirsSync(dataDir: string): void { - const paths = resolveDataPaths(dataDir) - for (const dir of Object.values(paths)) { - fs.mkdirSync(dir, { recursive: true }) - } -} - -export async function readJsonFile(filePath: string): Promise { - try { - const content = await fsp.readFile(filePath, 'utf-8') - return JSON.parse(content) as T - } catch { - return null - } -} - -export async function writeJsonFile(filePath: string, data: T): Promise { - const dir = path.dirname(filePath) - await fsp.mkdir(dir, { recursive: true }) - await fsp.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8') -} - -export function readJsonFileSync(filePath: string): T | null { - try { - const content = fs.readFileSync(filePath, 'utf-8') - return JSON.parse(content) as T - } catch { - return null - } -} - -export function writeJsonFileSync(filePath: string, data: T): void { - const dir = path.dirname(filePath) - fs.mkdirSync(dir, { recursive: true }) - fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8') -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/errors/index.ts b/extensions/entity-files/packages/simple-file-server/src/errors/index.ts deleted file mode 100644 index a21d7772..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/errors/index.ts +++ /dev/null @@ -1,93 +0,0 @@ -// SFS Error codes and helpers - -export enum SFSErrorCode { - // Auth - AUTH_REQUIRED = 'SFS_AUTH_REQUIRED', - AUTH_INVALID = 'SFS_AUTH_INVALID', - PERMISSION_DENIED = 'SFS_PERMISSION_DENIED', - - // Objects - OBJECT_NOT_FOUND = 'SFS_OBJECT_NOT_FOUND', - OBJECT_IS_DIRECTORY = 'SFS_OBJECT_IS_DIRECTORY', - PATH_TRAVERSAL = 'SFS_PATH_TRAVERSAL', - PATH_INVALID = 'SFS_PATH_INVALID', - PATH_RESERVED = 'SFS_PATH_RESERVED', - - // Buckets - BUCKET_NOT_FOUND = 'SFS_BUCKET_NOT_FOUND', - BUCKET_ALREADY_EXISTS = 'SFS_BUCKET_ALREADY_EXISTS', - BUCKET_PATH_INVALID = 'SFS_BUCKET_PATH_INVALID', - BUCKET_PATH_NOT_WRITABLE = 'SFS_BUCKET_PATH_NOT_WRITABLE', - - // Identities - IDENTITY_NOT_FOUND = 'SFS_IDENTITY_NOT_FOUND', - IDENTITY_ALREADY_EXISTS = 'SFS_IDENTITY_ALREADY_EXISTS', - - // Uploads - UPLOAD_FAILED = 'SFS_UPLOAD_FAILED', - UPLOAD_STAGING_FAILED = 'SFS_UPLOAD_STAGING_FAILED', - - // General - INTERNAL_ERROR = 'SFS_INTERNAL_ERROR', - NOT_IMPLEMENTED = 'SFS_NOT_IMPLEMENTED', -} - -export interface SFSErrorDetails { - code: SFSErrorCode - message: string - details?: Record -} - -export class SFSError extends Error { - public readonly code: SFSErrorCode - public readonly statusCode: number - public readonly details?: Record - - constructor(code: SFSErrorCode, message: string, statusCode: number = 500, details?: Record) { - super(message) - this.name = 'SFSError' - this.code = code - this.statusCode = statusCode - this.details = details - } - - toJSON(): { ok: false; error: SFSErrorDetails } { - return { - ok: false, - error: { - code: this.code, - message: this.message, - details: this.details, - }, - } - } -} - -export function notFound(resource: string, code: SFSErrorCode = SFSErrorCode.OBJECT_NOT_FOUND): SFSError { - return new SFSError(code, `${resource} not found`, 404) -} - -export function forbidden(message: string, code: SFSErrorCode = SFSErrorCode.PERMISSION_DENIED): SFSError { - return new SFSError(code, message, 403) -} - -export function unauthorized(message: string = 'Authentication required'): SFSError { - return new SFSError(SFSErrorCode.AUTH_REQUIRED, message, 401) -} - -export function badRequest(message: string, code: SFSErrorCode = SFSErrorCode.PATH_INVALID): SFSError { - return new SFSError(code, message, 400) -} - -export function conflict(message: string, code: SFSErrorCode): SFSError { - return new SFSError(code, message, 409) -} - -export function internalError(message: string, details?: Record): SFSError { - return new SFSError(SFSErrorCode.INTERNAL_ERROR, message, 500, details) -} - -export function successResponse(data: T): { ok: true; data: T } { - return { ok: true, data } -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/http/plugins/auth.plugin.ts b/extensions/entity-files/packages/simple-file-server/src/http/plugins/auth.plugin.ts deleted file mode 100644 index a7e63dc9..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/http/plugins/auth.plugin.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify' -import fp from 'fastify-plugin' -import { IdentityService } from '../../auth/identity.service.js' -import type { Identity } from '../../types/index.js' -import { SFSError, SFSErrorCode, unauthorized } from '../../errors/index.js' -import type { OperationalLogger } from '../../logging/logger.js' - -declare module 'fastify' { - interface FastifyRequest { - authIdentity: Identity - } -} - -interface AuthPluginOptions { - identityService: IdentityService - logger: OperationalLogger -} - -/** - * Authentication plugin wrapped with fastify-plugin so that: - * - The `authIdentity` request decoration is visible in all sibling/child plugins. - * - The `onRequest` hook applies to ALL routes registered on the root instance. - * - * Without fastify-plugin, Fastify's encapsulation would isolate the decoration - * and hook to routes within this plugin's scope only. - */ -export const authPlugin = fp(async function authPlugin( - fastify: FastifyInstance, - options: AuthPluginOptions, -): Promise { - const { identityService, logger } = options - - // Use a plain null initial value — NOT { getter: () => null }. - // In Fastify v5 the getter-object form defines the property as read-only - // (getter-only, no setter), which causes: - // "Cannot set property authIdentity of #<_Request> which has only a getter" - // when the onRequest hook does `request.authIdentity = id`. - fastify.decorateRequest('authIdentity', null) - - fastify.addHook('onRequest', async (request: FastifyRequest, reply: FastifyReply) => { - // Skip health check - if (request.url === '/health') return - - const identity = extractIdentity(request) - const secret = extractSecret(request) - - if (!identity || !secret) { - logger.logError('auth_failed', 'Missing credentials', { ip: request.ip }) - const err = unauthorized('Authentication required. Provide X-SFS-Identity and X-SFS-Secret headers.') - return reply.status(err.statusCode).send(err.toJSON()) - } - - const id = await identityService.verify(identity, secret) - if (!id) { - logger.logError('auth_failed', 'Invalid credentials', { identity, ip: request.ip }) - const err = new SFSError(SFSErrorCode.AUTH_INVALID, 'Invalid credentials', 401) - return reply.status(err.statusCode).send(err.toJSON()) - } - - request.authIdentity = id - }) -}, { name: 'sfs-auth' }) - -function extractIdentity(request: FastifyRequest): string | undefined { - const headerIdentity = request.headers['x-sfs-identity'] - if (typeof headerIdentity === 'string' && headerIdentity) return headerIdentity - - const auth = request.headers.authorization - if (auth?.startsWith('Basic ')) { - const decoded = Buffer.from(auth.slice(6), 'base64').toString('utf-8') - const colonIdx = decoded.indexOf(':') - if (colonIdx > 0) return decoded.slice(0, colonIdx) - } - - return undefined -} - -function extractSecret(request: FastifyRequest): string | undefined { - const headerSecret = request.headers['x-sfs-secret'] - if (typeof headerSecret === 'string' && headerSecret) return headerSecret - - const auth = request.headers.authorization - if (auth?.startsWith('Basic ')) { - const decoded = Buffer.from(auth.slice(6), 'base64').toString('utf-8') - const colonIdx = decoded.indexOf(':') - if (colonIdx >= 0) return decoded.slice(colonIdx + 1) - } - - return undefined -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/http/routes/objects.route.ts b/extensions/entity-files/packages/simple-file-server/src/http/routes/objects.route.ts deleted file mode 100644 index efcbeb92..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/http/routes/objects.route.ts +++ /dev/null @@ -1,243 +0,0 @@ -import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify' -import type { BucketService } from '../../storage/bucket.service.js' -import type { StorageService } from '../../storage/storage.service.js' -import type { ThumbnailService } from '../../thumbnail/thumbnail.service.js' -import type { IdentityService } from '../../auth/identity.service.js' -import type { OperationalLogger } from '../../logging/logger.js' -import { SFSError, SFSErrorCode, forbidden, successResponse } from '../../errors/index.js' -import type { Permission } from '../../types/index.js' - -interface ObjectRoutesOptions { - bucketService: BucketService - storageService: StorageService - thumbnailService: ThumbnailService - identityService: IdentityService - logger: OperationalLogger -} - -export async function objectRoutes(fastify: FastifyInstance, options: ObjectRoutesOptions): Promise { - const { bucketService, storageService, thumbnailService, identityService, logger } = options - - /** - * Helper: resolve bucket and check permission - */ - async function resolveBucketAndCheck( - request: FastifyRequest, - reply: FastifyReply, - bucketName: string, - key: string, - permission: Permission, - ) { - const bucket = await bucketService.get(bucketName) - const identity = request.authIdentity - - const grant = identityService.checkPermission(identity, bucketName, key, permission) - if (!grant) { - logger.logError('permission_denied', `Identity '${identity.identity}' lacks '${permission}' on '${bucketName}/${key}'`, { - identity: identity.identity, - bucket: bucketName, - key, - ip: request.ip, - }) - throw forbidden(`Permission '${permission}' denied on bucket '${bucketName}' for path '${key}'`) - } - - return bucket - } - - /** - * GET /:bucket - Bucket listing with pagination - */ - fastify.get<{ - Params: { bucket: string } - Querystring: { limit?: string; cursor?: string } - }>('/:bucket', async (request, reply) => { - const { bucket: bucketName } = request.params - const limit = Math.min(parseInt(request.query.limit ?? '100', 10), 1000) - const cursor = request.query.cursor - - const bucket = await resolveBucketAndCheck(request, reply, bucketName, '/', 'read') - const start = Date.now() - - const result = await storageService.listBucket(bucket, limit, cursor) - - logger.log({ - event: 'list', - identity: request.authIdentity.identity, - bucket: bucketName, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - - return reply.send(successResponse(result)) - }) - - /** - * GET /:bucket/*key - Download file or list directory - */ - fastify.get<{ - Params: { bucket: string; '*': string } - Querystring: { w?: string; h?: string; fit?: string; format?: string } - }>('/:bucket/*', async (request, reply) => { - const { bucket: bucketName } = request.params - const key = request.params['*'] ?? '' - - const bucket = await resolveBucketAndCheck(request, reply, bucketName, key, 'read') - const start = Date.now() - - // If key ends with '/', it's a directory listing - if (key.endsWith('/') || key === '') { - const result = await storageService.listDirectory(bucket, key) - logger.log({ - event: 'list', - identity: request.authIdentity.identity, - bucket: bucketName, - key, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - return reply.send(successResponse(result)) - } - - // Check for thumbnail request - const { w, h, fit, format } = request.query - if (w || h) { - const thumbOptions = { - width: w ? parseInt(w, 10) : undefined, - height: h ? parseInt(h, 10) : undefined, - fit: (fit as 'cover' | 'contain' | 'fill' | 'inside' | 'outside') ?? 'cover', - format: (format as 'jpeg' | 'png' | 'webp') ?? 'webp', - } - - const thumb = await thumbnailService.getThumbnail(bucket, key, thumbOptions) - if (thumb) { - reply.header('Content-Type', thumb.mimeType) - reply.header('Content-Length', thumb.size.toString()) - reply.header('Cache-Control', 'public, max-age=86400') - logger.log({ - event: 'download', - identity: request.authIdentity.identity, - bucket: bucketName, - key: `${key}?thumbnail`, - size: thumb.size, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - return reply.send(thumb.stream) - } - } - - // Regular file download - const download = await storageService.download(bucket, key) - - reply.header('Content-Type', download.mimeType) - reply.header('Content-Length', download.size.toString()) - reply.header('ETag', download.etag) - reply.header('Last-Modified', download.lastModified.toUTCString()) - reply.header('Cache-Control', 'private, max-age=0') - - logger.log({ - event: 'download', - identity: request.authIdentity.identity, - bucket: bucketName, - key, - size: download.size, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - - return reply.send(download.stream) - }) - - /** - * PUT /:bucket/*key - Upload file - */ - fastify.put<{ - Params: { bucket: string; '*': string } - }>('/:bucket/*', async (request, reply) => { - const { bucket: bucketName } = request.params - const key = request.params['*'] ?? '' - - if (!key) { - return reply.status(400).send({ - ok: false, - error: { code: SFSErrorCode.PATH_INVALID, message: 'Key is required for upload' }, - }) - } - - const bucket = await resolveBucketAndCheck(request, reply, bucketName, key, 'write') - const start = Date.now() - - logger.log({ - event: 'upload_started', - identity: request.authIdentity.identity, - bucket: bucketName, - key, - ip: request.ip, - }) - - try { - const result = await storageService.upload(bucket, key, request.raw as any) - - logger.log({ - event: 'upload_committed', - identity: request.authIdentity.identity, - bucket: bucketName, - key, - size: result.size, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - - return reply.status(201).send(successResponse({ - bucket: bucketName, - key, - size: result.size, - etag: result.etag, - })) - } catch (err) { - logger.logError('upload_failed', err instanceof Error ? err : String(err), { - identity: request.authIdentity.identity, - bucket: bucketName, - key, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - throw err - } - }) - - /** - * DELETE /:bucket/*key - Delete file - */ - fastify.delete<{ - Params: { bucket: string; '*': string } - }>('/:bucket/*', async (request, reply) => { - const { bucket: bucketName } = request.params - const key = request.params['*'] ?? '' - - if (!key) { - return reply.status(400).send({ - ok: false, - error: { code: SFSErrorCode.PATH_INVALID, message: 'Key is required for delete' }, - }) - } - - const bucket = await resolveBucketAndCheck(request, reply, bucketName, key, 'delete') - const start = Date.now() - - await storageService.delete(bucket, key) - - logger.log({ - event: 'delete', - identity: request.authIdentity.identity, - bucket: bucketName, - key, - elapsedMs: Date.now() - start, - ip: request.ip, - }) - - return reply.send(successResponse({ bucket: bucketName, key, deleted: true })) - }) -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/http/server.ts b/extensions/entity-files/packages/simple-file-server/src/http/server.ts deleted file mode 100644 index 2199b78c..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/http/server.ts +++ /dev/null @@ -1,90 +0,0 @@ -import Fastify from 'fastify' -import type { FastifyInstance } from 'fastify' -import { authPlugin } from './plugins/auth.plugin.js' -import { objectRoutes } from './routes/objects.route.js' -import type { BucketService } from '../storage/bucket.service.js' -import type { StorageService } from '../storage/storage.service.js' -import type { ThumbnailService } from '../thumbnail/thumbnail.service.js' -import type { IdentityService } from '../auth/identity.service.js' -import type { OperationalLogger } from '../logging/logger.js' -import { SFSError } from '../errors/index.js' -import type { SFSConfig } from '../types/index.js' - -interface ServerOptions { - config: SFSConfig - bucketService: BucketService - storageService: StorageService - thumbnailService: ThumbnailService - identityService: IdentityService - operationalLogger: OperationalLogger -} - -export async function createServer(options: ServerOptions): Promise { - const { config, bucketService, storageService, thumbnailService, identityService, operationalLogger } = options - - const fastify = Fastify({ - logger: { - level: config.logLevel, - transport: process.env.NODE_ENV !== 'production' - ? { target: 'pino-pretty', options: { translateTime: 'HH:MM:ss Z', ignore: 'pid,hostname' } } - : undefined, - }, - disableRequestLogging: false, - }) - - // Register sensible for default error handling - await fastify.register(import('@fastify/sensible')) - - // Error handler - fastify.setErrorHandler((error, request, reply) => { - if (error instanceof SFSError) { - return reply.status(error.statusCode).send(error.toJSON()) - } - - fastify.log.error(error) - return reply.status(500).send({ - ok: false, - error: { - code: 'SFS_INTERNAL_ERROR', - message: process.env.NODE_ENV === 'production' ? 'Internal server error' : (error instanceof Error ? error.message : String(error)), - }, - }) - }) - - // Not found handler - fastify.setNotFoundHandler((request, reply) => { - return reply.status(404).send({ - ok: false, - error: { - code: 'SFS_NOT_FOUND', - message: `Route ${request.method} ${request.url} not found`, - }, - }) - }) - - // Health check (no auth) - fastify.get('/health', async () => { - return { ok: true, data: { status: 'healthy', uptime: process.uptime() } } - }) - - // Accept any Content-Type for upload routes. - // The PUT handler reads directly from `request.raw` (Node.js IncomingMessage stream), - // so Fastify must NOT attempt to parse the body — it just needs to not reject it. - fastify.addContentTypeParser('*', (_request, _payload, done) => done(null)) - - // Auth plugin (applies to all routes below) - await fastify.register(authPlugin, { identityService, logger: operationalLogger }) - - // Object routes - await fastify.register(objectRoutes, { - bucketService, - storageService, - thumbnailService, - identityService, - logger: operationalLogger, - }) - - return fastify -} - - diff --git a/extensions/entity-files/packages/simple-file-server/src/index.ts b/extensions/entity-files/packages/simple-file-server/src/index.ts deleted file mode 100644 index c28cfcac..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Public API exports for simple-file-server -export { createRuntime, startServer } from './runtime/index.js' -export { BucketService } from './storage/bucket.service.js' -export { StorageService } from './storage/storage.service.js' -export { ThumbnailService } from './thumbnail/thumbnail.service.js' -export { IdentityService } from './auth/identity.service.js' -export { OperationalLogger } from './logging/logger.js' -export { createServer } from './http/server.js' -export * from './types/index.js' -export * from './errors/index.js' - diff --git a/extensions/entity-files/packages/simple-file-server/src/logging/logger.ts b/extensions/entity-files/packages/simple-file-server/src/logging/logger.ts deleted file mode 100644 index dad41ba8..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/logging/logger.ts +++ /dev/null @@ -1,103 +0,0 @@ -import path from 'node:path' -import fsp from 'node:fs/promises' -import fs from 'node:fs' -import { resolveDataPaths } from '../config/config.service.js' - -export type LogEvent = - | 'upload_started' - | 'upload_staged' - | 'upload_committed' - | 'upload_failed' - | 'download' - | 'list' - | 'delete' - | 'auth_failed' - | 'permission_denied' - | 'server_start' - | 'server_stop' - -export interface LogEntry { - ts: string - event: LogEvent - identity?: string - bucket?: string - key?: string - size?: number - elapsedMs?: number - ip?: string - message?: string - error?: string - [key: string]: unknown -} - -export class OperationalLogger { - private accessLogPath: string - private errorLogPath: string - private accessStream: fs.WriteStream | null = null - private errorStream: fs.WriteStream | null = null - - constructor(dataDir: string) { - const logsDir = resolveDataPaths(dataDir).logsDir - this.accessLogPath = path.join(logsDir, 'access.log.jsonl') - this.errorLogPath = path.join(logsDir, 'error.log.jsonl') - } - - async open(): Promise { - const logsDir = path.dirname(this.accessLogPath) - await fsp.mkdir(logsDir, { recursive: true }) - - this.accessStream = fs.createWriteStream(this.accessLogPath, { flags: 'a' }) - this.errorStream = fs.createWriteStream(this.errorLogPath, { flags: 'a' }) - } - - async close(): Promise { - await new Promise((resolve) => { - if (this.accessStream) { - this.accessStream.end(resolve) - } else { - resolve() - } - }) - await new Promise((resolve) => { - if (this.errorStream) { - this.errorStream.end(resolve) - } else { - resolve() - } - }) - } - - log(entry: Omit & { event: LogEvent }): void { - const fullEntry: LogEntry = { - ts: new Date().toISOString(), - ...entry, - } - - const line = JSON.stringify(fullEntry) + '\n' - const isError = entry.event === 'auth_failed' - || entry.event === 'permission_denied' - || entry.event === 'upload_failed' - - if (this.accessStream) { - this.accessStream.write(line) - } - - if (isError && this.errorStream) { - this.errorStream.write(line) - } - } - - logAccess(event: LogEvent, data: Partial): void { - this.log({ event, ...data }) - } - - logError(event: LogEvent, error: Error | string, data: Partial = {}): void { - this.log({ - event, - error: typeof error === 'string' ? error : error.message, - ...data, - }) - } -} - - diff --git a/extensions/entity-files/packages/simple-file-server/src/runtime/index.ts b/extensions/entity-files/packages/simple-file-server/src/runtime/index.ts deleted file mode 100644 index c34146d4..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/runtime/index.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { ensureDataDirs, getDefaultConfig } from '../config/config.service.js' -import { IdentityService } from '../auth/identity.service.js' -import { BucketService } from '../storage/bucket.service.js' -import { StorageService } from '../storage/storage.service.js' -import { ThumbnailService } from '../thumbnail/thumbnail.service.js' -import { OperationalLogger } from '../logging/logger.js' -import { createServer } from '../http/server.js' -import type { SFSConfig } from '../types/index.js' - -export interface SFSRuntime { - identityService: IdentityService - bucketService: BucketService - storageService: StorageService - thumbnailService: ThumbnailService - operationalLogger: OperationalLogger - config: SFSConfig -} - -export async function createRuntime(overrides?: Partial): Promise { - const config: SFSConfig = { ...getDefaultConfig(), ...overrides } - - // Ensure all data directories exist - await ensureDataDirs(config.dataDir) - - // Create services - const operationalLogger = new OperationalLogger(config.dataDir) - await operationalLogger.open() - - const identityService = new IdentityService(config.dataDir) - const bucketService = new BucketService(config.dataDir) - const storageService = new StorageService(bucketService) - const thumbnailService = new ThumbnailService(bucketService, storageService) - - return { - config, - identityService, - bucketService, - storageService, - thumbnailService, - operationalLogger, - } -} - -export async function startServer(overrides?: Partial): Promise { - const runtime = await createRuntime(overrides) - const { config, bucketService, storageService, thumbnailService, identityService, operationalLogger } = runtime - - // Validate buckets on startup - await bucketService.validateStartup() - - const server = await createServer({ - config, - bucketService, - storageService, - thumbnailService, - identityService, - operationalLogger, - }) - - operationalLogger.log({ event: 'server_start', message: `Starting SFS on ${config.host}:${config.port}` }) - - // Graceful shutdown - const shutdown = async (signal: string) => { - server.log.info(`Received ${signal}, gracefully shutting down...`) - operationalLogger.log({ event: 'server_stop', message: `Shutting down (${signal})` }) - await server.close() - await operationalLogger.close() - process.exit(0) - } - - process.on('SIGTERM', () => shutdown('SIGTERM')) - process.on('SIGINT', () => shutdown('SIGINT')) - - try { - await server.listen({ host: config.host, port: config.port }) - server.log.info(`SFS server listening on http://${config.host}:${config.port}`) - } catch (err) { - server.log.error(err) - await operationalLogger.close() - process.exit(1) - } - - return runtime -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/storage/bucket.service.ts b/extensions/entity-files/packages/simple-file-server/src/storage/bucket.service.ts deleted file mode 100644 index f3415df4..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/storage/bucket.service.ts +++ /dev/null @@ -1,176 +0,0 @@ -import path from 'node:path' -import fsp from 'node:fs/promises' -import fs from 'node:fs' -import { resolveDataPaths, readJsonFile, writeJsonFile } from '../config/config.service.js' -import type { Bucket } from '../types/index.js' -import { SFSError, SFSErrorCode, notFound } from '../errors/index.js' - -const SFS_INTERNAL_DIR = '.sfs' - -function conflict(message: string, code: SFSErrorCode): SFSError { - return new SFSError(code, message, 409) -} - -export class BucketService { - private bucketsDir: string - - constructor(dataDir: string) { - this.bucketsDir = resolveDataPaths(dataDir).bucketsDir - } - - private bucketFilePath(name: string): string { - const safe = name.replace(/[^a-zA-Z0-9_\-\.]/g, '_') - return path.join(this.bucketsDir, `${safe}.json`) - } - - async create(name: string, absolutePath: string): Promise { - if (!path.isAbsolute(absolutePath)) { - throw new SFSError(SFSErrorCode.BUCKET_PATH_INVALID, `Bucket path must be absolute: ${absolutePath}`, 400) - } - - const existing = await this.find(name) - if (existing) { - throw conflict(`Bucket '${name}' already exists`, SFSErrorCode.BUCKET_ALREADY_EXISTS) - } - - // Ensure bucket dir exists - await fsp.mkdir(absolutePath, { recursive: true }) - - // Validate writable - try { - await fsp.access(absolutePath, fs.constants.W_OK) - } catch { - throw new SFSError(SFSErrorCode.BUCKET_PATH_NOT_WRITABLE, `Bucket path is not writable: ${absolutePath}`, 400) - } - - // Create internal .sfs directory - await this.ensureBucketInternals(absolutePath) - - const bucket: Bucket = { - name, - path: absolutePath, - createdAt: new Date().toISOString(), - } - - await writeJsonFile(this.bucketFilePath(name), bucket) - return bucket - } - - async find(name: string): Promise { - return readJsonFile(this.bucketFilePath(name)) - } - - async get(name: string): Promise { - const bucket = await this.find(name) - if (!bucket) { - throw notFound(`Bucket '${name}'`, SFSErrorCode.BUCKET_NOT_FOUND) - } - return bucket - } - - async list(): Promise { - try { - const files = await fsp.readdir(this.bucketsDir) - const buckets: Bucket[] = [] - for (const file of files) { - if (!file.endsWith('.json')) continue - const b = await readJsonFile(path.join(this.bucketsDir, file)) - if (b) buckets.push(b) - } - return buckets - } catch { - return [] - } - } - - async delete(name: string): Promise { - const filePath = this.bucketFilePath(name) - try { - await fsp.unlink(filePath) - } catch { - throw notFound(`Bucket '${name}'`, SFSErrorCode.BUCKET_NOT_FOUND) - } - } - - /** - * Resolve a key to an absolute filesystem path within the bucket. - * Validates against path traversal attacks. - */ - resolveKey(bucket: Bucket, key: string): string { - // Normalize to remove double slashes, . and .. - const normalized = path.normalize(key).replace(/\\/g, '/') - - // Block access to internal .sfs directory - const parts = normalized.split('/') - if (parts.some(p => p === SFS_INTERNAL_DIR)) { - throw new SFSError(SFSErrorCode.PATH_RESERVED, `Access to internal '${SFS_INTERNAL_DIR}' path is forbidden`, 403) - } - - // Normalize bucket root to remove any trailing separator - const bucketRoot = path.resolve(bucket.path) - const resolved = path.resolve(bucketRoot, normalized.replace(/^\//, '')) - - // Ensure resolved path is within bucket root - if (!resolved.startsWith(bucketRoot + path.sep) && resolved !== bucketRoot) { - throw new SFSError(SFSErrorCode.PATH_TRAVERSAL, 'Path traversal detected', 400) - } - - return resolved - } - - /** - * Validate that a key does not point outside bucket boundaries. - */ - validateKey(bucket: Bucket, key: string): string { - return this.resolveKey(bucket, key) - } - - async ensureBucketInternals(bucketPath: string): Promise { - const sfsDir = path.join(bucketPath, SFS_INTERNAL_DIR) - await fsp.mkdir(path.join(sfsDir, 'staging'), { recursive: true }) - await fsp.mkdir(path.join(sfsDir, 'thumbs'), { recursive: true }) - await fsp.mkdir(path.join(sfsDir, 'runtime'), { recursive: true }) - } - - getStagingDir(bucket: Bucket): string { - return path.join(bucket.path, SFS_INTERNAL_DIR, 'staging') - } - - getThumbsDir(bucket: Bucket): string { - return path.join(bucket.path, SFS_INTERNAL_DIR, 'thumbs') - } - - /** - * Validate startup: check all buckets are accessible and writable, clean orphan staging files. - */ - async validateStartup(): Promise { - const buckets = await this.list() - for (const bucket of buckets) { - try { - await fsp.access(bucket.path, fs.constants.W_OK) - await this.ensureBucketInternals(bucket.path) - await this.cleanOrphanStagingFiles(bucket) - } catch (err) { - console.warn(`[SFS] Warning: bucket '${bucket.name}' at '${bucket.path}' is not accessible:`, err) - } - } - } - - private async cleanOrphanStagingFiles(bucket: Bucket): Promise { - const stagingDir = this.getStagingDir(bucket) - try { - const files = await fsp.readdir(stagingDir) - const cutoff = Date.now() - 60 * 60 * 1000 // older than 1 hour - for (const file of files) { - const filePath = path.join(stagingDir, file) - const stat = await fsp.stat(filePath) - if (stat.mtimeMs < cutoff) { - await fsp.unlink(filePath).catch(() => {}) - } - } - } catch { - // Ignore cleanup errors - } - } -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/storage/storage.service.ts b/extensions/entity-files/packages/simple-file-server/src/storage/storage.service.ts deleted file mode 100644 index aeb367fe..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/storage/storage.service.ts +++ /dev/null @@ -1,298 +0,0 @@ -import path from 'node:path' -import fsp from 'node:fs/promises' -import fs from 'node:fs' -import type { Stats } from 'node:fs' -import crypto from 'node:crypto' -import { pipeline } from 'node:stream/promises' -import type { Readable } from 'node:stream' -import { fileTypeFromBuffer, fileTypeFromFile } from 'file-type' -import type { Bucket, ListResult, ListEntry } from '../types/index.js' -import { SFSError, SFSErrorCode, notFound } from '../errors/index.js' -import { BucketService } from './bucket.service.js' - -export interface DownloadResult { - stream: fs.ReadStream - size: number - mimeType: string - lastModified: Date - etag: string -} - -export interface UploadOptions { - overwrite?: boolean -} - -export class StorageService { - constructor(private readonly bucketService: BucketService) {} - - /** - * Download a file from a bucket. Returns a readable stream. - */ - async download(bucket: Bucket, key: string): Promise { - const filePath = this.bucketService.resolveKey(bucket, key) - - let stat: Stats - try { - stat = await fsp.stat(filePath) - } catch { - throw notFound(`Object '${key}' in bucket '${bucket.name}'`, SFSErrorCode.OBJECT_NOT_FOUND) - } - - if (stat.isDirectory()) { - throw new SFSError(SFSErrorCode.OBJECT_IS_DIRECTORY, `'${key}' is a directory, not a file`, 400) - } - - const mimeType = await this.detectMimeType(filePath) - const etag = `"${stat.size}-${stat.mtimeMs}"` - - return { - stream: fs.createReadStream(filePath), - size: stat.size, - mimeType, - lastModified: stat.mtime, - etag, - } - } - - /** - * Upload a file to a bucket using staging + atomic move. - */ - async upload(bucket: Bucket, key: string, source: Readable, options: UploadOptions = {}): Promise<{ size: number; etag: string }> { - const finalPath = this.bucketService.resolveKey(bucket, key) - const stagingDir = this.bucketService.getStagingDir(bucket) - const stagingFile = path.join(stagingDir, `${crypto.randomUUID()}.tmp`) - - // Ensure parent directory exists - const parentDir = path.dirname(finalPath) - await fsp.mkdir(parentDir, { recursive: true }) - - let bytesWritten = 0 - - try { - // Stream upload to staging - const writeStream = fs.createWriteStream(stagingFile) - writeStream.on('pipe', () => {}) - - await pipeline(source, writeStream) - - // fsync to ensure data is on disk - const fd = await fsp.open(stagingFile, 'r') - try { - await fd.sync() - } finally { - await fd.close() - } - - const stat = await fsp.stat(stagingFile) - bytesWritten = stat.size - - // Atomic move to final destination - try { - await fsp.rename(stagingFile, finalPath) - } catch (err: unknown) { - // Cross-device rename: fallback to copy + unlink - const error = err as NodeJS.ErrnoException - if (error.code === 'EXDEV') { - await pipeline(fs.createReadStream(stagingFile), fs.createWriteStream(finalPath)) - await fsp.unlink(stagingFile) - } else { - throw err - } - } - - const etag = `"${bytesWritten}-${Date.now()}"` - return { size: bytesWritten, etag } - } catch (err) { - // Cleanup staging file on error - await fsp.unlink(stagingFile).catch(() => {}) - throw err - } - } - - /** - * Delete a file from a bucket. - */ - async delete(bucket: Bucket, key: string): Promise { - const filePath = this.bucketService.resolveKey(bucket, key) - - let stat: Stats - try { - stat = await fsp.stat(filePath) - } catch { - throw notFound(`Object '${key}' in bucket '${bucket.name}'`, SFSErrorCode.OBJECT_NOT_FOUND) - } - - if (stat.isDirectory()) { - throw new SFSError(SFSErrorCode.OBJECT_IS_DIRECTORY, `'${key}' is a directory and cannot be deleted`, 400) - } - - await fsp.unlink(filePath) - } - - /** - * List directory contents. - */ - async listDirectory(bucket: Bucket, keyPrefix: string): Promise { - const dirPath = this.bucketService.resolveKey(bucket, keyPrefix || '/') - - let stat: Stats - try { - stat = await fsp.stat(dirPath) - } catch { - throw notFound(`Directory '${keyPrefix}' in bucket '${bucket.name}'`, SFSErrorCode.OBJECT_NOT_FOUND) - } - - if (!stat.isDirectory()) { - throw new SFSError(SFSErrorCode.OBJECT_IS_DIRECTORY, `'${keyPrefix}' is not a directory`, 404) - } - - const entries = await fsp.readdir(dirPath, { withFileTypes: true }) - const result: ListEntry[] = [] - - for (const entry of entries) { - // Skip internal .sfs directory - if (entry.name === '.sfs') continue - - const entryPath = path.join(dirPath, entry.name) - try { - const entryStat = await fsp.stat(entryPath) - const relativeKey = path.join(keyPrefix || '', entry.name).replace(/\\/g, '/') - - result.push({ - key: entry.isDirectory() ? `${relativeKey}/` : relativeKey, - size: entryStat.size, - lastModified: entryStat.mtime.toISOString(), - isDirectory: entry.isDirectory(), - }) - } catch { - // Skip entries we can't stat - } - } - - return { - bucket: bucket.name, - prefix: keyPrefix || '/', - entries: result, - hasMore: false, - total: result.length, - } - } - - /** - * List bucket contents with pagination. - */ - async listBucket(bucket: Bucket, limit: number = 100, cursor?: string): Promise { - const allEntries = await this.collectAllEntries(bucket, bucket.path, '') - - let startIdx = 0 - if (cursor) { - const cursorIdx = allEntries.findIndex(e => e.key === cursor) - if (cursorIdx >= 0) startIdx = cursorIdx + 1 - } - - const page = allEntries.slice(startIdx, startIdx + limit) - const hasMore = startIdx + limit < allEntries.length - const nextCursor = hasMore ? page[page.length - 1]?.key : undefined - - return { - bucket: bucket.name, - prefix: '/', - entries: page, - cursor: nextCursor, - hasMore, - total: allEntries.length, - } - } - - private async collectAllEntries(bucket: Bucket, dirPath: string, prefix: string): Promise { - const result: ListEntry[] = [] - try { - const entries = await fsp.readdir(dirPath, { withFileTypes: true }) - for (const entry of entries) { - if (entry.name === '.sfs') continue - - const entryPath = path.join(dirPath, entry.name) - const relKey = prefix ? `${prefix}/${entry.name}` : entry.name - - try { - const stat = await fsp.stat(entryPath) - if (entry.isDirectory()) { - const subEntries = await this.collectAllEntries(bucket, entryPath, relKey) - result.push(...subEntries) - } else { - result.push({ - key: relKey, - size: stat.size, - lastModified: stat.mtime.toISOString(), - isDirectory: false, - }) - } - } catch { - // skip - } - } - } catch { - // empty - } - return result - } - - /** - * Detect MIME type using magic bytes, with fallback to extension. - */ - async detectMimeType(filePath: string): Promise { - try { - const result = await fileTypeFromFile(filePath) - if (result) return result.mime - } catch { - // fallback - } - return this.mimeFromExtension(filePath) - } - - async detectMimeTypeFromBuffer(buffer: Buffer): Promise { - try { - const result = await fileTypeFromBuffer(buffer) - if (result) return result.mime - } catch { - // fallback - } - return 'application/octet-stream' - } - - private mimeFromExtension(filePath: string): string { - const ext = path.extname(filePath).toLowerCase() - const mimeMap: Record = { - '.jpg': 'image/jpeg', - '.jpeg': 'image/jpeg', - '.png': 'image/png', - '.gif': 'image/gif', - '.webp': 'image/webp', - '.svg': 'image/svg+xml', - '.pdf': 'application/pdf', - '.json': 'application/json', - '.txt': 'text/plain', - '.html': 'text/html', - '.css': 'text/css', - '.js': 'application/javascript', - '.ts': 'application/typescript', - '.xml': 'application/xml', - '.zip': 'application/zip', - '.tar': 'application/x-tar', - '.gz': 'application/gzip', - '.mp4': 'video/mp4', - '.mp3': 'audio/mpeg', - '.wav': 'audio/wav', - } - return mimeMap[ext] ?? 'application/octet-stream' - } - - isImageMime(mimeType: string): boolean { - return mimeType.startsWith('image/') && mimeType !== 'image/svg+xml' - } -} - - - - - diff --git a/extensions/entity-files/packages/simple-file-server/src/thumbnail/thumbnail.service.ts b/extensions/entity-files/packages/simple-file-server/src/thumbnail/thumbnail.service.ts deleted file mode 100644 index 0d715a4c..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/thumbnail/thumbnail.service.ts +++ /dev/null @@ -1,135 +0,0 @@ -import path from 'node:path' -import fsp from 'node:fs/promises' -import fs from 'node:fs' -import sharp from 'sharp' -import type { Bucket } from '../types/index.js' -import { BucketService } from '../storage/bucket.service.js' -import { StorageService } from '../storage/storage.service.js' - -export interface ThumbnailOptions { - width?: number - height?: number - fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside' - format?: 'jpeg' | 'png' | 'webp' -} - -export interface ThumbnailResult { - stream: fs.ReadStream - mimeType: string - size: number -} - -export class ThumbnailService { - constructor( - private readonly bucketService: BucketService, - private readonly storageService: StorageService, - ) {} - - /** - * Generate or retrieve a thumbnail. - * Thumbnails are stored inside the bucket alongside the original file: - * {original_dir}/{WxH}/{original_filename} - * Example: - * Request: account1/producto.jpg?w=200&h=200 - * Stored: account1/200x200/producto.jpg - */ - async getThumbnail(bucket: Bucket, key: string, options: ThumbnailOptions): Promise { - const filePath = this.bucketService.resolveKey(bucket, key) - - // Check if original file exists - try { - await fsp.stat(filePath) - } catch { - return null - } - - // Detect mime type — only process images - const mimeType = await this.storageService.detectMimeType(filePath) - if (!this.storageService.isImageMime(mimeType)) { - return null - } - - // Resolve output format: explicit param > inferred from original mime - const outputFormat = options.format ?? this.formatFromMime(mimeType) - - // Build the thumbnail key and resolve its absolute path inside the bucket - const thumbKey = this.buildThumbKey(key, options) - const thumbPath = this.bucketService.resolveKey(bucket, thumbKey) - - // Serve existing thumbnail if already cached - try { - const stat = await fsp.stat(thumbPath) - return { - stream: fs.createReadStream(thumbPath), - mimeType: `image/${outputFormat}`, - size: stat.size, - } - } catch { - // Not cached yet — generate below - } - - // Ensure the {WxH} sub-directory exists - await fsp.mkdir(path.dirname(thumbPath), { recursive: true }) - - try { - let pipeline = sharp(filePath) - - if (options.width || options.height) { - pipeline = pipeline.resize({ - width: options.width, - height: options.height, - fit: options.fit ?? 'cover', - withoutEnlargement: true, - }) - } - - if (outputFormat === 'webp') { - pipeline = pipeline.webp({ quality: 85 }) - } else if (outputFormat === 'png') { - pipeline = pipeline.png({ compressionLevel: 6 }) - } else { - pipeline = pipeline.jpeg({ quality: 85 }) - } - - await pipeline.toFile(thumbPath) - - const stat = await fsp.stat(thumbPath) - return { - stream: fs.createReadStream(thumbPath), - mimeType: `image/${outputFormat}`, - size: stat.size, - } - } catch (err) { - // Clean up any partial file on failure - await fsp.unlink(thumbPath).catch(() => {}) - return null - } - } - - /** - * Build the bucket-relative key for a thumbnail. - * Structure: {original_dir}/{WxH}/{original_filename} - * Examples: - * "account1/producto.jpg" + 200x200 → "account1/200x200/producto.jpg" - * "photo.png" + 100x100 → "100x100/photo.png" - */ - buildThumbKey(key: string, options: Pick): string { - const dir = path.dirname(key) // "account1" | "." - const filename = path.basename(key) // "producto.jpg" - const w = options.width ?? 0 - const h = options.height ?? 0 - const dimensionFolder = `${w}x${h}` - const baseDir = dir === '.' ? '' : dir - return baseDir ? `${baseDir}/${dimensionFolder}/${filename}` : `${dimensionFolder}/${filename}` - } - - /** - * Infer a sharp-compatible output format from a MIME type. - */ - private formatFromMime(mimeType: string): 'jpeg' | 'png' | 'webp' { - if (mimeType === 'image/png') return 'png' - if (mimeType === 'image/webp') return 'webp' - return 'jpeg' - } -} - diff --git a/extensions/entity-files/packages/simple-file-server/src/types/index.ts b/extensions/entity-files/packages/simple-file-server/src/types/index.ts deleted file mode 100644 index 76331c0f..00000000 --- a/extensions/entity-files/packages/simple-file-server/src/types/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Shared types for simple-file-server - -export type Permission = 'read' | 'write' | 'delete' - -export interface Grant { - bucket: string - prefixes: string[] - permissions: Permission[] -} - -export interface Identity { - identity: string - hashedSecret: string - grants: Grant[] - createdAt: string - updatedAt: string -} - -export interface Bucket { - name: string - path: string - createdAt: string -} - -export interface SFSConfig { - dataDir: string - host: string - port: number - logLevel: string -} - -export interface ListEntry { - key: string - size: number - lastModified: string - isDirectory: boolean -} - -export interface ListResult { - bucket: string - prefix: string - entries: ListEntry[] - cursor?: string - hasMore: boolean - total: number -} - -export interface AuthContext { - identity: string - grants: Grant[] -} - diff --git a/extensions/entity-files/packages/simple-file-server/test/core.test.ts b/extensions/entity-files/packages/simple-file-server/test/core.test.ts deleted file mode 100644 index bfe9046b..00000000 --- a/extensions/entity-files/packages/simple-file-server/test/core.test.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { describe, it, expect, beforeEach, afterEach } from 'vitest' -import path from 'node:path' -import os from 'node:os' -import fsp from 'node:fs/promises' -import { BucketService } from '../src/storage/bucket.service.js' -import { StorageService } from '../src/storage/storage.service.js' -import { ThumbnailService } from '../src/thumbnail/thumbnail.service.js' -import { IdentityService } from '../src/auth/identity.service.js' -import { ensureDataDirs } from '../src/config/config.service.js' -import { Readable } from 'node:stream' - -let tempDir: string -let bucketService: BucketService -let storageService: StorageService -let thumbnailService: ThumbnailService -let identityService: IdentityService - -beforeEach(async () => { - tempDir = await fsp.mkdtemp(path.join(os.tmpdir(), 'sfs-test-')) - await ensureDataDirs(tempDir) - bucketService = new BucketService(tempDir) - storageService = new StorageService(bucketService) - thumbnailService = new ThumbnailService(bucketService, storageService) - identityService = new IdentityService(tempDir) -}) - -afterEach(async () => { - await fsp.rm(tempDir, { recursive: true, force: true }) -}) - -// ────────────────────────────────────────────────────────── -// BucketService Tests -// ────────────────────────────────────────────────────────── -describe('BucketService', () => { - it('should create a bucket', async () => { - const bucketPath = path.join(tempDir, 'my-bucket') - const bucket = await bucketService.create('test', bucketPath) - expect(bucket.name).toBe('test') - expect(bucket.path).toBe(bucketPath) - expect(bucket.createdAt).toBeDefined() - }) - - it('should reject non-absolute paths', async () => { - await expect(bucketService.create('bad', 'relative/path')).rejects.toThrow('must be absolute') - }) - - it('should prevent duplicate buckets', async () => { - const bucketPath = path.join(tempDir, 'dup-bucket') - await bucketService.create('dup', bucketPath) - await expect(bucketService.create('dup', bucketPath)).rejects.toThrow('already exists') - }) - - it('should list buckets', async () => { - await bucketService.create('b1', path.join(tempDir, 'b1')) - await bucketService.create('b2', path.join(tempDir, 'b2')) - const list = await bucketService.list() - expect(list.length).toBe(2) - }) - - it('should delete a bucket', async () => { - await bucketService.create('del', path.join(tempDir, 'del')) - await bucketService.delete('del') - const bucket = await bucketService.find('del') - expect(bucket).toBeNull() - }) - - it('should detect path traversal attacks', async () => { - const bucketPath = path.join(tempDir, 'safe-bucket') - const bucket = await bucketService.create('safe', bucketPath) - expect(() => bucketService.resolveKey(bucket, '../../../etc/passwd')).toThrow() - }) - - it('should block access to .sfs directory', async () => { - const bucketPath = path.join(tempDir, 'internal-bucket') - const bucket = await bucketService.create('internal', bucketPath) - expect(() => bucketService.resolveKey(bucket, '.sfs/staging/file.txt')).toThrow() - }) -}) - -// ────────────────────────────────────────────────────────── -// IdentityService Tests -// ────────────────────────────────────────────────────────── -describe('IdentityService', () => { - it('should create an identity', async () => { - const identity = await identityService.create('test-user', 'secret123') - expect(identity.identity).toBe('test-user') - expect(identity.hashedSecret).not.toBe('secret123') - expect(identity.grants).toEqual([]) - }) - - it('should verify correct credentials', async () => { - await identityService.create('verifiable', 'my-secret') - const result = await identityService.verify('verifiable', 'my-secret') - expect(result).not.toBeNull() - expect(result?.identity).toBe('verifiable') - }) - - it('should reject incorrect credentials', async () => { - await identityService.create('user1', 'correct-pass') - const result = await identityService.verify('user1', 'wrong-pass') - expect(result).toBeNull() - }) - - it('should return null for unknown identity', async () => { - const result = await identityService.verify('unknown', 'any') - expect(result).toBeNull() - }) - - it('should grant and check permissions', async () => { - const id = await identityService.create('perm-user', 'pass') - await identityService.grant('perm-user', { - bucket: 'docs', - prefixes: ['/tenant-a/'], - permissions: ['read', 'write'], - }) - - const updated = await identityService.get('perm-user') - const grant = identityService.checkPermission(updated, 'docs', '/tenant-a/file.pdf', 'read') - expect(grant).not.toBeNull() - - const denied = identityService.checkPermission(updated, 'docs', '/tenant-b/file.pdf', 'read') - expect(denied).toBeNull() - }) - - it('should revoke permissions', async () => { - await identityService.create('rev-user', 'pass') - await identityService.grant('rev-user', { - bucket: 'docs', - prefixes: [], - permissions: ['read'], - }) - await identityService.revoke('rev-user', 'docs') - - const id = await identityService.get('rev-user') - expect(id.grants).toHaveLength(0) - }) - - it('should delete an identity', async () => { - await identityService.create('deletable', 'pass') - await identityService.delete('deletable') - const found = await identityService.find('deletable') - expect(found).toBeNull() - }) -}) - -// ────────────────────────────────────────────────────────── -// StorageService Tests -// ────────────────────────────────────────────────────────── -describe('StorageService', () => { - let bucket: Awaited> - - beforeEach(async () => { - bucket = await bucketService.create('store', path.join(tempDir, 'store')) - }) - - it('should upload and download a file', async () => { - const content = 'Hello, SFS!' - const source = Readable.from([content]) - await storageService.upload(bucket, 'test/hello.txt', source) - - const download = await storageService.download(bucket, 'test/hello.txt') - const chunks: Buffer[] = [] - for await (const chunk of download.stream) { - chunks.push(Buffer.from(chunk)) - } - expect(Buffer.concat(chunks).toString('utf-8')).toBe(content) - expect(download.size).toBe(content.length) - }) - - it('should delete a file', async () => { - const source = Readable.from(['delete me']) - await storageService.upload(bucket, 'to-delete.txt', source) - await storageService.delete(bucket, 'to-delete.txt') - await expect(storageService.download(bucket, 'to-delete.txt')).rejects.toThrow() - }) - - it('should throw on missing file download', async () => { - await expect(storageService.download(bucket, 'nonexistent.txt')).rejects.toThrow() - }) - - it('should list directory contents', async () => { - await storageService.upload(bucket, 'dir/a.txt', Readable.from(['a'])) - await storageService.upload(bucket, 'dir/b.txt', Readable.from(['b'])) - - const result = await storageService.listDirectory(bucket, 'dir') - expect(result.entries.length).toBe(2) - const keys = result.entries.map(e => e.key) - expect(keys).toContain('dir/a.txt') - expect(keys).toContain('dir/b.txt') - }) - - it('should list a bucket with pagination', async () => { - for (let i = 0; i < 5; i++) { - await storageService.upload(bucket, `file-${i}.txt`, Readable.from([`content-${i}`])) - } - - const page1 = await storageService.listBucket(bucket, 3) - expect(page1.entries.length).toBe(3) - expect(page1.hasMore).toBe(true) - - const page2 = await storageService.listBucket(bucket, 3, page1.cursor) - expect(page2.entries.length).toBe(2) - expect(page2.hasMore).toBe(false) - }) -}) - -// ────────────────────────────────────────────────────────── -// ThumbnailService Tests -// ────────────────────────────────────────────────────────── -describe('ThumbnailService.buildThumbKey', () => { - it('should build key for a file in a subdirectory', () => { - const key = thumbnailService.buildThumbKey('account1/producto.jpg', { width: 200, height: 200 }) - expect(key).toBe('account1/200x200/producto.jpg') - }) - - it('should build key for a file at bucket root', () => { - const key = thumbnailService.buildThumbKey('photo.png', { width: 100, height: 100 }) - expect(key).toBe('100x100/photo.png') - }) - - it('should build key for a deeply nested file', () => { - const key = thumbnailService.buildThumbKey('a/b/c/image.webp', { width: 300, height: 150 }) - expect(key).toBe('a/b/c/300x150/image.webp') - }) - - it('should use 0 for missing width or height', () => { - const key = thumbnailService.buildThumbKey('img.jpg', { width: 400 }) - expect(key).toBe('400x0/img.jpg') - }) - - it('should return null for non-image files', async () => { - const bucket = await bucketService.create('thumb-test', path.join(tempDir, 'thumb-test')) - await storageService.upload(bucket, 'doc.txt', Readable.from(['hello'])) - const result = await thumbnailService.getThumbnail(bucket, 'doc.txt', { width: 200, height: 200 }) - expect(result).toBeNull() - }) - - it('should return null for missing files', async () => { - const bucket = await bucketService.create('thumb-missing', path.join(tempDir, 'thumb-missing')) - const result = await thumbnailService.getThumbnail(bucket, 'nonexistent.jpg', { width: 200, height: 200 }) - expect(result).toBeNull() - }) -}) - diff --git a/extensions/entity-files/packages/simple-file-server/tsconfig.build.json b/extensions/entity-files/packages/simple-file-server/tsconfig.build.json deleted file mode 100644 index 6f794190..00000000 --- a/extensions/entity-files/packages/simple-file-server/tsconfig.build.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": false - } -} - diff --git a/extensions/entity-files/packages/simple-file-server/tsconfig.json b/extensions/entity-files/packages/simple-file-server/tsconfig.json deleted file mode 100644 index d4d2580b..00000000 --- a/extensions/entity-files/packages/simple-file-server/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "moduleResolution": "bundler", - "lib": ["ES2022"], - "outDir": "./dist", - "rootDir": "./src", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "resolveJsonModule": true, - "forceConsistentCasingInFileNames": true, - "noUnusedLocals": false, - "noUnusedParameters": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"], - "exclude": ["node_modules", "dist"] -} - diff --git a/extensions/entity-files/packages/simple-file-server/vitest.config.ts b/extensions/entity-files/packages/simple-file-server/vitest.config.ts deleted file mode 100644 index 66e5397d..00000000 --- a/extensions/entity-files/packages/simple-file-server/vitest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - include: ['test/**/*.test.ts'], - environment: 'node', - testTimeout: 30000, - }, -}) - diff --git a/extensions/entity-files/sources/core/pom.xml b/extensions/entity-files/sources/core/pom.xml index 4b0e3e2e..6ebbc54e 100644 --- a/extensions/entity-files/sources/core/pom.xml +++ b/extensions/entity-files/sources/core/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules.entityfiles.parent tools.dynamia.modules - 26.5.1 + 26.5.2 DynamiaModules - EntityFiles - Core tools.dynamia.modules.entityfiles @@ -54,20 +54,20 @@ tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 jar tools.dynamia tools.dynamia.io - 26.5.1 + 26.5.2 jar tools.dynamia tools.dynamia.web - 26.5.1 + 26.5.2 jar diff --git a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/EntityFileAccountProvider.java b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/EntityFileAccountProvider.java index c51c6fa4..8ff9ad44 100644 --- a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/EntityFileAccountProvider.java +++ b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/EntityFileAccountProvider.java @@ -18,12 +18,30 @@ package tools.dynamia.modules.entityfile; +import tools.dynamia.modules.entityfile.domain.EntityFile; + /** * * @author Mario Serrano Leones */ public interface EntityFileAccountProvider { + /** + * Return current account Id for tenant + * + * @return account id + */ Long getAccountId(); + + /** + * Check is the account id is valid, by default just validate if account id not null + * + * @param entityFile + * @return valid + */ + default boolean isValidEntityFile(EntityFile entityFile) { + return entityFile != null && entityFile.getAccountId() != null && entityFile.getAccountId() > 0; + } + } diff --git a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/controller/EntityFileStorageController.java b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/controller/EntityFileStorageController.java index cd32e128..d0899301 100644 --- a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/controller/EntityFileStorageController.java +++ b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/controller/EntityFileStorageController.java @@ -74,7 +74,7 @@ public ResponseEntity> export(@PathVariable String uuid, Htt return ResponseEntity.notFound().build(); } - if (!isSameAccount(entityFile)) { + if (!isValidAccount(entityFile)) { return ResponseEntity.notFound().build(); } @@ -209,7 +209,7 @@ public ResponseEntity get(@PathVariable("uuid") String uuid, @PathVari return ResponseEntity.notFound().build(); } - if (!isSameAccount(entityFile)) { + if (!isValidAccount(entityFile)) { return ResponseEntity.notFound().build(); } @@ -320,7 +320,7 @@ private EntityFile resolveParent(String parentUuid) { } EntityFile parent = entityFileService.getEntityFile(parentUuid.trim()); - if (parent == null || !isSameAccount(parent)) { + if (parent == null || !isValidAccount(parent)) { throw new UploadRequestException(HttpStatus.NOT_FOUND, "Parent entity file not found: " + parentUuid); } return parent; @@ -565,12 +565,10 @@ private boolean isNumeric(String value) { * @param entityFile file to evaluate * @return {@code true} when the file can be accessed from the current account context */ - private boolean isSameAccount(EntityFile entityFile) { + private boolean isValidAccount(EntityFile entityFile) { EntityFileAccountProvider accountProvider = Containers.get().findObject(EntityFileAccountProvider.class); - if (accountProvider != null) { - if (entityFile.getAccountId() != null) { - return entityFile.getAccountId().equals(accountProvider.getAccountId()); - } + if (accountProvider != null && entityFile != null) { + return accountProvider.isValidEntityFile(entityFile); } return true; } diff --git a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/local/LocalEntityFileStorage.java b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/local/LocalEntityFileStorage.java index b72c2b6b..a3d7db36 100644 --- a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/local/LocalEntityFileStorage.java +++ b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/local/LocalEntityFileStorage.java @@ -56,13 +56,12 @@ public class LocalEntityFileStorage implements EntityFileStorage { private final Environment environment; - private final EntityFileService entityFileService; - public LocalEntityFileStorage(Parameters appParams, CrudService crudService, Environment environment, EntityFileService entityFileService) { + public LocalEntityFileStorage(Parameters appParams, CrudService crudService, Environment environment) { this.appParams = appParams; this.crudService = crudService; this.environment = environment; - this.entityFileService = entityFileService; + } @Override @@ -117,7 +116,7 @@ public String generateURL(EntityFile entityFile) { String fileName = entityFile.getName(); fileName = fileName.replace(" ", "%20"); - return serverPath + context + LOCAL_FILE_HANDLER + entityFile.getUuid() + "/" + fileName; + return serverPath + context + LOCAL_FILE_HANDLER + entityFile.getUuid() + "/" + fileName; } private String getContextPath() { diff --git a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/remote/RemoteEntityFileStorage.java b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/remote/BuckieEntityFileStorage.java similarity index 87% rename from extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/remote/RemoteEntityFileStorage.java rename to extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/remote/BuckieEntityFileStorage.java index 3fbd4ab7..d7c1d308 100644 --- a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/remote/RemoteEntityFileStorage.java +++ b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/remote/BuckieEntityFileStorage.java @@ -32,6 +32,7 @@ import tools.dynamia.modules.entityfile.UploadedFileInfo; import tools.dynamia.modules.entityfile.domain.EntityFile; import tools.dynamia.modules.entityfile.domain.enums.EntityFileState; +import tools.dynamia.modules.entityfile.local.LocalEntityFileStorage; import java.io.File; import java.io.Serial; @@ -50,7 +51,7 @@ * * *

Files are served to the browser through the local proxy endpoint - * {@link #PROXY_PATH} so that SFS credentials are never exposed to the client.

+ * * *

The remote file key follows the same convention as {@code LocalEntityFileStorage}: * {@code Account{accountId}/{subfolder}/{storedFileName|uuid}}

@@ -58,16 +59,11 @@ * @author Dynamia Soluciones IT */ @Service -public class RemoteEntityFileStorage implements EntityFileStorage { - - private final LoggingService logger = new SLF4JLoggingService(RemoteEntityFileStorage.class, "SFS: "); +public class BuckieEntityFileStorage implements EntityFileStorage { - public static final String ID = "RemoteSimpleFileStorage"; + private final LoggingService logger = new SLF4JLoggingService(BuckieEntityFileStorage.class, "Buckie: "); - /** - * Base path of the local proxy handler that serves SFS files to the browser. - */ - public static final String PROXY_PATH = "/storage/remote/"; + public static final String ID = "buckie"; // ── Parameter names ────────────────────────────────────────────────────── public static final String SFS_URL = "SFS_URL"; @@ -76,19 +72,21 @@ public class RemoteEntityFileStorage implements EntityFileStorage { public static final String SFS_SECRET = "SFS_SECRET"; // ── Header names ───────────────────────────────────────────────────────── - static final String HEADER_IDENTITY = "X-SFS-Identity"; - static final String HEADER_SECRET = "X-SFS-Secret"; - + static final String HEADER_IDENTITY = "X-Buckie-Identity"; + static final String HEADER_SECRET = "X-Buckie-Secret"; + private final LocalEntityFileStorage localEntityFileStorage; private final Parameters appParams; private final CrudService crudService; private final Environment environment; + /** * Lazily-built RestClient; rebuilt whenever {@link #reloadParams()} is invoked. */ private volatile RestClient restClient; - public RemoteEntityFileStorage(Parameters appParams, CrudService crudService, Environment environment) { + public BuckieEntityFileStorage(LocalEntityFileStorage localEntityFileStorage, Parameters appParams, CrudService crudService, Environment environment) { + this.localEntityFileStorage = localEntityFileStorage; this.appParams = appParams; this.crudService = crudService; this.environment = environment; @@ -103,7 +101,7 @@ public String getId() { @Override public String getName() { - return "Remote Simple File Storage"; + return "Buckie Remote File Storage"; } @Override @@ -134,7 +132,7 @@ public String getFilename() { .uri(uriBuilder -> uriBuilder.replacePath("/" + bucket + "/" + key).build()) .header(HEADER_IDENTITY, getIdentity()) .header(HEADER_SECRET, getSecret()) - // .contentType(org.springframework.http.MediaType.parseMediaType(contentType(fileInfo))) + // .contentType(org.springframework.http.MediaType.parseMediaType(contentType(fileInfo))) .body(resource) .retrieve() .toBodilessEntity(); @@ -152,8 +150,10 @@ public String getFilename() { @Override public StoredEntityFile download(EntityFile entityFile) { - String url = buildRemoteUrl(entityFile); - return new RemoteStoredEntityFile(entityFile, url, client(), getIdentity(), getSecret()); + String remoteUrl = buildRemoteUrl(entityFile); + String publicUrl = localEntityFileStorage.generateURL(entityFile); + + return new BuckieStoredEntityFile(entityFile, remoteUrl, publicUrl, client(), getIdentity(), getSecret()); } @Override @@ -161,7 +161,7 @@ public void delete(EntityFile entityFile) { String key = buildKey(entityFile); String bucket = getBucket(); - logger.info("Deleting from SFS: " + key); + logger.info("Deleting: " + key); try { client().delete() @@ -297,18 +297,24 @@ private static String contentType(UploadedFileInfo fileInfo) { * SFS credentials are included in every download request so the server can * authorise the caller. */ - public static class RemoteStoredEntityFile extends StoredEntityFile { + public static class BuckieStoredEntityFile extends StoredEntityFile { @Serial private static final long serialVersionUID = 1L; + private final LoggingService logger = LoggingService.get(BuckieStoredEntityFile.class, "SFS: "); + + private final transient RestClient restClient; private final String identity; private final String secret; + private final String remoteUrl; - public RemoteStoredEntityFile(EntityFile entityFile, String remoteUrl, + + public BuckieStoredEntityFile(EntityFile entityFile, String remoteUrl, String publicUrl, RestClient restClient, String identity, String secret) { - super(entityFile, remoteUrl, null); + super(entityFile, publicUrl, null); + this.remoteUrl = remoteUrl; this.restClient = restClient; this.identity = identity; this.secret = secret; @@ -329,12 +335,16 @@ public File getThumbnailFile(int width, int height) { @Override public Resource toResource() { - return fetchResource(getUrl()); + return fetchResource(remoteUrl); + } + + public String getRemoteUrl() { + return remoteUrl; } @Override public Resource toThumbnailResource(int width, int height) { - return fetchResource(getThumbnailUrl(width, height)); + return fetchResource(remoteUrl + "?w=" + width + "&h=" + height); } /** @@ -343,6 +353,7 @@ public Resource toThumbnailResource(int width, int height) { */ private Resource fetchResource(String url) { try { + logger.info("Fetching resource from SFS: " + url); return restClient.get() .uri(url) .header(HEADER_IDENTITY, identity) diff --git a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/EntityFileService.java b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/EntityFileService.java index 49941cb2..97681d23 100644 --- a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/EntityFileService.java +++ b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/EntityFileService.java @@ -152,4 +152,6 @@ public interface EntityFileService { EntityFile getEntityFile(String uuid); EntityFileStorage getStorage(String name); + + boolean isForceEntityFileStorage(); } diff --git a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/impl/EntityFileServiceImpl.java b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/impl/EntityFileServiceImpl.java index 60c96d0b..f14077cd 100644 --- a/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/impl/EntityFileServiceImpl.java +++ b/extensions/entity-files/sources/core/src/main/java/tools/dynamia/modules/entityfile/service/impl/EntityFileServiceImpl.java @@ -47,8 +47,8 @@ import tools.dynamia.modules.entityfile.service.EntityFileService; import java.io.File; +import java.io.OutputStream; import java.io.Serializable; -import java.net.URL; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -65,6 +65,7 @@ public class EntityFileServiceImpl implements EntityFileService { private Parameters appParams; private static final String DEFAULT_STORAGE = "DEFAULT_STORAGE_ID"; + private static final String FORCE_STORAGE = "FORCE_STORAGE"; private LoggingService logger = new SLF4JLoggingService(EntityFileService.class); @@ -272,7 +273,7 @@ public void syncEntityFileAware() { @Override public StoredEntityFile download(EntityFile file) { EntityFileStorage storage = null; - if (file.getStorageInfo() != null && !file.getStorageInfo().isEmpty()) { + if (!isForceEntityFileStorage() && file.getStorageInfo() != null && !file.getStorageInfo().isEmpty()) { storage = findStorage(file.getStorageInfo()); } @@ -289,13 +290,30 @@ public void download(EntityFile entityFile, File outputFile) { try { StoredEntityFile storedEntityFile = download(entityFile); if (storedEntityFile != null) { - IOUtils.copy(new URL(storedEntityFile.getUrl()).openStream(), outputFile); + var resource = storedEntityFile.toResource(); + if (resource != null) { + IOUtils.copy(resource.getInputStream(), outputFile); + } } } catch (Exception e) { throw new EntityFileException("Error downloading entity file to local file", e); } } + public void download(EntityFile entityFile, OutputStream outputStream) { + try { + StoredEntityFile storedEntityFile = download(entityFile); + if (storedEntityFile != null) { + var resource = storedEntityFile.toResource(); + if (resource != null) { + IOUtils.copy(resource.getInputStream(), outputStream); + } + } + } catch (Exception e) { + throw new EntityFileException("Error downloading entity file to outputstream", e); + } + } + @Override @Cacheable public EntityFile getEntityFile(String uuid) { @@ -328,8 +346,8 @@ private EntityFileStorage getCurrentStorage() { String storageId = appParams.getValue(DEFAULT_STORAGE, LocalEntityFileStorage.ID); EntityFileStorage storage = findStorage(storageId); if (storage == null) { - throw new EntityFileException("No default " + EntityFileStorage.class - .getSimpleName() + " configured"); + logger.warn("No default " + EntityFileStorage.class.getSimpleName() + " found with id: " + storageId + ". Using local storage."); + return Containers.get().findObject(LocalEntityFileStorage.class); } return storage; } @@ -372,4 +390,10 @@ private void configureEntityFileAccount(EntityFile entityFile) { } } + @Override + public boolean isForceEntityFileStorage() { + String storageId = appParams.getValue(FORCE_STORAGE, "false"); + return "true".equalsIgnoreCase(storageId); + } + } diff --git a/extensions/entity-files/sources/core/src/test/java/tools/dynamia/modules/entityfile/remote/RemoteEntityFileStorageTest.java b/extensions/entity-files/sources/core/src/test/java/tools/dynamia/modules/entityfile/remote/BuckieEntityFileStorageTest.java similarity index 80% rename from extensions/entity-files/sources/core/src/test/java/tools/dynamia/modules/entityfile/remote/RemoteEntityFileStorageTest.java rename to extensions/entity-files/sources/core/src/test/java/tools/dynamia/modules/entityfile/remote/BuckieEntityFileStorageTest.java index da2cc9fc..1ad115ea 100644 --- a/extensions/entity-files/sources/core/src/test/java/tools/dynamia/modules/entityfile/remote/RemoteEntityFileStorageTest.java +++ b/extensions/entity-files/sources/core/src/test/java/tools/dynamia/modules/entityfile/remote/BuckieEntityFileStorageTest.java @@ -31,6 +31,7 @@ import tools.dynamia.modules.entityfile.domain.EntityFile; import tools.dynamia.modules.entityfile.domain.enums.EntityFileState; import tools.dynamia.modules.entityfile.enums.EntityFileType; +import tools.dynamia.modules.entityfile.local.LocalEntityFileStorage; import java.io.ByteArrayInputStream; import java.net.HttpURLConnection; @@ -42,7 +43,7 @@ import static org.junit.Assert.*; /** - * Integration tests for {@link RemoteEntityFileStorage}. + * Integration tests for {@link BuckieEntityFileStorage}. * *

Pure-logic tests (buildKey, getFileName, etc.) always run. * HTTP tests are skipped automatically via {@code Assume.assumeTrue} @@ -58,23 +59,23 @@ * Maven example: {@code mvn test -DSFS_URL=http://my-sfs:8081 -DSFS_BUCKET=test} *

*/ -public class RemoteEntityFileStorageTest { +public class BuckieEntityFileStorageTest { private static String sfsUrl; private static String sfsBucket; private static String sfsIdentity; private static String sfsSecret; - private RemoteEntityFileStorage storage; + private BuckieEntityFileStorage storage; // ── Setup ───────────────────────────────────────────────────────────────── @BeforeClass public static void readConfiguration() { - sfsUrl = systemOrEnv(RemoteEntityFileStorage.SFS_URL, "http://localhost:8500"); - sfsBucket = systemOrEnv(RemoteEntityFileStorage.SFS_BUCKET, "test"); - sfsIdentity = systemOrEnv(RemoteEntityFileStorage.SFS_IDENTITY, "test"); - sfsSecret = systemOrEnv(RemoteEntityFileStorage.SFS_SECRET, "test"); + sfsUrl = systemOrEnv(BuckieEntityFileStorage.SFS_URL, "http://localhost:8500"); + sfsBucket = systemOrEnv(BuckieEntityFileStorage.SFS_BUCKET, "test"); + sfsIdentity = systemOrEnv(BuckieEntityFileStorage.SFS_IDENTITY, "test"); + sfsSecret = systemOrEnv(BuckieEntityFileStorage.SFS_SECRET, "test"); System.out.println("[SFS Test] URL=" + sfsUrl + " | BUCKET=" + sfsBucket); } @@ -82,19 +83,21 @@ public static void readConfiguration() { @Before public void setUp() { MockEnvironment env = new MockEnvironment(); - env.setProperty(RemoteEntityFileStorage.SFS_URL, sfsUrl); - env.setProperty(RemoteEntityFileStorage.SFS_BUCKET, sfsBucket); - env.setProperty(RemoteEntityFileStorage.SFS_IDENTITY, sfsIdentity); - env.setProperty(RemoteEntityFileStorage.SFS_SECRET, sfsSecret); + env.setProperty(BuckieEntityFileStorage.SFS_URL, sfsUrl); + env.setProperty(BuckieEntityFileStorage.SFS_BUCKET, sfsBucket); + env.setProperty(BuckieEntityFileStorage.SFS_IDENTITY, sfsIdentity); + env.setProperty(BuckieEntityFileStorage.SFS_SECRET, sfsSecret); - storage = new RemoteEntityFileStorage(noOpParameters(), new InMemoryCrudService(), env); + var local = new LocalEntityFileStorage(noOpParameters(), new InMemoryCrudService(), env); + + storage = new BuckieEntityFileStorage(local, noOpParameters(), new InMemoryCrudService(), env); } // ── Pure-logic tests (no server required) ───────────────────────────────── @Test public void testGetId() { - assertEquals(RemoteEntityFileStorage.ID, storage.getId()); + assertEquals(BuckieEntityFileStorage.ID, storage.getId()); } @Test @@ -124,17 +127,17 @@ public void testBuildKey_withSubfolder() { @Test public void testGetFileName_withSpacesAndDashes() { EntityFile ef = buildEntityFile("My File-Final.pdf", null, 1L); - String name = RemoteEntityFileStorage.getFileName(ef); + String name = BuckieEntityFileStorage.getFileName(ef); assertFalse("File name must not contain spaces", name.contains(" ")); assertFalse("File name base must not contain dashes", - name.substring(name.lastIndexOf('/') + 1).replace(ef.getUuid(), "").contains("-")); + name.substring(name.lastIndexOf('/') + 1).replace(ef.getUuid(), "").contains("-")); } @Test public void testGetFileName_withAccentsAndSpecialChars() { EntityFile ef = buildEntityFile("Ñoño Ávido Murió.pdf", null, 1L); - String name = RemoteEntityFileStorage.getFileName(ef); + String name = BuckieEntityFileStorage.getFileName(ef); assertFalse("File name must not contain ñ", name.contains("ñ")); assertFalse("File name must not contain á", name.contains("á")); @@ -147,7 +150,7 @@ public void testGetFileName_usesStoredFileNameWhenSet() { EntityFile ef = buildEntityFile("original.pdf", null, 1L); ef.setStoredFileName("custom_stored_name.pdf"); - String name = RemoteEntityFileStorage.getFileName(ef); + String name = BuckieEntityFileStorage.getFileName(ef); assertEquals("Must use storedFileName when it is set", "custom_stored_name.pdf", name); } @@ -155,7 +158,7 @@ public void testGetFileName_usesStoredFileNameWhenSet() { @Test public void testGetFileName_withoutSubfolder() { EntityFile ef = buildEntityFile("doc.txt", null, 1L); - String name = RemoteEntityFileStorage.getFileName(ef); + String name = BuckieEntityFileStorage.getFileName(ef); assertFalse("Without subfolder the name must not start with /", name.startsWith("/")); assertTrue("Name must contain the uuid", name.contains(ef.getUuid())); @@ -163,9 +166,9 @@ public void testGetFileName_withoutSubfolder() { @Test public void testGetAccountFolderName() { - assertEquals("account42/", RemoteEntityFileStorage.getAccountFolderName(42L)); - assertEquals("account1/", RemoteEntityFileStorage.getAccountFolderName(1L)); - assertEquals("account999/", RemoteEntityFileStorage.getAccountFolderName(999L)); + assertEquals("account42/", BuckieEntityFileStorage.getAccountFolderName(42L)); + assertEquals("account1/", BuckieEntityFileStorage.getAccountFolderName(1L)); + assertEquals("account999/", BuckieEntityFileStorage.getAccountFolderName(999L)); } @Test @@ -333,7 +336,7 @@ public void testUploadAndDownloadUrl_areConsistent() { storage.upload(ef, info); StoredEntityFile stored = storage.download(ef); - String url = stored.getUrl(); + String url = stored instanceof BuckieEntityFileStorage.BuckieStoredEntityFile r ? r.getRemoteUrl() : stored.getUrl(); // The URL returned by download() must point to the same resource that was uploaded assertNotNull(url); @@ -398,22 +401,80 @@ private static String systemOrEnv(String key, String defaultValue) { @SuppressWarnings({"rawtypes", "unchecked"}) private static Parameters noOpParameters() { return new Parameters() { - @Override public List getParameters(List n) { return List.of(); } - @Override public List getParameters(Class c, List n) { return List.of(); } - @Override public List all() { return List.of(); } - @Override public Parameter getParameter(String name) { return null; } - @Override public String getValue(String p) { return null; } - @Override public String getValue(Class c, String p) { return null; } - @Override public String getValue(String p, String def) { return def; } - @Override public String getValue(Class c, String p, String def) { return def; } - @Override public void save(Parameter p) {} - @Override public void save(Collection params) {} - @Override public void setParameter(Class c, String n, Object v) {} - @Override public void setParameter(String n, Object v) {} - @Override public Parameter getParameter(Class c, String n) { return null; } - @Override public void increaseCounter(Parameter p) {} - @Override public long findNextCounterValue(Parameter p) { return 0; } - @Override public Parameter findParameter(Class c, String n, QueryParameters f) { return null; } + @Override + public List getParameters(List n) { + return List.of(); + } + + @Override + public List getParameters(Class c, List n) { + return List.of(); + } + + @Override + public List all() { + return List.of(); + } + + @Override + public Parameter getParameter(String name) { + return null; + } + + @Override + public String getValue(String p) { + return null; + } + + @Override + public String getValue(Class c, String p) { + return null; + } + + @Override + public String getValue(String p, String def) { + return def; + } + + @Override + public String getValue(Class c, String p, String def) { + return def; + } + + @Override + public void save(Parameter p) { + } + + @Override + public void save(Collection params) { + } + + @Override + public void setParameter(Class c, String n, Object v) { + } + + @Override + public void setParameter(String n, Object v) { + } + + @Override + public Parameter getParameter(Class c, String n) { + return null; + } + + @Override + public void increaseCounter(Parameter p) { + } + + @Override + public long findNextCounterValue(Parameter p) { + return 0; + } + + @Override + public Parameter findParameter(Class c, String n, QueryParameters f) { + return null; + } }; } } diff --git a/extensions/entity-files/sources/pom.xml b/extensions/entity-files/sources/pom.xml index fbaf0ac6..6de537a4 100644 --- a/extensions/entity-files/sources/pom.xml +++ b/extensions/entity-files/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml diff --git a/extensions/entity-files/sources/s3/pom.xml b/extensions/entity-files/sources/s3/pom.xml index 70f2150f..74313fb3 100644 --- a/extensions/entity-files/sources/s3/pom.xml +++ b/extensions/entity-files/sources/s3/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles.parent - 26.5.1 + 26.5.2 DynamiaModules - EntityFiles - S3 @@ -49,7 +49,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.5.1 + 26.5.2 software.amazon.awssdk diff --git a/extensions/entity-files/sources/s3/src/main/java/tools/dynamia/modules/entityfiles/s3/S3EntityFileStorage.java b/extensions/entity-files/sources/s3/src/main/java/tools/dynamia/modules/entityfiles/s3/S3EntityFileStorage.java index ff626ecc..d0615967 100644 --- a/extensions/entity-files/sources/s3/src/main/java/tools/dynamia/modules/entityfiles/s3/S3EntityFileStorage.java +++ b/extensions/entity-files/sources/s3/src/main/java/tools/dynamia/modules/entityfiles/s3/S3EntityFileStorage.java @@ -45,10 +45,8 @@ import tools.dynamia.modules.entityfile.UploadedFileInfo; import tools.dynamia.modules.entityfile.domain.EntityFile; import tools.dynamia.modules.entityfile.enums.EntityFileType; -import tools.dynamia.modules.entityfile.remote.RemoteEntityFileStorage; import java.io.File; -import java.net.URL; import java.net.URLConnection; import java.nio.file.Files; import java.nio.file.Path; @@ -58,8 +56,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; -import static tools.dynamia.modules.entityfile.remote.RemoteEntityFileStorage.getAccountFolderName; -import static tools.dynamia.modules.entityfile.remote.RemoteEntityFileStorage.getFileName; +import static tools.dynamia.modules.entityfile.remote.BuckieEntityFileStorage.getAccountFolderName; +import static tools.dynamia.modules.entityfile.remote.BuckieEntityFileStorage.getFileName; /** * {@link EntityFileStorage} implementation that store files in Amazon S3 service. diff --git a/extensions/entity-files/sources/ui/pom.xml b/extensions/entity-files/sources/ui/pom.xml index 591e028c..e13f3f70 100644 --- a/extensions/entity-files/sources/ui/pom.xml +++ b/extensions/entity-files/sources/ui/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules.entityfiles.parent tools.dynamia.modules - 26.5.1 + 26.5.2 DynamiaModules - EntityFiles UI tools.dynamia.modules.entityfiles.ui @@ -48,12 +48,12 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 jar diff --git a/extensions/entity-files/sources/ui/src/main/resources/META-INF/descriptors/EntityFileConfig.yml b/extensions/entity-files/sources/ui/src/main/resources/META-INF/descriptors/EntityFileConfig.yml index 23720908..6e2668ba 100644 --- a/extensions/entity-files/sources/ui/src/main/resources/META-INF/descriptors/EntityFileConfig.yml +++ b/extensions/entity-files/sources/ui/src/main/resources/META-INF/descriptors/EntityFileConfig.yml @@ -33,6 +33,13 @@ fields: params: parameterName: LOCAL_USE_HTTPS cacheable: true + forceStorage: + label: Force Use of Selected Storage + component: checkbox + params: + parameterName: FORCE_STORAGE + cacheable: true + s3BucketName: label: Bucket Name diff --git a/extensions/file-importer/sources/core/pom.xml b/extensions/file-importer/sources/core/pom.xml index b4a41bbc..feccb829 100644 --- a/extensions/file-importer/sources/core/pom.xml +++ b/extensions/file-importer/sources/core/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules.importer.parent tools.dynamia.modules - 26.5.1 + 26.5.2 Dynamia Modules - Importer Core tools.dynamia.modules.importer @@ -56,7 +56,7 @@ tools.dynamia tools.dynamia.reports - 26.5.1 + 26.5.2 diff --git a/extensions/file-importer/sources/pom.xml b/extensions/file-importer/sources/pom.xml index 78f20784..6797f1b8 100644 --- a/extensions/file-importer/sources/pom.xml +++ b/extensions/file-importer/sources/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml diff --git a/extensions/file-importer/sources/ui/pom.xml b/extensions/file-importer/sources/ui/pom.xml index e81924bc..e36976cd 100644 --- a/extensions/file-importer/sources/ui/pom.xml +++ b/extensions/file-importer/sources/ui/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules.importer.parent tools.dynamia.modules - 26.5.1 + 26.5.2 Dynamia Modules - Importer UI tools.dynamia.modules.importer.ui @@ -55,13 +55,13 @@ tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.importer - 26.5.1 + 26.5.2 diff --git a/extensions/finances/sources/api/pom.xml b/extensions/finances/sources/api/pom.xml index a7045f82..03571d28 100644 --- a/extensions/finances/sources/api/pom.xml +++ b/extensions/finances/sources/api/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.finances.parent - 26.5.1 + 26.5.2 Dynamia Modules - Finances API diff --git a/extensions/finances/sources/pom.xml b/extensions/finances/sources/pom.xml index d9732afd..bdbf1d5b 100644 --- a/extensions/finances/sources/pom.xml +++ b/extensions/finances/sources/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml diff --git a/extensions/pom.xml b/extensions/pom.xml index 30f3b600..21b2dea3 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -6,7 +6,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../pom.xml diff --git a/extensions/reports/packages/reports-sdk/package.json b/extensions/reports/packages/reports-sdk/package.json index 018618f9..3ca57297 100644 --- a/extensions/reports/packages/reports-sdk/package.json +++ b/extensions/reports/packages/reports-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/reports-sdk", - "version": "26.5.1", + "version": "26.5.2", "website": "https://dynamia.tools", "description": "TypeScript/JavaScript client SDK for the Dynamia Reports extension REST API", "keywords": [ @@ -63,11 +63,14 @@ }, "devDependencies": { "@dynamia-tools/sdk": "workspace:*", - "@types/node": "^22.0.0", + "@types/node": "^24.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", - "vitest": "^3.0.0", - "@vitest/coverage-v8": "^3.0.0" + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", + "vitest": "^4.0.0", + "@vitest/coverage-v8": "^4.0.0" + }, + "engines": { + "node": ">=24" } } diff --git a/extensions/reports/sources/api/pom.xml b/extensions/reports/sources/api/pom.xml index eee7d154..6cc844c6 100644 --- a/extensions/reports/sources/api/pom.xml +++ b/extensions/reports/sources/api/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.reports.parent - 26.5.1 + 26.5.2 DynamiaModules - Reports API diff --git a/extensions/reports/sources/core/pom.xml b/extensions/reports/sources/core/pom.xml index a2aa883e..31961eed 100644 --- a/extensions/reports/sources/core/pom.xml +++ b/extensions/reports/sources/core/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.reports.parent - 26.5.1 + 26.5.2 DynamiaModules - Reports Core @@ -50,17 +50,17 @@ tools.dynamia.modules tools.dynamia.modules.reports.api - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.5.1 + 26.5.2 org.springframework @@ -69,12 +69,12 @@ tools.dynamia tools.dynamia.reports - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.templates - 26.5.1 + 26.5.2 compile diff --git a/extensions/reports/sources/pom.xml b/extensions/reports/sources/pom.xml index 27d2af56..595fd927 100644 --- a/extensions/reports/sources/pom.xml +++ b/extensions/reports/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml diff --git a/extensions/reports/sources/ui/pom.xml b/extensions/reports/sources/ui/pom.xml index 62cc73ac..2faed0a6 100644 --- a/extensions/reports/sources/ui/pom.xml +++ b/extensions/reports/sources/ui/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.reports.parent - 26.5.1 + 26.5.2 DynamiaModules - Reports UI @@ -49,17 +49,17 @@ tools.dynamia.modules tools.dynamia.modules.reports.core - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.dashboard - 26.5.1 + 26.5.2 io.swagger.core.v3 diff --git a/extensions/saas/packages/saas-sdk/package.json b/extensions/saas/packages/saas-sdk/package.json index 69eac2ab..bae84fd8 100644 --- a/extensions/saas/packages/saas-sdk/package.json +++ b/extensions/saas/packages/saas-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/saas-sdk", - "version": "26.5.1", + "version": "26.5.2", "website": "https://dynamia.tools", "description": "TypeScript/JavaScript client SDK for the Dynamia SaaS extension REST API", "keywords": [ @@ -64,11 +64,14 @@ }, "devDependencies": { "@dynamia-tools/sdk": "workspace:*", - "@types/node": "^22.0.0", + "@types/node": "^24.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", - "vitest": "^3.0.0", - "@vitest/coverage-v8": "^3.0.0" + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", + "vitest": "^4.0.0", + "@vitest/coverage-v8": "^4.0.0" + }, + "engines": { + "node": ">=24" } } diff --git a/extensions/saas/sources/api/pom.xml b/extensions/saas/sources/api/pom.xml index 7c5999b9..03aa57f4 100644 --- a/extensions/saas/sources/api/pom.xml +++ b/extensions/saas/sources/api/pom.xml @@ -26,7 +26,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.parent - 26.5.1 + 26.5.2 @@ -55,7 +55,7 @@ tools.dynamia tools.dynamia.actions - 26.5.1 + 26.5.2 org.springframework.boot diff --git a/extensions/saas/sources/core/pom.xml b/extensions/saas/sources/core/pom.xml index e7514fbf..7bd6e07b 100644 --- a/extensions/saas/sources/core/pom.xml +++ b/extensions/saas/sources/core/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.parent - 26.5.1 + 26.5.2 DynamiaModules - SaaS Core @@ -49,18 +49,18 @@ tools.dynamia.modules tools.dynamia.modules.saas.api - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 @@ -86,7 +86,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.5.1 + 26.5.2 org.hibernate.orm diff --git a/extensions/saas/sources/core/src/main/java/tools/dynamia/modules/saas/AccountEntityFileProvider.java b/extensions/saas/sources/core/src/main/java/tools/dynamia/modules/saas/AccountEntityFileProvider.java deleted file mode 100644 index 0d41ed53..00000000 --- a/extensions/saas/sources/core/src/main/java/tools/dynamia/modules/saas/AccountEntityFileProvider.java +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (C) 2023 Dynamia Soluciones IT S.A.S - NIT 900302344-1 - * Colombia / South America - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package tools.dynamia.modules.saas; - -import org.springframework.beans.factory.annotation.Autowired; -import tools.dynamia.integration.sterotypes.Provider; -import tools.dynamia.modules.entityfile.EntityFileAccountProvider; -import tools.dynamia.modules.saas.api.AccountServiceAPI; - -/** - * - * @author Mario Serrano Leones - */ -@Provider -public class AccountEntityFileProvider implements EntityFileAccountProvider { - - - private final AccountServiceAPI accountServiceAPI; - - public AccountEntityFileProvider(AccountServiceAPI accountServiceAPI) { - this.accountServiceAPI = accountServiceAPI; - } - - @Override - public Long getAccountId() { - return accountServiceAPI.getCurrentAccountId(); - } - -} diff --git a/extensions/saas/sources/jpa/pom.xml b/extensions/saas/sources/jpa/pom.xml index 76995d51..125b2da0 100644 --- a/extensions/saas/sources/jpa/pom.xml +++ b/extensions/saas/sources/jpa/pom.xml @@ -24,7 +24,7 @@ tools.dynamia.modules.saas.parent tools.dynamia.modules - 26.5.1 + 26.5.2 DynamiaModules - SaaS JPA @@ -35,12 +35,12 @@ tools.dynamia.modules tools.dynamia.modules.saas.api - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 diff --git a/extensions/saas/sources/pom.xml b/extensions/saas/sources/pom.xml index 08e93708..6e29a7d9 100644 --- a/extensions/saas/sources/pom.xml +++ b/extensions/saas/sources/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml diff --git a/extensions/saas/sources/remote/pom.xml b/extensions/saas/sources/remote/pom.xml index 2ce77ef9..123cead2 100644 --- a/extensions/saas/sources/remote/pom.xml +++ b/extensions/saas/sources/remote/pom.xml @@ -25,7 +25,7 @@ tools.dynamia.modules.saas.parent tools.dynamia.modules - 26.5.1 + 26.5.2 @@ -38,7 +38,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.jpa - 26.5.1 + 26.5.2 diff --git a/extensions/saas/sources/ui/pom.xml b/extensions/saas/sources/ui/pom.xml index e36b95ad..5f18074e 100644 --- a/extensions/saas/sources/ui/pom.xml +++ b/extensions/saas/sources/ui/pom.xml @@ -22,7 +22,7 @@ tools.dynamia.modules tools.dynamia.modules.saas.parent - 26.5.1 + 26.5.2 DynamiaModules - SaaS UI tools.dynamia.modules.saas.ui @@ -54,12 +54,12 @@ tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.saas - 26.5.1 + 26.5.2 @@ -70,7 +70,7 @@ tools.dynamia.modules tools.dynamia.modules.entityfiles.ui - 26.5.1 + 26.5.2 diff --git a/extensions/security/sources/core/pom.xml b/extensions/security/sources/core/pom.xml index cd0f6bf8..1fad2973 100644 --- a/extensions/security/sources/core/pom.xml +++ b/extensions/security/sources/core/pom.xml @@ -17,7 +17,7 @@ tools.dynamia.modules tools.dynamia.modules.security.parent - 26.5.1 + 26.5.2 4.0.0 @@ -32,34 +32,34 @@ tools.dynamia.modules tools.dynamia.modules.saas.api - 26.5.1 + 26.5.2 tools.dynamia.modules tools.dynamia.modules.entityfiles - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.web - 26.5.1 + 26.5.2 diff --git a/extensions/security/sources/pom.xml b/extensions/security/sources/pom.xml index d7d4d643..c1099cc1 100644 --- a/extensions/security/sources/pom.xml +++ b/extensions/security/sources/pom.xml @@ -19,7 +19,7 @@ tools.dynamia.modules tools.dynamia.modules.parent - 26.5.1 + 26.5.2 ../../pom.xml diff --git a/extensions/security/sources/ui/pom.xml b/extensions/security/sources/ui/pom.xml index bdb98f91..97aaa34b 100644 --- a/extensions/security/sources/ui/pom.xml +++ b/extensions/security/sources/ui/pom.xml @@ -17,7 +17,7 @@ tools.dynamia.modules tools.dynamia.modules.security.parent - 26.5.1 + 26.5.2 DynamiaModules - Security UI @@ -44,18 +44,18 @@ tools.dynamia.modules tools.dynamia.modules.security - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.app - 26.5.1 + 26.5.2 diff --git a/package.json b/package.json index 716b5cfb..81281796 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/workspace", - "version": "26.4.1", + "version": "26.5.1", "private": true, "author": "Mario Serrano", "repository": "https://github.com/dynamiatools/framework", @@ -15,20 +15,19 @@ "publish:all": "pnpm -r publish --access public --no-git-checks" }, "devDependencies": { - "@types/node": "^22.0.0", + "@types/node": "^24.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", - "vitest": "^3.0.0", - "@vitest/coverage-v8": "^3.0.0", + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", + "vitest": "^4.0.0", + "@vitest/coverage-v8": "^4.0.0", "eslint": "^9.0.0", "prettier": "^3.5.0" }, "engines": { - "node": ">=20", - "pnpm": ">=9" + "node": ">=24", + "pnpm": ">=11" }, - "packageManager": "pnpm@10.31.0", + "packageManager": "pnpm@11.1.3", "license": "Apache-2.0" } - diff --git a/platform/app/pom.xml b/platform/app/pom.xml index 8e183829..6be5dcaa 100644 --- a/platform/app/pom.xml +++ b/platform/app/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../pom.xml @@ -74,58 +74,58 @@ tools.dynamia tools.dynamia.actions - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.crud - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.io - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.navigation - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.reports - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.templates - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.viewers - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.web - 26.5.1 + 26.5.2 @@ -205,7 +205,7 @@ tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 test diff --git a/platform/core/actions/pom.xml b/platform/core/actions/pom.xml index 8041cd90..79ade5d9 100644 --- a/platform/core/actions/pom.xml +++ b/platform/core/actions/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -65,12 +65,12 @@ tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 diff --git a/platform/core/commons/pom.xml b/platform/core/commons/pom.xml index 8370e989..02c855b6 100644 --- a/platform/core/commons/pom.xml +++ b/platform/core/commons/pom.xml @@ -25,7 +25,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml DynamiaTools - Commons diff --git a/platform/core/crud/pom.xml b/platform/core/crud/pom.xml index 8e6ae8df..fb230208 100644 --- a/platform/core/crud/pom.xml +++ b/platform/core/crud/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -62,23 +62,23 @@ tools.dynamia tools.dynamia.actions - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.viewers - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.navigation - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 test diff --git a/platform/core/domain-jpa/pom.xml b/platform/core/domain-jpa/pom.xml index 57298ba7..5036758e 100644 --- a/platform/core/domain-jpa/pom.xml +++ b/platform/core/domain-jpa/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -65,7 +65,7 @@ tools.dynamia tools.dynamia.domain - 26.5.1 + 26.5.2 diff --git a/platform/core/domain/pom.xml b/platform/core/domain/pom.xml index 8115135b..a71341d3 100644 --- a/platform/core/domain/pom.xml +++ b/platform/core/domain/pom.xml @@ -26,7 +26,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml DynamiaTools - Domain diff --git a/platform/core/integration/pom.xml b/platform/core/integration/pom.xml index bcf4eb6a..0cf7a378 100644 --- a/platform/core/integration/pom.xml +++ b/platform/core/integration/pom.xml @@ -27,7 +27,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -67,7 +67,7 @@ tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 provided diff --git a/platform/core/io/pom.xml b/platform/core/io/pom.xml index aa2f457d..d6cc7c76 100644 --- a/platform/core/io/pom.xml +++ b/platform/core/io/pom.xml @@ -28,7 +28,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml diff --git a/platform/core/io/src/main/java/tools/dynamia/io/IOUtils.java b/platform/core/io/src/main/java/tools/dynamia/io/IOUtils.java index 77884cb5..86cd716f 100644 --- a/platform/core/io/src/main/java/tools/dynamia/io/IOUtils.java +++ b/platform/core/io/src/main/java/tools/dynamia/io/IOUtils.java @@ -26,18 +26,17 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.Base64; import java.util.Collection; +import java.util.Comparator; import java.util.List; import java.util.Objects; import java.util.zip.ZipEntry; @@ -65,6 +64,10 @@ */ public abstract class IOUtils { + private static final long KB = 1024L; + private static final long MB = KB * 1024L; + private static final long GB = MB * 1024L; + /** * The default resource locator. */ @@ -91,19 +94,16 @@ private IOUtils() { * @return the located Resource, or null if not found */ public static Resource getResource(String location) { - Resource resource = null; + Objects.requireNonNull(location, "location cannot be null"); Collection locators = Containers.get().findObjects(ResourceLocator.class); if (locators != null && !locators.isEmpty()) { - for (ResourceLocator resourceLocator : locators) { - resource = resourceLocator.getResource(location); - if (resource != null) { - break; - } - } - } else { - resource = DEFAULT_RESOURCE_LOCATOR.getResource(location); + return locators.stream() + .map(rl -> rl.getResource(location)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); } - return resource; + return DEFAULT_RESOURCE_LOCATOR.getResource(location); } /** @@ -115,21 +115,18 @@ public static Resource getResource(String location) { * @throws IOException if an I/O error occurs */ public static Resource[] getResources(String location) throws IOException { - Resource[] results = new Resource[0]; + Objects.requireNonNull(location, "location cannot be null"); Collection locators = Containers.get().findObjects(ResourceLocator.class); if (locators != null && !locators.isEmpty()) { for (ResourceLocator resourceLocator : locators) { Resource[] resources = resourceLocator.getResources(location); if (resources != null) { - results = resources; - break; + return resources; } } - } else { - results = DEFAULT_RESOURCE_LOCATOR.getResources(location); + return new Resource[0]; } - - return results; + return DEFAULT_RESOURCE_LOCATOR.getResources(location); } /** @@ -140,8 +137,15 @@ public static Resource[] getResources(String location) throws IOException { * @return the File object, or null if not found or error */ public static File createFromClasspath(final String path) { + if (path == null) { + return null; + } try { - return new File(IOUtils.class.getResource(path).toURI()); + URL url = IOUtils.class.getResource(path); + if (url == null) { + return null; + } + return new File(url.toURI()); } catch (URISyntaxException ex) { return null; } @@ -155,9 +159,11 @@ public static File createFromClasspath(final String path) { * @throws IOException if an I/O error occurs during serialization */ public static byte[] serializeToBytes(Serializable obj) throws IOException { + Objects.requireNonNull(obj, "obj cannot be null"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(obj); + try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { + oos.writeObject(obj); + } return baos.toByteArray(); } @@ -170,9 +176,10 @@ public static byte[] serializeToBytes(Serializable obj) throws IOException { * @throws ClassNotFoundException if the class of the object cannot be found */ public static Serializable deserializeFromBytes(byte[] data) throws IOException, ClassNotFoundException { - ByteArrayInputStream bais = new ByteArrayInputStream(data); - ObjectInputStream ois = new ObjectInputStream(bais); - return (Serializable) ois.readObject(); + Objects.requireNonNull(data, "data cannot be null"); + try (ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data))) { + return (Serializable) ois.readObject(); + } } /** @@ -183,12 +190,10 @@ public static Serializable deserializeFromBytes(byte[] data) throws IOException, * @throws IOException if an I/O error occurs */ public static String readContent(String path) throws IOException { - InputStream in = IOUtils.class.getResourceAsStream(path); - if (in == null) { - in = new FileInputStream(path); + Objects.requireNonNull(path, "path cannot be null"); + try (InputStream in = openInputStream(path)) { + return readContent(in, Charset.defaultCharset()); } - - return readContent(in, Charset.defaultCharset()); } /** @@ -200,12 +205,11 @@ public static String readContent(String path) throws IOException { * @throws IOException if an I/O error occurs */ public static String readContent(String path, String charset) throws IOException { - InputStream in = IOUtils.class.getResourceAsStream(path); - if (in == null) { - in = new FileInputStream(path); + Objects.requireNonNull(path, "path cannot be null"); + Objects.requireNonNull(charset, "charset cannot be null"); + try (InputStream in = openInputStream(path)) { + return readContent(in, Charset.forName(charset)); } - - return readContent(in, Charset.forName(charset)); } /** @@ -217,45 +221,29 @@ public static String readContent(String path, String charset) throws IOException * @throws IOException if an I/O error occurs */ public static String readContent(InputStream inputStream, Charset charset) throws IOException { + Objects.requireNonNull(inputStream, "inputStream cannot be null"); + Objects.requireNonNull(charset, "charset cannot be null"); StringBuilder content = new StringBuilder(); try (BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, charset))) { - String line = null; + String line; while ((line = br.readLine()) != null) { content.append(line); } } - return content.toString(); } /** - * Copies data from an InputStream to an OutputStream using NIO channels for fast transfer. + * Copies data from an InputStream to an OutputStream. * * @param streamIn the source InputStream * @param streamOut the destination OutputStream * @throws IOException if an I/O error occurs */ public static void copy(InputStream streamIn, OutputStream streamOut) throws IOException { - ReadableByteChannel src = Channels.newChannel(streamIn); - WritableByteChannel dest = Channels.newChannel(streamOut); - final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); - - while (src.read(buffer) != -1) { - // prepare the buffer to be drained - buffer.flip(); - // write to the channel, may block - dest.write(buffer); - // If partial transfer, shift remainder down - // If buffer is empty, same as doing clear() - buffer.compact(); - } - // EOF will leave buffer in fill state - buffer.flip(); - // make sure the buffer is fully drained. - while (buffer.hasRemaining()) { - dest.write(buffer); - } - + Objects.requireNonNull(streamIn, "streamIn cannot be null"); + Objects.requireNonNull(streamOut, "streamOut cannot be null"); + streamIn.transferTo(streamOut); } /** @@ -266,7 +254,11 @@ public static void copy(InputStream streamIn, OutputStream streamOut) throws IOE * @throws IOException if an I/O error occurs */ public static void copy(InputStream streamIn, File fileOut) throws IOException { - copy(streamIn, new FileOutputStream(fileOut)); + Objects.requireNonNull(streamIn, "streamIn cannot be null"); + Objects.requireNonNull(fileOut, "fileOut cannot be null"); + try (FileOutputStream fos = new FileOutputStream(fileOut)) { + streamIn.transferTo(fos); + } } /** @@ -277,10 +269,9 @@ public static void copy(InputStream streamIn, File fileOut) throws IOException { * @throws IOException if an I/O error occurs */ public static void copy(File fileIn, File fileOut) throws IOException { - FileInputStream fis = new FileInputStream(fileIn); - FileOutputStream fos = new FileOutputStream(fileOut); - copy(fis, fos); - + Objects.requireNonNull(fileIn, "fileIn cannot be null"); + Objects.requireNonNull(fileOut, "fileOut cannot be null"); + Files.copy(fileIn.toPath(), fileOut.toPath(), StandardCopyOption.REPLACE_EXISTING); } /** @@ -291,10 +282,11 @@ public static void copy(File fileIn, File fileOut) throws IOException { * @throws IOException if an I/O error occurs */ public static void copy(byte[] bytes, File fileOut) throws IOException { - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - FileOutputStream fos = new FileOutputStream(fileOut); - copy(bais, fos); - + Objects.requireNonNull(bytes, "bytes cannot be null"); + Objects.requireNonNull(fileOut, "fileOut cannot be null"); + try (FileOutputStream fos = new FileOutputStream(fileOut)) { + fos.write(bytes); + } } /** @@ -305,8 +297,9 @@ public static void copy(byte[] bytes, File fileOut) throws IOException { * @throws IOException if an I/O error occurs */ public static void copy(byte[] bytes, OutputStream streamOut) throws IOException { - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - copy(bais, streamOut); + Objects.requireNonNull(bytes, "bytes cannot be null"); + Objects.requireNonNull(streamOut, "streamOut cannot be null"); + streamOut.write(bytes); } /** @@ -317,19 +310,12 @@ public static void copy(byte[] bytes, OutputStream streamOut) throws IOException */ public static String formatFileSize(long length) { DecimalFormat f = new DecimalFormat("###,###.#"); - if (length > 1024) { - double kb = (double) length / 1024; - if (kb > 1024) { - double mb = kb / 1024; - if (mb > 1024) { - double gb = mb / 1024; - return f.format(gb) + " GB"; - } else { - return f.format(mb) + " MB"; - } - } else { - return f.format(kb) + " KB"; - } + if (length >= GB) { + return f.format((double) length / GB) + " GB"; + } else if (length >= MB) { + return f.format((double) length / MB) + " MB"; + } else if (length >= KB) { + return f.format((double) length / KB) + " KB"; } else { return length + " B"; } @@ -342,24 +328,23 @@ public static String formatFileSize(long length) { * @return the file name without extension */ public static String getFileNameWithoutExtension(File file) { + Objects.requireNonNull(file, "file cannot be null"); String name = file.getName(); - if (name.contains(".")) { - return name.substring(0, name.lastIndexOf(".")); - } else { - return name; - } - + int dotIndex = name.lastIndexOf('.'); + return (dotIndex != -1) ? name.substring(0, dotIndex) : name; } /** * Gets the file extension from a File object. * * @param file the File object - * @return the file extension (without dot) + * @return the file extension (without dot), or empty string if no extension */ public static String getFileExtension(File file) { + Objects.requireNonNull(file, "file cannot be null"); String name = file.getName(); - return name.substring(name.lastIndexOf(".") + 1); + int dotIndex = name.lastIndexOf('.'); + return (dotIndex != -1) ? name.substring(dotIndex + 1) : ""; } /** @@ -370,43 +355,47 @@ public static String getFileExtension(File file) { * @return the matching FileInfo, or null if not found */ public static FileInfo find(String name, List fileList) { - for (FileInfo fileInfo : fileList) { - if (fileInfo.getName().equals(name)) { - return fileInfo; - } + if (fileList == null || fileList.isEmpty() || name == null) { + return null; } - return null; + return fileList.stream() + .filter(f -> f != null && name.equals(f.getName())) + .findFirst() + .orElse(null); } /** * Unzips a specific zip file into the given output folder. + * Protected against Zip Slip path traversal attacks. * * @param zipFile the zip file to unzip * @param outputfolder the output directory - * @throws IOException if an I/O error occurs + * @throws IOException if an I/O error occurs or a Zip Slip attack is detected */ public static void unzipFile(File zipFile, File outputfolder) throws IOException { - byte[] buffer = new byte[1024]; + Objects.requireNonNull(zipFile, "zipFile cannot be null"); + Objects.requireNonNull(outputfolder, "outputfolder cannot be null"); + final byte[] buffer = new byte[8 * 1024]; + final String canonicalOutput = outputfolder.getCanonicalPath() + File.separator; - // create output directory is not exists if (!outputfolder.exists()) { - outputfolder.mkdir(); + outputfolder.mkdirs(); } - // get the zipped file list entry - try ( // get the zip file content - ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { - // get the zipped file list entry - ZipEntry ze = zis.getNextEntry(); - while (ze != null) { - String fileName = ze.getName(); - File newFile = new File(outputfolder, fileName); - // create all non exists folders - // else you will hit FileNotFoundException for compressed folder + try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile))) { + ZipEntry ze; + while ((ze = zis.getNextEntry()) != null) { + File newFile = new File(outputfolder, ze.getName()); + + // Zip Slip protection + if (!newFile.getCanonicalPath().startsWith(canonicalOutput)) { + throw new IOException("Zip Slip attack detected: " + ze.getName()); + } + if (ze.isDirectory()) { newFile.mkdirs(); } else { - new File(newFile.getParent()).mkdirs(); + newFile.getParentFile().mkdirs(); try (FileOutputStream fos = new FileOutputStream(newFile)) { int len; while ((len = zis.read(buffer)) > 0) { @@ -414,9 +403,8 @@ public static void unzipFile(File zipFile, File outputfolder) throws IOException } } } - ze = zis.getNextEntry(); + zis.closeEntry(); } - zis.closeEntry(); } } @@ -460,22 +448,21 @@ public static File getUserDirectory() { * Deletes a directory recursively, including all its files and subdirectories. * * @param directory the directory to delete - * @return true if the directory was deleted, false otherwise + * @return true if the directory was deleted successfully, false otherwise */ public static boolean deleteDirectory(File directory) { - if (directory.exists()) { - File[] files = directory.listFiles(); - if (null != files) { - for (File file : files) { - if (file.isDirectory()) { - deleteDirectory(file); - } else { - file.delete(); - } - } - } + if (directory == null || !directory.exists()) { + return false; + } + try (var paths = Files.walk(directory.toPath())) { + paths.sorted(Comparator.reverseOrder()) + .map(Path::toFile) + .forEach(File::delete); + return !directory.exists(); + } catch (IOException e) { + LOGGER.error("Error deleting directory: " + directory, e); + return false; } - return (directory.delete()); } /** @@ -488,19 +475,17 @@ public static boolean deleteDirectory(File directory) { * @throws Exception if an error occurs */ public static Path downloadFile(String baseURL, final String fileURI, final String localFolder) throws Exception { - if (baseURL == null || baseURL.isEmpty()) { - LOGGER.info("-No base URL to download file: " + fileURI); + LOGGER.info("-No base URL to download file: " + fileURI); + return null; + } + if (localFolder == null || localFolder.isEmpty()) { + LOGGER.info("-No local folder specified to download file: " + fileURI); return null; } if (fileURI != null && !fileURI.isEmpty()) { - - String separator = "/"; - if (baseURL.endsWith("/")) { - separator = ""; - } - + String separator = baseURL.endsWith("/") ? "" : "/"; final URL url = URI.create(baseURL + separator + fileURI).toURL(); final Path folder = Paths.get(localFolder); final Path localFile = folder.resolve(fileURI); @@ -549,7 +534,9 @@ public static Path downloadFile(URL url, Path destPath) throws IOException { * @throws IOException if an I/O error occurs */ public static List downloadFiles(List urls, Path destPath) throws IOException { - List downloadedFiles = new java.util.ArrayList<>(); + Objects.requireNonNull(urls, "urls cannot be null"); + Objects.requireNonNull(destPath, "destPath cannot be null"); + List downloadedFiles = new ArrayList<>(urls.size()); if (Files.notExists(destPath)) { Files.createDirectories(destPath); @@ -573,6 +560,7 @@ public static List downloadFiles(List urls, Path destPath) throws IOE * @throws IOException if an I/O error occurs */ public static String encodeBase64(File file) throws IOException { + Objects.requireNonNull(file, "file cannot be null"); return Base64.getEncoder().encodeToString(Files.readAllBytes(file.toPath())); } @@ -584,8 +572,10 @@ public static String encodeBase64(File file) throws IOException { * @throws IOException if an I/O error occurs */ public static void decodeBase64(String base64, File outputFile) throws IOException { + Objects.requireNonNull(base64, "base64 cannot be null"); + Objects.requireNonNull(outputFile, "outputFile cannot be null"); + byte[] data = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.US_ASCII)); try (FileOutputStream outputStream = new FileOutputStream(outputFile)) { - byte[] data = Base64.getDecoder().decode(base64.getBytes()); outputStream.write(data); } } @@ -608,7 +598,8 @@ public static long getFileSize(File file) { */ public static List listFiles(File directory) { if (directory != null && directory.isDirectory()) { - return List.of(Objects.requireNonNull(directory.listFiles(File::isFile))); + File[] files = directory.listFiles(File::isFile); + return (files != null) ? List.of(files) : List.of(); } return List.of(); } @@ -617,11 +608,12 @@ public static List listFiles(File directory) { * Lists all directories in a given directory. * * @param directory the directory to list subdirectories from - * @return an list of Files representing directories, or empty list if none + * @return a list of Files representing directories, or empty list if none */ public static List listDirectories(File directory) { if (directory != null && directory.isDirectory()) { - return List.of(Objects.requireNonNull(directory.listFiles(File::isDirectory))); + File[] dirs = directory.listFiles(File::isDirectory); + return (dirs != null) ? List.of(dirs) : List.of(); } return List.of(); } @@ -697,4 +689,17 @@ public static Path getAbsolutePath(File file) { return (file != null) ? file.toPath().toAbsolutePath() : null; } + // ------------------------------------------------------------------------- + // Private helpers + // ------------------------------------------------------------------------- + + /** + * Opens an InputStream for the given path, first trying the classpath, + * then the file system. + */ + private static InputStream openInputStream(String path) throws FileNotFoundException { + Objects.requireNonNull(path, "path cannot be null"); + InputStream in = IOUtils.class.getResourceAsStream(path); + return (in != null) ? in : new FileInputStream(path); + } } diff --git a/platform/core/navigation/pom.xml b/platform/core/navigation/pom.xml index 66a84341..d1ba11b5 100644 --- a/platform/core/navigation/pom.xml +++ b/platform/core/navigation/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -63,17 +63,17 @@ tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.actions - 26.5.1 + 26.5.2 diff --git a/platform/core/reports/pom.xml b/platform/core/reports/pom.xml index 5a0a154d..6136ff73 100644 --- a/platform/core/reports/pom.xml +++ b/platform/core/reports/pom.xml @@ -26,7 +26,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml diff --git a/platform/core/templates/pom.xml b/platform/core/templates/pom.xml index d3ccd570..9dd76020 100644 --- a/platform/core/templates/pom.xml +++ b/platform/core/templates/pom.xml @@ -23,7 +23,7 @@ tools.dynamia.parent tools.dynamia - 26.5.1 + 26.5.2 ../../../pom.xml @@ -64,12 +64,12 @@ tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 diff --git a/platform/core/viewers/pom.xml b/platform/core/viewers/pom.xml index 542546d9..de976614 100644 --- a/platform/core/viewers/pom.xml +++ b/platform/core/viewers/pom.xml @@ -25,7 +25,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -67,27 +67,27 @@ tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.io - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.actions - 26.5.1 + 26.5.2 org.yaml diff --git a/platform/core/web/pom.xml b/platform/core/web/pom.xml index 93a4f5db..52499b7a 100644 --- a/platform/core/web/pom.xml +++ b/platform/core/web/pom.xml @@ -29,7 +29,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -88,27 +88,27 @@ tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.navigation - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.viewers - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.crud - 26.5.1 + 26.5.2 org.springframework diff --git a/platform/packages/cli/package-lock.json b/platform/packages/cli/package-lock.json index bed6e67d..90c342e0 100644 --- a/platform/packages/cli/package-lock.json +++ b/platform/packages/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dynamia-tools/cli", - "version": "26.5.1", + "version": "26.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dynamia-tools/cli", - "version": "26.5.1", + "version": "26.5.2", "license": "Apache-2.0", "dependencies": { "@inquirer/prompts": "^7.0.0", diff --git a/platform/packages/cli/package.json b/platform/packages/cli/package.json index 69f1aaeb..a95b557b 100644 --- a/platform/packages/cli/package.json +++ b/platform/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/cli", - "version": "26.5.1", + "version": "26.5.2", "description": "Dynamia Tools CLI — Scaffold new Dynamia Platform projects", "keywords": [ "dynamia", diff --git a/platform/packages/cli/tsconfig.json b/platform/packages/cli/tsconfig.json index 4174b878..c08b1101 100644 --- a/platform/packages/cli/tsconfig.json +++ b/platform/packages/cli/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2022", + "target": "ES2023", "module": "NodeNext", "moduleResolution": "NodeNext", "outDir": "dist", diff --git a/platform/packages/sdk/package-lock.json b/platform/packages/sdk/package-lock.json index d69bb72a..55c2ba2f 100644 --- a/platform/packages/sdk/package-lock.json +++ b/platform/packages/sdk/package-lock.json @@ -1,12 +1,12 @@ { "name": "@dynamia-tools/sdk", - "version": "26.5.1", + "version": "26.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@dynamia-tools/sdk", - "version": "26.5.1", + "version": "26.5.2", "license": "Apache-2.0", "devDependencies": { "@types/node": "^22.0.0", diff --git a/platform/packages/sdk/package.json b/platform/packages/sdk/package.json index a8a6b575..21b395eb 100644 --- a/platform/packages/sdk/package.json +++ b/platform/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/sdk", - "version": "26.5.1", + "version": "26.5.2", "website": "https://dynamia.tools", "description": "Official JavaScript / TypeScript client SDK for Dynamia Platform REST APIs", "keywords": [ @@ -59,11 +59,14 @@ "registry": "https://registry.npmjs.org/" }, "devDependencies": { - "@types/node": "^22.0.0", + "@types/node": "^24.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", - "vitest": "^3.0.0", - "@vitest/coverage-v8": "^3.0.0" + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", + "vitest": "^4.0.0", + "@vitest/coverage-v8": "^4.0.0" + }, + "engines": { + "node": ">=24" } } diff --git a/platform/packages/ui-core/package.json b/platform/packages/ui-core/package.json index e6897e0b..936b8694 100644 --- a/platform/packages/ui-core/package.json +++ b/platform/packages/ui-core/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/ui-core", - "version": "26.5.1", + "version": "26.5.2", "description": "Framework-agnostic view/viewer/renderer core for Dynamia Platform", "keywords": [ "dynamia", @@ -52,14 +52,17 @@ }, "devDependencies": { "@dynamia-tools/sdk": "workspace:*", - "@types/node": "^22.0.0", + "@types/node": "^24.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", - "vitest": "^3.0.0" + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", + "vitest": "^4.0.0" }, "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" + }, + "engines": { + "node": ">=24" } } diff --git a/platform/packages/vue/package.json b/platform/packages/vue/package.json index a5af1350..73bf5e77 100644 --- a/platform/packages/vue/package.json +++ b/platform/packages/vue/package.json @@ -1,6 +1,6 @@ { "name": "@dynamia-tools/vue", - "version": "26.5.1", + "version": "26.5.2", "description": "Vue 3 adapter for Dynamia Platform UI", "keywords": [ "dynamia", @@ -56,16 +56,19 @@ "devDependencies": { "@dynamia-tools/sdk": "workspace:*", "@dynamia-tools/ui-core": "workspace:*", - "@types/node": "^22.0.0", - "@vitejs/plugin-vue": "^5.0.0", + "@types/node": "^24.0.0", + "@vitejs/plugin-vue": "^6.0.0", "typescript": "^5.7.0", - "vite": "^6.2.0", - "vite-plugin-dts": "^4.5.0", + "vite": "^8.0.0", + "vite-plugin-dts": "^5.0.0", "vue": "^3.4.0", "vue-tsc": "^2.0.0" }, "publishConfig": { "access": "public", "registry": "https://registry.npmjs.org/" + }, + "engines": { + "node": ">=24" } } diff --git a/platform/starters/zk-starter/pom.xml b/platform/starters/zk-starter/pom.xml index 18e99a7a..f753ceb3 100644 --- a/platform/starters/zk-starter/pom.xml +++ b/platform/starters/zk-starter/pom.xml @@ -4,7 +4,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -28,22 +28,22 @@ tools.dynamia tools.dynamia.app - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain.jpa - 26.5.1 + 26.5.2 org.hibernate.validator diff --git a/platform/ui/ui-shared/pom.xml b/platform/ui/ui-shared/pom.xml index 3646f530..e53f3b28 100644 --- a/platform/ui/ui-shared/pom.xml +++ b/platform/ui/ui-shared/pom.xml @@ -23,7 +23,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../../../pom.xml @@ -64,17 +64,17 @@ tools.dynamia tools.dynamia.integration - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.commons - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.io - 26.5.1 + 26.5.2 diff --git a/platform/ui/zk/pom.xml b/platform/ui/zk/pom.xml index a4fb5fa4..b4084ac7 100644 --- a/platform/ui/zk/pom.xml +++ b/platform/ui/zk/pom.xml @@ -21,7 +21,7 @@ tools.dynamia.parent tools.dynamia - 26.5.1 + 26.5.2 ../../../pom.xml 4.0.0 @@ -99,31 +99,31 @@ tools.dynamia tools.dynamia.web - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.navigation - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.ui - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.domain - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.viewers - 26.5.1 + 26.5.2 org.yaml @@ -134,19 +134,19 @@ tools.dynamia tools.dynamia.crud - 26.5.1 + 26.5.2 tools.dynamia tools.dynamia.reports - 26.5.1 + 26.5.2 compile tools.dynamia tools.dynamia.templates - 26.5.1 + 26.5.2 compile diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a82ba67..64867f30 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,29 +9,29 @@ importers: .: devDependencies: '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@vitest/coverage-v8': - specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^4.0.0 + version: 4.1.6(vitest@4.1.6) eslint: specifier: ^9.0.0 version: 9.39.4 prettier: specifier: ^3.5.0 - version: 3.8.1 + version: 3.8.3 typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) extensions/entity-files/packages/files-sdk: devDependencies: @@ -39,23 +39,23 @@ importers: specifier: workspace:* version: link:../../../../platform/packages/sdk '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@vitest/coverage-v8': - specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^4.0.0 + version: 4.1.6(vitest@4.1.6) typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) extensions/entity-files/packages/simple-file-server: dependencies: @@ -91,20 +91,20 @@ importers: version: 3.25.76 devDependencies: '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@types/sharp': specifier: ^0.31.0 version: 0.31.1 tsx: specifier: ^4.19.0 - version: 4.22.0 + version: 4.22.1 typescript: specifier: ^5.7.0 version: 5.9.3 vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) extensions/reports/packages/reports-sdk: devDependencies: @@ -112,23 +112,23 @@ importers: specifier: workspace:* version: link:../../../../platform/packages/sdk '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@vitest/coverage-v8': - specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^4.0.0 + version: 4.1.6(vitest@4.1.6) typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) extensions/saas/packages/saas-sdk: devDependencies: @@ -136,29 +136,29 @@ importers: specifier: workspace:* version: link:../../../../platform/packages/sdk '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@vitest/coverage-v8': - specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^4.0.0 + version: 4.1.6(vitest@4.1.6) typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) platform/packages/cli: dependencies: '@inquirer/prompts': specifier: ^7.0.0 - version: 7.10.1(@types/node@24.12.2) + version: 7.10.1(@types/node@24.12.4) chalk: specifier: ^5.0.0 version: 5.6.2 @@ -171,7 +171,7 @@ importers: devDependencies: '@types/node': specifier: ^24.0.0 - version: 24.12.2 + version: 24.12.4 typescript: specifier: ^5.7.0 version: 5.9.3 @@ -179,23 +179,23 @@ importers: platform/packages/sdk: devDependencies: '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@vitest/coverage-v8': - specifier: ^3.0.0 - version: 3.2.4(vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^4.0.0 + version: 4.1.6(vitest@4.1.6) typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) platform/packages/ui-core: dependencies: @@ -204,20 +204,20 @@ importers: version: link:../sdk devDependencies: '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vitest: - specifier: ^3.0.0 - version: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^4.0.0 + version: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) platform/packages/vue: dependencies: @@ -229,33 +229,29 @@ importers: version: link:../ui-core devDependencies: '@types/node': - specifier: ^22.0.0 - version: 22.19.15 + specifier: ^24.0.0 + version: 24.12.4 '@vitejs/plugin-vue': - specifier: ^5.0.0 - version: 5.2.4(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0))(vue@3.5.30(typescript@5.9.3)) + specifier: ^6.0.0 + version: 6.0.7(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1))(vue@3.5.34(typescript@5.9.3)) typescript: specifier: ^5.7.0 version: 5.9.3 vite: - specifier: ^6.2.0 - version: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + specifier: ^8.0.0 + version: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) vite-plugin-dts: - specifier: ^4.5.0 - version: 4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) + specifier: ^5.0.0 + version: 5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) vue: specifier: ^3.4.0 - version: 3.5.30(typescript@5.9.3) + version: 3.5.34(typescript@5.9.3) vue-tsc: specifier: ^2.0.0 version: 2.2.12(typescript@5.9.3) packages: - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -264,8 +260,8 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} engines: {node: '>=6.0.0'} hasBin: true @@ -280,14 +276,14 @@ packages: '@borewit/text-codec@0.2.2': resolution: {integrity: sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} + '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} '@esbuild/aix-ppc64@0.28.0': resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} @@ -295,300 +291,150 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.28.0': resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.28.0': resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.28.0': resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.28.0': resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.28.0': resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.28.0': resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.28.0': resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.28.0': resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.28.0': resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.28.0': resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.28.0': resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.28.0': resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.28.0': resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.28.0': resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.28.0': resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.28.0': resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.28.0': resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.28.0': resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.28.0': resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.28.0': resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - '@esbuild/openharmony-arm64@0.28.0': resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.28.0': resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.28.0': resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.28.0': resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.28.0': resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} engines: {node: '>=18'} @@ -654,12 +500,16 @@ packages: '@fastify/sensible@6.0.4': resolution: {integrity: sha512-1vxcCUlPMew6WroK8fq+LVOwbsLtX+lmuRuqpcp6eYqu6vmkLwbKTdBWAZwbeaSgCfW4tzUpTIHLLvTiQQ1BwQ==} - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} + engines: {node: '>=18.18.0'} + + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': @@ -957,17 +807,12 @@ packages: '@types/node': optional: true - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@istanbuljs/schema@0.1.3': - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -982,18 +827,14 @@ packages: resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} engines: {node: '>=8'} - '@microsoft/api-extractor-model@7.33.4': - resolution: {integrity: sha512-u1LTaNTikZAQ9uK6KG1Ms7nvNedsnODnspq/gH2dcyETWvH4hVNGNDvRAEutH66kAmxA4/necElqGNs1FggC8w==} - - '@microsoft/api-extractor@7.57.7': - resolution: {integrity: sha512-kmnmVs32MFWbV5X6BInC1/TfCs7y1ugwxv1xHsAIj/DyUfoe7vtO0alRUgbQa57+yRGHBBjlNcEk33SCAt5/dA==} - hasBin: true - - '@microsoft/tsdoc-config@0.18.1': - resolution: {integrity: sha512-9brPoVdfN9k9g0dcWkFeA7IH9bbcttzDJlXvkf8b2OBzd5MueR1V2wkKBL0abn0otvmkHJC6aapBOTJDDeMCZg==} + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 - '@microsoft/tsdoc@0.16.0': - resolution: {integrity: sha512-xgAyonlVVS+q7Vc7qLW0UrJU7rSFcETRWsqdXZtjzRU8dF+6CkozTK4V4y1LwOX7j8r/vHphjDeMeGI4tNGeGA==} + '@oxc-project/types@0.130.0': + resolution: {integrity: sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==} '@phc/format@1.0.0': resolution: {integrity: sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==} @@ -1002,187 +843,113 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - - '@rollup/pluginutils@5.3.0': - resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - - '@rollup/rollup-android-arm-eabi@4.59.0': - resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.59.0': - resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + '@rolldown/binding-android-arm64@1.0.1': + resolution: {integrity: sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.59.0': - resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + '@rolldown/binding-darwin-arm64@1.0.1': + resolution: {integrity: sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.59.0': - resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + '@rolldown/binding-darwin-x64@1.0.1': + resolution: {integrity: sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.59.0': - resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.59.0': - resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + '@rolldown/binding-freebsd-x64@1.0.1': + resolution: {integrity: sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + '@rolldown/binding-linux-arm-gnueabihf@1.0.1': + resolution: {integrity: sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + '@rolldown/binding-linux-arm64-gnu@1.0.1': + resolution: {integrity: sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.59.0': - resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + '@rolldown/binding-linux-arm64-musl@1.0.1': + resolution: {integrity: sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.59.0': - resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.59.0': - resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.59.0': - resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + '@rolldown/binding-linux-ppc64-gnu@1.0.1': + resolution: {integrity: sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-musl@4.59.0': - resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.59.0': - resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.59.0': - resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.59.0': - resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + '@rolldown/binding-linux-s390x-gnu@1.0.1': + resolution: {integrity: sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.59.0': - resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} + '@rolldown/binding-linux-x64-gnu@1.0.1': + resolution: {integrity: sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.59.0': - resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + '@rolldown/binding-linux-x64-musl@1.0.1': + resolution: {integrity: sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openbsd-x64@4.59.0': - resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.59.0': - resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + '@rolldown/binding-openharmony-arm64@1.0.1': + resolution: {integrity: sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.59.0': - resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} - cpu: [arm64] - os: [win32] + '@rolldown/binding-wasm32-wasi@1.0.1': + resolution: {integrity: sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] - '@rollup/rollup-win32-ia32-msvc@4.59.0': - resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} - cpu: [ia32] + '@rolldown/binding-win32-arm64-msvc@1.0.1': + resolution: {integrity: sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.59.0': - resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + '@rolldown/binding-win32-x64-msvc@1.0.1': + resolution: {integrity: sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.59.0': - resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} - cpu: [x64] - os: [win32] + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} - '@rushstack/node-core-library@5.20.3': - resolution: {integrity: sha512-95JgEPq2k7tHxhF9/OJnnyHDXfC9cLhhta0An/6MlkDsX2A6dTzDrTUG18vx4vjc280V0fi0xDH9iQczpSuWsw==} - peerDependencies: - '@types/node': '*' - peerDependenciesMeta: - '@types/node': - optional: true - - '@rushstack/problem-matcher@0.2.1': - resolution: {integrity: sha512-gulfhBs6n+I5b7DvjKRfhMGyUejtSgOHTclF/eONr8hcgF1APEDjhxIsfdUYYMzC3rvLwGluqLjbwCFZ8nxrog==} - peerDependencies: - '@types/node': '*' - peerDependenciesMeta: - '@types/node': - optional: true - - '@rushstack/rig-package@0.7.2': - resolution: {integrity: sha512-9XbFWuqMYcHUso4mnETfhGVUSaADBRj6HUAAEYk50nMPn8WRICmBuCphycQGNB3duIR6EEZX3Xj3SYc2XiP+9A==} - - '@rushstack/terminal@0.22.3': - resolution: {integrity: sha512-gHC9pIMrUPzAbBiI4VZMU7Q+rsCzb8hJl36lFIulIzoceKotyKL3Rd76AZ2CryCTKEg+0bnTj406HE5YY5OQvw==} + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} peerDependencies: - '@types/node': '*' + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: - '@types/node': + rollup: optional: true - '@rushstack/ts-command-line@5.3.3': - resolution: {integrity: sha512-c+ltdcvC7ym+10lhwR/vWiOhsrm/bP3By2VsFcs5qTKv+6tTmxgbVrtJ5NdNjANiV5TcmOZgUN+5KYQ4llsvEw==} - '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -1190,6 +957,9 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@tokenizer/inflate@0.2.7': resolution: {integrity: sha512-MADQgmZT1eKjp06jpI2yozxaU9uVs4GzzgSL+uEq7bVcJ9V1ZXQkeGNql1fsSI0gMy1vhvNTNbUqrx+pZfJVmg==} engines: {node: '>=18'} @@ -1197,8 +967,8 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} - '@types/argparse@1.0.38': - resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@tybys/wasm-util@0.10.2': + resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} '@types/chai@5.2.3': resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} @@ -1206,65 +976,62 @@ packages: '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.19.15': - resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==} - - '@types/node@24.12.2': - resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + '@types/node@24.12.4': + resolution: {integrity: sha512-GUUEShf+PBCGW2KaXwcIt3Yk+e3pkKwWKb9GSyM9WQVE+ep2jzmHdGsHzu4wgcZy5fN9FBdVzjpBQsYlpfpgLA==} '@types/sharp@0.31.1': resolution: {integrity: sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==} - '@vitejs/plugin-vue@5.2.4': - resolution: {integrity: sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==} - engines: {node: ^18.0.0 || >=20.0.0} + '@vitejs/plugin-vue@6.0.7': + resolution: {integrity: sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==} + engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: ^5.0.0 || ^6.0.0 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vue: ^3.2.25 - '@vitest/coverage-v8@3.2.4': - resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==} + '@vitest/coverage-v8@4.1.6': + resolution: {integrity: sha512-36l628fQ/9a/8ihy97eOtEnvWQEdqULQOJtcaxtoNq0G1w3Mxd4szSahOaMM9/NGyZ+hyKcMtIW/WIxq0XQViQ==} peerDependencies: - '@vitest/browser': 3.2.4 - vitest: 3.2.4 + '@vitest/browser': 4.1.6 + vitest: 4.1.6 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@4.1.6': + resolution: {integrity: sha512-7EHDquPthALSV0jhhjgEW8FXaviMx7rSqu8W6oqCoAuOhKov814P99QDV1pxMA3QPv21YudvJngIhjrNI4opLg==} - '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + '@vitest/mocker@4.1.6': + resolution: {integrity: sha512-MCFc63czMjEInOlcY2cpQCvCN+KgbAn+60xu9cMgP4sKaLC5JNAKw7JH8QdAnoAC88hW1IiSNZ+GgVXlN1UcMQ==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/pretty-format@4.1.6': + resolution: {integrity: sha512-h5SxD/IzNhZYnrSZRsUZQIC+vD0GY8cUvq0iwsmkFKixRCKLLWqCXa/FIQ4S1R+sI+PGoojkHsdNrbZiM9Qpgw==} - '@vitest/runner@3.2.4': - resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + '@vitest/runner@4.1.6': + resolution: {integrity: sha512-nOPCmn2+yD0ZNmKdsXGv/UxMMWbMuKeD6GyYncNwdkYDxpQvrPSKYj2rWuDjC2Y4b6w6hjip5dBKFzEUuZe3vA==} - '@vitest/snapshot@3.2.4': - resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + '@vitest/snapshot@4.1.6': + resolution: {integrity: sha512-YhsdE6xAVfTDmzjxL2ZDUvjj+ZsgyOKe+TdQzqkD72wIOmHka8NuGQ6NpTNZv9D2Z63fbwWKJPeVpEw4EQgYxw==} - '@vitest/spy@3.2.4': - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/spy@4.1.6': + resolution: {integrity: sha512-JFKxMx6udhwKh/Ldo270e17QX710vgunMkuPAvXjHSvC6oqLWAHhVhjg/I71q0u0CBSErIODV1Kjv0FQNSWjdg==} - '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/utils@4.1.6': + resolution: {integrity: sha512-FxIY+U81R3LGKCxaHHFRQ5+g6/iRgGLmeHWdp2Amj4ljQRrEIWHmZyDfDYBRZlpyqA7qKxtS9DD1dhk8RnRIVQ==} '@volar/language-core@2.4.15': resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} @@ -1284,29 +1051,21 @@ packages: '@volar/typescript@2.4.28': resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} - '@vue/compiler-core@3.5.30': - resolution: {integrity: sha512-s3DfdZkcu/qExZ+td75015ljzHc6vE+30cFMGRPROYjqkroYI5NV2X1yAMX9UeyBNWB9MxCfPcsjpLS11nzkkw==} + '@vue/compiler-core@3.5.34': + resolution: {integrity: sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==} - '@vue/compiler-dom@3.5.30': - resolution: {integrity: sha512-eCFYESUEVYHhiMuK4SQTldO3RYxyMR/UQL4KdGD1Yrkfdx4m/HYuZ9jSfPdA+nWJY34VWndiYdW/wZXyiPEB9g==} + '@vue/compiler-dom@3.5.34': + resolution: {integrity: sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==} - '@vue/compiler-sfc@3.5.30': - resolution: {integrity: sha512-LqmFPDn89dtU9vI3wHJnwaV6GfTRD87AjWpTWpyrdVOObVtjIuSeZr181z5C4PmVx/V3j2p+0f7edFKGRMpQ5A==} + '@vue/compiler-sfc@3.5.34': + resolution: {integrity: sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==} - '@vue/compiler-ssr@3.5.30': - resolution: {integrity: sha512-NsYK6OMTnx109PSL2IAyf62JP6EUdk4Dmj6AkWcJGBvN0dQoMYtVekAmdqgTtWQgEJo+Okstbf/1p7qZr5H+bA==} + '@vue/compiler-ssr@3.5.34': + resolution: {integrity: sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==} '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} - '@vue/language-core@2.2.0': - resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - '@vue/language-core@2.2.12': resolution: {integrity: sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==} peerDependencies: @@ -1315,22 +1074,22 @@ packages: typescript: optional: true - '@vue/reactivity@3.5.30': - resolution: {integrity: sha512-179YNgKATuwj9gB+66snskRDOitDiuOZqkYia7mHKJaidOMo/WJxHKF8DuGc4V4XbYTJANlfEKb0yxTQotnx4Q==} + '@vue/reactivity@3.5.34': + resolution: {integrity: sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==} - '@vue/runtime-core@3.5.30': - resolution: {integrity: sha512-e0Z+8PQsUTdwV8TtEsLzUM7SzC7lQwYKePydb7K2ZnmS6jjND+WJXkmmfh/swYzRyfP1EY3fpdesyYoymCzYfg==} + '@vue/runtime-core@3.5.34': + resolution: {integrity: sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==} - '@vue/runtime-dom@3.5.30': - resolution: {integrity: sha512-2UIGakjU4WSQ0T4iwDEW0W7vQj6n7AFn7taqZ9Cvm0Q/RA2FFOziLESrDL4GmtI1wV3jXg5nMoJSYO66egDUBw==} + '@vue/runtime-dom@3.5.34': + resolution: {integrity: sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==} - '@vue/server-renderer@3.5.30': - resolution: {integrity: sha512-v+R34icapydRwbZRD0sXwtHqrQJv38JuMB4JxbOxd8NEpGLny7cncMp53W9UH/zo4j8eDHjQ1dEJXwzFQknjtQ==} + '@vue/server-renderer@3.5.34': + resolution: {integrity: sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==} peerDependencies: - vue: 3.5.30 + vue: 3.5.34 - '@vue/shared@3.5.30': - resolution: {integrity: sha512-YXgQ7JjaO18NeK2K9VTbDHaFy62WrObMa6XERNfNOkAhD1F1oDSf3ZJ7K6GqabZ0BvSDHajp8qfS5Sa2I9n8uQ==} + '@vue/shared@3.5.34': + resolution: {integrity: sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==} abstract-logging@2.0.1: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} @@ -1345,14 +1104,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ajv-draft-04@1.0.0: - resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==} - peerDependencies: - ajv: ^8.5.0 - peerDependenciesMeta: - ajv: - optional: true - ajv-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -1361,14 +1112,11 @@ packages: ajv: optional: true - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} - - ajv@8.18.0: - resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} - alien-signals@0.4.14: - resolution: {integrity: sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} alien-signals@1.0.13: resolution: {integrity: sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==} @@ -1385,17 +1133,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} - argon2@0.43.1: resolution: {integrity: sha512-TfOzvDWUaQPurCT1hOwIeFNkgrAJDpbBGBGWDgzDsm11nNhImc13WhdGdCU6K7brkp8VpeY07oGtSex0Wmhg8w==} engines: {node: '>=16.17.0'} - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1403,8 +1144,8 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - ast-v8-to-istanbul@0.3.12: - resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==} + ast-v8-to-istanbul@1.0.0: + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} @@ -1416,30 +1157,18 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - balanced-match@4.0.4: - resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} - engines: {node: 18 || 20 || >=22} - - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + brace-expansion@1.1.14: + resolution: {integrity: sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==} - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - - brace-expansion@5.0.4: - resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} - engines: {node: 18 || 20 || >=22} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} + brace-expansion@2.1.0: + resolution: {integrity: sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==} callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chalk@4.1.2: @@ -1453,10 +1182,6 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -1499,6 +1224,9 @@ packages: resolution: {integrity: sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==} engines: {node: '>=18'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie@1.1.1: resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} engines: {node: '>=18'} @@ -1525,10 +1253,6 @@ packages: supports-color: optional: true - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1544,22 +1268,12 @@ packages: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} - diff@8.0.3: - resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} - engines: {node: '>=0.3.1'} - - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} @@ -1567,13 +1281,8 @@ packages: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} - engines: {node: '>=18'} - hasBin: true + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} esbuild@0.28.0: resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} @@ -1667,8 +1376,8 @@ packages: fast-safe-stringify@2.1.1: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} fastify-plugin@5.1.0: resolution: {integrity: sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw==} @@ -1715,31 +1424,20 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flatted@3.4.1: - resolution: {integrity: sha512-IxfVbRFVlV8V/yRaGzk0UVIcsKKHMSfYw66T/u4nTwlWteQePsxe//LjudR1AMX4tZW3WFCh3Zqa/sjlqpbURQ==} - - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} - fs-extra@11.3.4: - resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} - engines: {node: '>=14.14'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} + get-east-asian-width@1.6.0: + resolution: {integrity: sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==} engines: {node: '>=18'} get-stream@9.0.1: @@ -1750,26 +1448,14 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.5.0: - resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - hasBin: true - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - he@1.2.0: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true @@ -1803,10 +1489,6 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} - import-lazy@4.0.0: - resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} - engines: {node: '>=8'} - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -1818,10 +1500,6 @@ packages: resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} engines: {node: '>= 10'} - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -1865,20 +1543,10 @@ packages: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@5.0.6: - resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} - engines: {node: '>=10'} - istanbul-reports@3.2.0: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jju@1.4.0: - resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} - joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -1886,9 +1554,6 @@ packages: js-tokens@10.0.0: resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} - js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -1908,9 +1573,6 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -1924,6 +1586,80 @@ packages: light-my-request@6.6.0: resolution: {integrity: sha512-CHYbu8RtboSIoVsHZ6Ye4cj4Aw/yg2oAFimlF7mNvfDV192LR7nDiKtSIfCuLT7KokPSTn/9kfVLm5OGN0A28A==} + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + local-pkg@1.1.2: resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} engines: {node: '>=14'} @@ -1935,28 +1671,15 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash@4.17.23: - resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} - log-symbols@6.0.0: resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} engines: {node: '>=18'} - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.3.5: - resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + magicast@0.5.3: + resolution: {integrity: sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -1978,14 +1701,6 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} - minimatch@10.2.3: - resolution: {integrity: sha512-Rwi3pnapEqirPSbWbrZaa6N3nmqq4Xer/2XooiOKyV3q12ML06f7MOuc5DVH8ONZIFhwIYQ3yzPH4nt7iWHaTg==} - engines: {node: 18 || 20 || >=22} - - minimatch@10.2.4: - resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} - engines: {node: 18 || 20 || >=22} - minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -1996,12 +1711,8 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.3: - resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} - engines: {node: '>=16 || 14 >=14.17'} - - mlly@1.8.1: - resolution: {integrity: sha512-SnL6sNutTwRWWR/vcmCYHSADjiEesp5TGQQ0pXyLhW5IoeibRlF/CbSLailbB3CNqJUk9cVJ9dUDnbD7GrcHBQ==} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -2013,8 +1724,8 @@ packages: resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} engines: {node: ^18.17.0 || >=20.5.0} - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -2033,6 +1744,9 @@ packages: resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==} engines: {node: '>=18'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -2060,9 +1774,6 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -2086,25 +1797,14 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} pino-abstract-transport@2.0.0: @@ -2127,19 +1827,19 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.3.0: - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + pkg-types@2.3.1: + resolution: {integrity: sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==} - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.8.1: - resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + prettier@3.8.3: + resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} engines: {node: '>=14'} hasBin: true @@ -2178,11 +1878,6 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} - engines: {node: '>= 0.4'} - hasBin: true - restore-cursor@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -2198,9 +1893,9 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - rollup@4.59.0: - resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} + rolldown@1.0.1: + resolution: {integrity: sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true safe-regex2@5.1.1: @@ -2217,13 +1912,8 @@ packages: secure-json-parse@4.1.0: resolution: {integrity: sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==} - semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - - semver@7.7.4: - resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + semver@7.8.0: + resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} engines: {node: '>=10'} hasBin: true @@ -2259,17 +1949,10 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2277,25 +1960,17 @@ packages: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} stdin-discarder@0.2.2: resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} engines: {node: '>=18'} - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -2320,9 +1995,6 @@ packages: resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} engines: {node: '>=14.16'} - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} - strtok3@10.3.5: resolution: {integrity: sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==} engines: {node: '>=18'} @@ -2331,41 +2003,22 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - test-exclude@7.0.2: - resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} - engines: {node: '>=18'} - thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} + engines: {node: '>=18'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} toad-cache@3.7.1: @@ -2383,8 +2036,8 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.22.0: - resolution: {integrity: sha512-8ccZMPD69s1AbKXx0C5ddTNZfNjwV04iIKgjZmKfKxMynEtSYcK0Lh7iQFh53fI5Yu4pb9usgAiqyPmEONaALg==} + tsx@4.22.1: + resolution: {integrity: sha512-TvncJykhxAzFCk0VQZKBTClall4Pm7qXDSodb6uxi8QFa8X8mT6ABjxxsQ2opDRYxG7AzcRWXaFtruz5HJKuWg==} engines: {node: '>=18.0.0'} hasBin: true @@ -2396,26 +2049,18 @@ packages: resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==} engines: {node: '>= 18'} - typescript@5.8.2: - resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} - engines: {node: '>=14.17'} - hasBin: true - typescript@5.9.3: resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} engines: {node: '>=14.17'} hasBin: true - ufo@1.6.3: - resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} uint8array-extras@1.5.0: resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==} engines: {node: '>=18'} - undici-types@6.21.0: - resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} - undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} @@ -2423,9 +2068,39 @@ packages: resolution: {integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==} engines: {node: '>=18'} - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} + unplugin-dts@1.0.0: + resolution: {integrity: sha512-qz+U1lCscwq+t8Mkaxy5Esa7IQ5wWV18b4mnioOXSdnPaNiJ0+qgE3I+KL6UkXYZWxxGo2qdGone8LEQ52Sfkw==} + peerDependencies: + '@microsoft/api-extractor': '>=7' + '@rspack/core': ^1 + '@vue/language-core': ~3.1.5 + esbuild: '*' + rolldown: '*' + rollup: '>=3' + typescript: '>=4' + vite: '>=3' + webpack: ^4 || ^5 + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@rspack/core': + optional: true + '@vue/language-core': + optional: true + esbuild: + optional: true + rolldown: + optional: true + rollup: + optional: true + vite: + optional: true + webpack: + optional: true + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -2434,45 +2109,48 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vite-node@3.2.4: - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - - vite-plugin-dts@4.5.4: - resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==} + vite-plugin-dts@5.0.0: + resolution: {integrity: sha512-VLNAUttBq7pLxxL/m/ztjd5zj5yiviiC7ijfPFVLK5c45FLcibvieBsdjSka3a4ag1qdrAF9K3OysH4/lW+rPQ==} peerDependencies: - typescript: '*' - vite: '*' + '@microsoft/api-extractor': '>=7' + rollup: '>=3' + vite: '>=3' peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + rollup: + optional: true vite: optional: true - vite@6.4.1: - resolution: {integrity: sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vite@8.0.13: + resolution: {integrity: sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 jiti: '>=1.21.0' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 peerDependenciesMeta: '@types/node': optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true jiti: optional: true less: optional: true - lightningcss: - optional: true sass: optional: true sass-embedded: @@ -2488,26 +2166,39 @@ packages: yaml: optional: true - vitest@3.2.4: - resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.1.6: + resolution: {integrity: sha512-6lvjbS3p9b4CrdCmguzbh2/4uoXhGE2q71R4OX5sqF9R1bo9Xd6fGrMAfvp5wnCzlBnFVdCOp6onuTQVbo8iUQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.4 - '@vitest/ui': 3.2.4 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.6 + '@vitest/browser-preview': 4.1.6 + '@vitest/browser-webdriverio': 4.1.6 + '@vitest/coverage-istanbul': 4.1.6 + '@vitest/coverage-v8': 4.1.6 + '@vitest/ui': 4.1.6 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true - '@types/debug': + '@opentelemetry/api': optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -2525,14 +2216,17 @@ packages: peerDependencies: typescript: '>=5.0.0' - vue@3.5.30: - resolution: {integrity: sha512-hTHLc6VNZyzzEH/l7PFGjpcTvUgiaPK5mdLkbjrTeWSRcEfxFrv56g/XckIYlE9ckuobsdwqd5mk2g1sBkMewg==} + vue@3.5.34: + resolution: {integrity: sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2551,20 +2245,9 @@ packages: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2582,16 +2265,11 @@ packages: snapshots: - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} - '@babel/parser@7.29.2': + '@babel/parser@7.29.3': dependencies: '@babel/types': 7.29.0 @@ -2604,164 +2282,97 @@ snapshots: '@borewit/text-codec@0.2.2': {} - '@emnapi/runtime@1.10.0': + '@emnapi/core@1.10.0': dependencies: + '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.25.12': + '@emnapi/runtime@1.10.0': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/aix-ppc64@0.28.0': + '@emnapi/wasi-threads@1.2.1': + dependencies: + tslib: 2.8.1 optional: true - '@esbuild/android-arm64@0.25.12': + '@esbuild/aix-ppc64@0.28.0': optional: true '@esbuild/android-arm64@0.28.0': optional: true - '@esbuild/android-arm@0.25.12': - optional: true - '@esbuild/android-arm@0.28.0': optional: true - '@esbuild/android-x64@0.25.12': - optional: true - '@esbuild/android-x64@0.28.0': optional: true - '@esbuild/darwin-arm64@0.25.12': - optional: true - '@esbuild/darwin-arm64@0.28.0': optional: true - '@esbuild/darwin-x64@0.25.12': - optional: true - '@esbuild/darwin-x64@0.28.0': optional: true - '@esbuild/freebsd-arm64@0.25.12': - optional: true - '@esbuild/freebsd-arm64@0.28.0': optional: true - '@esbuild/freebsd-x64@0.25.12': - optional: true - '@esbuild/freebsd-x64@0.28.0': optional: true - '@esbuild/linux-arm64@0.25.12': - optional: true - '@esbuild/linux-arm64@0.28.0': optional: true - '@esbuild/linux-arm@0.25.12': - optional: true - '@esbuild/linux-arm@0.28.0': optional: true - '@esbuild/linux-ia32@0.25.12': - optional: true - '@esbuild/linux-ia32@0.28.0': optional: true - '@esbuild/linux-loong64@0.25.12': - optional: true - '@esbuild/linux-loong64@0.28.0': optional: true - '@esbuild/linux-mips64el@0.25.12': - optional: true - '@esbuild/linux-mips64el@0.28.0': optional: true - '@esbuild/linux-ppc64@0.25.12': - optional: true - '@esbuild/linux-ppc64@0.28.0': optional: true - '@esbuild/linux-riscv64@0.25.12': - optional: true - - '@esbuild/linux-riscv64@0.28.0': - optional: true - - '@esbuild/linux-s390x@0.25.12': + '@esbuild/linux-riscv64@0.28.0': optional: true '@esbuild/linux-s390x@0.28.0': optional: true - '@esbuild/linux-x64@0.25.12': - optional: true - '@esbuild/linux-x64@0.28.0': optional: true - '@esbuild/netbsd-arm64@0.25.12': - optional: true - '@esbuild/netbsd-arm64@0.28.0': optional: true - '@esbuild/netbsd-x64@0.25.12': - optional: true - '@esbuild/netbsd-x64@0.28.0': optional: true - '@esbuild/openbsd-arm64@0.25.12': - optional: true - '@esbuild/openbsd-arm64@0.28.0': optional: true - '@esbuild/openbsd-x64@0.25.12': - optional: true - '@esbuild/openbsd-x64@0.28.0': optional: true - '@esbuild/openharmony-arm64@0.25.12': - optional: true - '@esbuild/openharmony-arm64@0.28.0': optional: true - '@esbuild/sunos-x64@0.25.12': - optional: true - '@esbuild/sunos-x64@0.28.0': optional: true - '@esbuild/win32-arm64@0.25.12': - optional: true - '@esbuild/win32-arm64@0.28.0': optional: true - '@esbuild/win32-ia32@0.25.12': - optional: true - '@esbuild/win32-ia32@0.28.0': optional: true - '@esbuild/win32-x64@0.25.12': - optional: true - '@esbuild/win32-x64@0.28.0': optional: true @@ -2790,7 +2401,7 @@ snapshots: '@eslint/eslintrc@3.3.5': dependencies: - ajv: 6.14.0 + ajv: 6.15.0 debug: 4.4.3 espree: 10.4.0 globals: 14.0.0 @@ -2813,9 +2424,9 @@ snapshots: '@fastify/ajv-compiler@4.0.5': dependencies: - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) - fast-uri: 3.1.0 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.2 '@fastify/error@4.2.0': {} @@ -2844,13 +2455,18 @@ snapshots: type-is: 2.1.0 vary: 1.1.2 - '@humanfs/core@0.19.1': {} + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 - '@humanfs/node@0.16.7': + '@humanfs/node@0.16.8': dependencies: - '@humanfs/core': 0.19.1 + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 '@humanwhocodes/retry': 0.4.3 + '@humanfs/types@0.15.0': {} + '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.4.3': {} @@ -2953,145 +2569,139 @@ snapshots: '@inquirer/ansi@1.0.2': {} - '@inquirer/checkbox@4.3.2(@types/node@24.12.2)': + '@inquirer/checkbox@4.3.2(@types/node@24.12.4)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/type': 3.0.10(@types/node@24.12.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/confirm@5.1.21(@types/node@24.12.2)': + '@inquirer/confirm@5.1.21(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/core@10.3.2(@types/node@24.12.2)': + '@inquirer/core@10.3.2(@types/node@24.12.4)': dependencies: '@inquirer/ansi': 1.0.2 '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/type': 3.0.10(@types/node@24.12.4) cli-width: 4.1.0 mute-stream: 2.0.0 signal-exit: 4.1.0 wrap-ansi: 6.2.0 yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/editor@4.2.23(@types/node@24.12.2)': + '@inquirer/editor@4.2.23(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/external-editor': 1.0.3(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/external-editor': 1.0.3(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/expand@4.0.23(@types/node@24.12.2)': + '@inquirer/expand@4.0.23(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/external-editor@1.0.3(@types/node@24.12.2)': + '@inquirer/external-editor@1.0.3(@types/node@24.12.4)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 '@inquirer/figures@1.0.15': {} - '@inquirer/input@4.3.1(@types/node@24.12.2)': + '@inquirer/input@4.3.1(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/number@3.0.23(@types/node@24.12.2)': + '@inquirer/number@3.0.23(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/password@4.0.23(@types/node@24.12.2)': + '@inquirer/password@4.0.23(@types/node@24.12.4)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) optionalDependencies: - '@types/node': 24.12.2 - - '@inquirer/prompts@7.10.1(@types/node@24.12.2)': - dependencies: - '@inquirer/checkbox': 4.3.2(@types/node@24.12.2) - '@inquirer/confirm': 5.1.21(@types/node@24.12.2) - '@inquirer/editor': 4.2.23(@types/node@24.12.2) - '@inquirer/expand': 4.0.23(@types/node@24.12.2) - '@inquirer/input': 4.3.1(@types/node@24.12.2) - '@inquirer/number': 3.0.23(@types/node@24.12.2) - '@inquirer/password': 4.0.23(@types/node@24.12.2) - '@inquirer/rawlist': 4.1.11(@types/node@24.12.2) - '@inquirer/search': 3.2.2(@types/node@24.12.2) - '@inquirer/select': 4.4.2(@types/node@24.12.2) + '@types/node': 24.12.4 + + '@inquirer/prompts@7.10.1(@types/node@24.12.4)': + dependencies: + '@inquirer/checkbox': 4.3.2(@types/node@24.12.4) + '@inquirer/confirm': 5.1.21(@types/node@24.12.4) + '@inquirer/editor': 4.2.23(@types/node@24.12.4) + '@inquirer/expand': 4.0.23(@types/node@24.12.4) + '@inquirer/input': 4.3.1(@types/node@24.12.4) + '@inquirer/number': 3.0.23(@types/node@24.12.4) + '@inquirer/password': 4.0.23(@types/node@24.12.4) + '@inquirer/rawlist': 4.1.11(@types/node@24.12.4) + '@inquirer/search': 3.2.2(@types/node@24.12.4) + '@inquirer/select': 4.4.2(@types/node@24.12.4) optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/rawlist@4.1.11(@types/node@24.12.2)': + '@inquirer/rawlist@4.1.11(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) + '@inquirer/type': 3.0.10(@types/node@24.12.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/search@3.2.2(@types/node@24.12.2)': + '@inquirer/search@3.2.2(@types/node@24.12.4)': dependencies: - '@inquirer/core': 10.3.2(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/type': 3.0.10(@types/node@24.12.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/select@4.4.2(@types/node@24.12.2)': + '@inquirer/select@4.4.2(@types/node@24.12.4)': dependencies: '@inquirer/ansi': 1.0.2 - '@inquirer/core': 10.3.2(@types/node@24.12.2) + '@inquirer/core': 10.3.2(@types/node@24.12.4) '@inquirer/figures': 1.0.15 - '@inquirer/type': 3.0.10(@types/node@24.12.2) + '@inquirer/type': 3.0.10(@types/node@24.12.4) yoctocolors-cjs: 2.1.3 optionalDependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@inquirer/type@3.0.10(@types/node@24.12.2)': + '@inquirer/type@3.0.10(@types/node@24.12.4)': optionalDependencies: - '@types/node': 24.12.2 - - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.2.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@istanbuljs/schema@0.1.3': {} + '@types/node': 24.12.4 '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -3103,175 +2713,82 @@ snapshots: '@lukeed/ms@2.0.2': {} - '@microsoft/api-extractor-model@7.33.4(@types/node@22.19.15)': - dependencies: - '@microsoft/tsdoc': 0.16.0 - '@microsoft/tsdoc-config': 0.18.1 - '@rushstack/node-core-library': 5.20.3(@types/node@22.19.15) - transitivePeerDependencies: - - '@types/node' - - '@microsoft/api-extractor@7.57.7(@types/node@22.19.15)': - dependencies: - '@microsoft/api-extractor-model': 7.33.4(@types/node@22.19.15) - '@microsoft/tsdoc': 0.16.0 - '@microsoft/tsdoc-config': 0.18.1 - '@rushstack/node-core-library': 5.20.3(@types/node@22.19.15) - '@rushstack/rig-package': 0.7.2 - '@rushstack/terminal': 0.22.3(@types/node@22.19.15) - '@rushstack/ts-command-line': 5.3.3(@types/node@22.19.15) - diff: 8.0.3 - lodash: 4.17.23 - minimatch: 10.2.3 - resolve: 1.22.11 - semver: 7.5.4 - source-map: 0.6.1 - typescript: 5.8.2 - transitivePeerDependencies: - - '@types/node' - - '@microsoft/tsdoc-config@0.18.1': + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@microsoft/tsdoc': 0.16.0 - ajv: 8.18.0 - jju: 1.4.0 - resolve: 1.22.11 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.2 + optional: true - '@microsoft/tsdoc@0.16.0': {} + '@oxc-project/types@0.130.0': {} '@phc/format@1.0.0': {} '@pinojs/redact@0.4.0': {} - '@pkgjs/parseargs@0.11.0': - optional: true - - '@rollup/pluginutils@5.3.0(rollup@4.59.0)': - dependencies: - '@types/estree': 1.0.8 - estree-walker: 2.0.2 - picomatch: 4.0.3 - optionalDependencies: - rollup: 4.59.0 - - '@rollup/rollup-android-arm-eabi@4.59.0': - optional: true - - '@rollup/rollup-android-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.59.0': - optional: true - - '@rollup/rollup-darwin-x64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.59.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.59.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.59.0': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.59.0': + '@rolldown/binding-android-arm64@1.0.1': optional: true - '@rollup/rollup-linux-loong64-musl@4.59.0': + '@rolldown/binding-darwin-arm64@1.0.1': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.59.0': + '@rolldown/binding-darwin-x64@1.0.1': optional: true - '@rollup/rollup-linux-ppc64-musl@4.59.0': + '@rolldown/binding-freebsd-x64@1.0.1': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.59.0': + '@rolldown/binding-linux-arm-gnueabihf@1.0.1': optional: true - '@rollup/rollup-linux-riscv64-musl@4.59.0': + '@rolldown/binding-linux-arm64-gnu@1.0.1': optional: true - '@rollup/rollup-linux-s390x-gnu@4.59.0': + '@rolldown/binding-linux-arm64-musl@1.0.1': optional: true - '@rollup/rollup-linux-x64-gnu@4.59.0': + '@rolldown/binding-linux-ppc64-gnu@1.0.1': optional: true - '@rollup/rollup-linux-x64-musl@4.59.0': + '@rolldown/binding-linux-s390x-gnu@1.0.1': optional: true - '@rollup/rollup-openbsd-x64@4.59.0': + '@rolldown/binding-linux-x64-gnu@1.0.1': optional: true - '@rollup/rollup-openharmony-arm64@4.59.0': + '@rolldown/binding-linux-x64-musl@1.0.1': optional: true - '@rollup/rollup-win32-arm64-msvc@4.59.0': + '@rolldown/binding-openharmony-arm64@1.0.1': optional: true - '@rollup/rollup-win32-ia32-msvc@4.59.0': + '@rolldown/binding-wasm32-wasi@1.0.1': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@rollup/rollup-win32-x64-gnu@4.59.0': + '@rolldown/binding-win32-arm64-msvc@1.0.1': optional: true - '@rollup/rollup-win32-x64-msvc@4.59.0': + '@rolldown/binding-win32-x64-msvc@1.0.1': optional: true - '@rushstack/node-core-library@5.20.3(@types/node@22.19.15)': - dependencies: - ajv: 8.18.0 - ajv-draft-04: 1.0.0(ajv@8.18.0) - ajv-formats: 3.0.1(ajv@8.18.0) - fs-extra: 11.3.4 - import-lazy: 4.0.0 - jju: 1.4.0 - resolve: 1.22.11 - semver: 7.5.4 - optionalDependencies: - '@types/node': 22.19.15 - - '@rushstack/problem-matcher@0.2.1(@types/node@22.19.15)': - optionalDependencies: - '@types/node': 22.19.15 - - '@rushstack/rig-package@0.7.2': - dependencies: - resolve: 1.22.11 - strip-json-comments: 3.1.1 - - '@rushstack/terminal@0.22.3(@types/node@22.19.15)': - dependencies: - '@rushstack/node-core-library': 5.20.3(@types/node@22.19.15) - '@rushstack/problem-matcher': 0.2.1(@types/node@22.19.15) - supports-color: 8.1.1 - optionalDependencies: - '@types/node': 22.19.15 + '@rolldown/pluginutils@1.0.1': {} - '@rushstack/ts-command-line@5.3.3(@types/node@22.19.15)': + '@rollup/pluginutils@5.3.0': dependencies: - '@rushstack/terminal': 0.22.3(@types/node@22.19.15) - '@types/argparse': 1.0.38 - argparse: 1.0.10 - string-argv: 0.3.2 - transitivePeerDependencies: - - '@types/node' + '@types/estree': 1.0.9 + estree-walker: 2.0.2 + picomatch: 4.0.4 '@sec-ant/readable-stream@0.4.1': {} '@sindresorhus/merge-streams@4.0.0': {} + '@standard-schema/spec@1.1.0': {} + '@tokenizer/inflate@0.2.7': dependencies: debug: 4.4.3 @@ -3282,7 +2799,10 @@ snapshots: '@tokenizer/token@0.3.0': {} - '@types/argparse@1.0.38': {} + '@tybys/wasm-util@0.10.2': + dependencies: + tslib: 2.8.1 + optional: true '@types/chai@5.2.3': dependencies: @@ -3291,87 +2811,78 @@ snapshots: '@types/deep-eql@4.0.2': {} - '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} '@types/json-schema@7.0.15': {} - '@types/node@22.19.15': - dependencies: - undici-types: 6.21.0 - - '@types/node@24.12.2': + '@types/node@24.12.4': dependencies: undici-types: 7.16.0 '@types/sharp@0.31.1': dependencies: - '@types/node': 24.12.2 + '@types/node': 24.12.4 - '@vitejs/plugin-vue@5.2.4(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0))(vue@3.5.30(typescript@5.9.3))': + '@vitejs/plugin-vue@6.0.7(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1))(vue@3.5.34(typescript@5.9.3))': dependencies: - vite: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) - vue: 3.5.30(typescript@5.9.3) + '@rolldown/pluginutils': 1.0.1 + vite: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) + vue: 3.5.34(typescript@5.9.3) - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0))': + '@vitest/coverage-v8@4.1.6(vitest@4.1.6)': dependencies: - '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - ast-v8-to-istanbul: 0.3.12 - debug: 4.4.3 + '@vitest/utils': 4.1.6 + ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 istanbul-reports: 3.2.0 - magic-string: 0.30.21 - magicast: 0.3.5 - std-env: 3.10.0 - test-exclude: 7.0.2 - tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) - transitivePeerDependencies: - - supports-color + magicast: 0.5.3 + obug: 2.1.1 + std-env: 4.1.0 + tinyrainbow: 3.1.0 + vitest: 4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) - '@vitest/expect@3.2.4': + '@vitest/expect@4.1.6': dependencies: + '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 + chai: 6.2.2 + tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0))': + '@vitest/mocker@4.1.6(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1))': dependencies: - '@vitest/spy': 3.2.4 + '@vitest/spy': 4.1.6 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + vite: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) - '@vitest/pretty-format@3.2.4': + '@vitest/pretty-format@4.1.6': dependencies: - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.0 - '@vitest/runner@3.2.4': + '@vitest/runner@4.1.6': dependencies: - '@vitest/utils': 3.2.4 + '@vitest/utils': 4.1.6 pathe: 2.0.3 - strip-literal: 3.1.0 - '@vitest/snapshot@3.2.4': + '@vitest/snapshot@4.1.6': dependencies: - '@vitest/pretty-format': 3.2.4 + '@vitest/pretty-format': 4.1.6 + '@vitest/utils': 4.1.6 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.2.4': - dependencies: - tinyspy: 4.0.4 + '@vitest/spy@4.1.6': {} - '@vitest/utils@3.2.4': + '@vitest/utils@4.1.6': dependencies: - '@vitest/pretty-format': 3.2.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 + '@vitest/pretty-format': 4.1.6 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 '@volar/language-core@2.4.15': dependencies: @@ -3397,60 +2908,47 @@ snapshots: path-browserify: 1.0.1 vscode-uri: 3.1.0 - '@vue/compiler-core@3.5.30': + '@vue/compiler-core@3.5.34': dependencies: - '@babel/parser': 7.29.2 - '@vue/shared': 3.5.30 + '@babel/parser': 7.29.3 + '@vue/shared': 3.5.34 entities: 7.0.1 estree-walker: 2.0.2 source-map-js: 1.2.1 - '@vue/compiler-dom@3.5.30': + '@vue/compiler-dom@3.5.34': dependencies: - '@vue/compiler-core': 3.5.30 - '@vue/shared': 3.5.30 + '@vue/compiler-core': 3.5.34 + '@vue/shared': 3.5.34 - '@vue/compiler-sfc@3.5.30': + '@vue/compiler-sfc@3.5.34': dependencies: - '@babel/parser': 7.29.2 - '@vue/compiler-core': 3.5.30 - '@vue/compiler-dom': 3.5.30 - '@vue/compiler-ssr': 3.5.30 - '@vue/shared': 3.5.30 + '@babel/parser': 7.29.3 + '@vue/compiler-core': 3.5.34 + '@vue/compiler-dom': 3.5.34 + '@vue/compiler-ssr': 3.5.34 + '@vue/shared': 3.5.34 estree-walker: 2.0.2 magic-string: 0.30.21 - postcss: 8.5.8 + postcss: 8.5.14 source-map-js: 1.2.1 - '@vue/compiler-ssr@3.5.30': + '@vue/compiler-ssr@3.5.34': dependencies: - '@vue/compiler-dom': 3.5.30 - '@vue/shared': 3.5.30 + '@vue/compiler-dom': 3.5.34 + '@vue/shared': 3.5.34 '@vue/compiler-vue2@2.7.16': dependencies: de-indent: 1.0.2 he: 1.2.0 - '@vue/language-core@2.2.0(typescript@5.9.3)': - dependencies: - '@volar/language-core': 2.4.28 - '@vue/compiler-dom': 3.5.30 - '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.30 - alien-signals: 0.4.14 - minimatch: 9.0.9 - muggle-string: 0.4.1 - path-browserify: 1.0.1 - optionalDependencies: - typescript: 5.9.3 - '@vue/language-core@2.2.12(typescript@5.9.3)': dependencies: '@volar/language-core': 2.4.15 - '@vue/compiler-dom': 3.5.30 + '@vue/compiler-dom': 3.5.34 '@vue/compiler-vue2': 2.7.16 - '@vue/shared': 3.5.30 + '@vue/shared': 3.5.34 alien-signals: 1.0.13 minimatch: 9.0.9 muggle-string: 0.4.1 @@ -3458,29 +2956,29 @@ snapshots: optionalDependencies: typescript: 5.9.3 - '@vue/reactivity@3.5.30': + '@vue/reactivity@3.5.34': dependencies: - '@vue/shared': 3.5.30 + '@vue/shared': 3.5.34 - '@vue/runtime-core@3.5.30': + '@vue/runtime-core@3.5.34': dependencies: - '@vue/reactivity': 3.5.30 - '@vue/shared': 3.5.30 + '@vue/reactivity': 3.5.34 + '@vue/shared': 3.5.34 - '@vue/runtime-dom@3.5.30': + '@vue/runtime-dom@3.5.34': dependencies: - '@vue/reactivity': 3.5.30 - '@vue/runtime-core': 3.5.30 - '@vue/shared': 3.5.30 + '@vue/reactivity': 3.5.34 + '@vue/runtime-core': 3.5.34 + '@vue/shared': 3.5.34 csstype: 3.2.3 - '@vue/server-renderer@3.5.30(vue@3.5.30(typescript@5.9.3))': + '@vue/server-renderer@3.5.34(vue@3.5.34(typescript@5.9.3))': dependencies: - '@vue/compiler-ssr': 3.5.30 - '@vue/shared': 3.5.30 - vue: 3.5.30(typescript@5.9.3) + '@vue/compiler-ssr': 3.5.34 + '@vue/shared': 3.5.34 + vue: 3.5.34(typescript@5.9.3) - '@vue/shared@3.5.30': {} + '@vue/shared@3.5.34': {} abstract-logging@2.0.1: {} @@ -3490,30 +2988,24 @@ snapshots: acorn@8.16.0: {} - ajv-draft-04@1.0.0(ajv@8.18.0): - optionalDependencies: - ajv: 8.18.0 - - ajv-formats@3.0.1(ajv@8.18.0): + ajv-formats@3.0.1(ajv@8.20.0): optionalDependencies: - ajv: 8.18.0 + ajv: 8.20.0 - ajv@6.14.0: + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.18.0: + ajv@8.20.0: dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.2 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - alien-signals@0.4.14: {} - alien-signals@1.0.13: {} ansi-regex@5.0.1: {} @@ -3524,23 +3016,17 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.3: {} - argon2@0.43.1: dependencies: '@phc/format': 1.0.0 node-addon-api: 8.7.0 node-gyp-build: 4.8.4 - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - argparse@2.0.1: {} assertion-error@2.0.1: {} - ast-v8-to-istanbul@0.3.12: + ast-v8-to-istanbul@1.0.0: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 @@ -3555,32 +3041,18 @@ snapshots: balanced-match@1.0.2: {} - balanced-match@4.0.4: {} - - brace-expansion@1.1.12: + brace-expansion@1.1.14: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.2: + brace-expansion@2.1.0: dependencies: balanced-match: 1.0.2 - brace-expansion@5.0.4: - dependencies: - balanced-match: 4.0.4 - - cac@6.7.14: {} - callsites@3.1.0: {} - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + chai@6.2.2: {} chalk@4.1.2: dependencies: @@ -3591,8 +3063,6 @@ snapshots: chardet@2.1.1: {} - check-error@2.1.3: {} - cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -3621,6 +3091,8 @@ snapshots: content-type@2.0.0: {} + convert-source-map@2.0.0: {} + cookie@1.1.1: {} cross-spawn@7.0.6: @@ -3639,8 +3111,6 @@ snapshots: dependencies: ms: 2.1.3 - deep-eql@5.0.2: {} - deep-is@0.1.4: {} depd@2.0.0: {} @@ -3649,52 +3119,17 @@ snapshots: detect-libc@2.1.2: {} - diff@8.0.3: {} - - eastasianwidth@0.2.0: {} - emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - end-of-stream@1.4.5: dependencies: once: 1.4.0 entities@7.0.1: {} - es-module-lexer@1.7.0: {} - - esbuild@0.25.12: - optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 + es-module-lexer@2.1.0: {} esbuild@0.28.0: optionalDependencies: @@ -3746,11 +3181,11 @@ snapshots: '@eslint/eslintrc': 3.3.5 '@eslint/js': 9.39.4 '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 + '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.14.0 + '@types/estree': 1.0.9 + ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3 @@ -3795,7 +3230,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 esutils@2.0.3: {} @@ -3829,9 +3264,9 @@ snapshots: fast-json-stringify@6.4.0: dependencies: '@fastify/merge-json-schemas': 0.2.1 - ajv: 8.18.0 - ajv-formats: 3.0.1(ajv@8.18.0) - fast-uri: 3.1.0 + ajv: 8.20.0 + ajv-formats: 3.0.1(ajv@8.20.0) + fast-uri: 3.1.2 json-schema-ref-resolver: 3.0.0 rfdc: 1.4.1 @@ -3843,7 +3278,7 @@ snapshots: fast-safe-stringify@2.1.1: {} - fast-uri@3.1.0: {} + fast-uri@3.1.2: {} fastify-plugin@5.1.0: {} @@ -3862,16 +3297,16 @@ snapshots: process-warning: 5.0.0 rfdc: 1.4.1 secure-json-parse: 4.1.0 - semver: 7.7.4 + semver: 7.8.0 toad-cache: 3.7.1 fastq@1.20.1: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.3): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.3 + picomatch: 4.0.4 fflate@0.8.3: {} @@ -3905,30 +3340,17 @@ snapshots: flat-cache@4.0.1: dependencies: - flatted: 3.4.1 + flatted: 3.4.2 keyv: 4.5.4 - flatted@3.4.1: {} - - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 + flatted@3.4.2: {} forwarded@0.2.0: {} - fs-extra@11.3.4: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - - get-east-asian-width@1.5.0: {} + get-east-asian-width@1.6.0: {} get-stream@9.0.1: dependencies: @@ -3939,25 +3361,10 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.5.0: - dependencies: - foreground-child: 3.3.1 - jackspeak: 3.4.3 - minimatch: 9.0.9 - minipass: 7.1.3 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - globals@14.0.0: {} - graceful-fs@4.2.11: {} - has-flag@4.0.0: {} - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - he@1.2.0: {} help-me@5.0.0: {} @@ -3987,18 +3394,12 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 - import-lazy@4.0.0: {} - imurmurhash@0.1.4: {} inherits@2.0.4: {} ipaddr.js@2.4.0: {} - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -4027,33 +3428,15 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@5.0.6: - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - debug: 4.4.3 - istanbul-lib-coverage: 3.2.2 - transitivePeerDependencies: - - supports-color - istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jju@1.4.0: {} - joycon@3.1.1: {} js-tokens@10.0.0: {} - js-tokens@9.0.1: {} - js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -4070,12 +3453,6 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -4093,10 +3470,59 @@ snapshots: process-warning: 4.0.1 set-cookie-parser: 2.7.2 + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + local-pkg@1.1.2: dependencies: - mlly: 1.8.1 - pkg-types: 2.3.0 + mlly: 1.8.2 + pkg-types: 2.3.1 quansync: 0.2.11 locate-path@6.0.0: @@ -4105,34 +3531,24 @@ snapshots: lodash.merge@4.6.2: {} - lodash@4.17.23: {} - log-symbols@6.0.0: dependencies: chalk: 5.6.2 is-unicode-supported: 1.3.0 - loupe@3.2.1: {} - - lru-cache@10.4.3: {} - - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.3.5: + magicast@0.5.3: dependencies: - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.3 '@babel/types': 7.29.0 source-map-js: 1.2.1 make-dir@4.0.0: dependencies: - semver: 7.7.4 + semver: 7.8.0 media-typer@1.1.0: {} @@ -4144,32 +3560,22 @@ snapshots: mimic-function@5.0.1: {} - minimatch@10.2.3: - dependencies: - brace-expansion: 5.0.4 - - minimatch@10.2.4: - dependencies: - brace-expansion: 5.0.4 - minimatch@3.1.5: dependencies: - brace-expansion: 1.1.12 + brace-expansion: 1.1.14 minimatch@9.0.9: dependencies: - brace-expansion: 2.0.2 + brace-expansion: 2.1.0 minimist@1.2.8: {} - minipass@7.1.3: {} - - mlly@1.8.1: + mlly@1.8.2: dependencies: acorn: 8.16.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.3 + ufo: 1.6.4 ms@2.1.3: {} @@ -4177,7 +3583,7 @@ snapshots: mute-stream@2.0.0: {} - nanoid@3.3.11: {} + nanoid@3.3.12: {} natural-compare@1.4.0: {} @@ -4190,6 +3596,8 @@ snapshots: path-key: 4.0.0 unicorn-magic: 0.3.0 + obug@2.1.1: {} + on-exit-leak-free@2.1.2: {} once@1.4.0: @@ -4229,8 +3637,6 @@ snapshots: dependencies: p-limit: 3.1.0 - package-json-from-dist@1.0.1: {} - parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -4245,20 +3651,11 @@ snapshots: path-key@4.0.0: {} - path-parse@1.0.7: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.3 - pathe@2.0.3: {} - pathval@2.0.1: {} - picocolors@1.1.1: {} - picomatch@4.0.3: {} + picomatch@4.0.4: {} pino-abstract-transport@2.0.0: dependencies: @@ -4303,24 +3700,24 @@ snapshots: pkg-types@1.3.1: dependencies: confbox: 0.1.8 - mlly: 1.8.1 + mlly: 1.8.2 pathe: 2.0.3 - pkg-types@2.3.0: + pkg-types@2.3.1: dependencies: confbox: 0.2.4 exsolve: 1.0.8 pathe: 2.0.3 - postcss@8.5.8: + postcss@8.5.14: dependencies: - nanoid: 3.3.11 + nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 prelude-ls@1.2.1: {} - prettier@3.8.1: {} + prettier@3.8.3: {} pretty-ms@9.3.0: dependencies: @@ -4347,12 +3744,6 @@ snapshots: resolve-from@4.0.0: {} - resolve@1.22.11: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -4364,36 +3755,26 @@ snapshots: rfdc@1.4.1: {} - rollup@4.59.0: + rolldown@1.0.1: dependencies: - '@types/estree': 1.0.8 + '@oxc-project/types': 0.130.0 + '@rolldown/pluginutils': 1.0.1 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.59.0 - '@rollup/rollup-android-arm64': 4.59.0 - '@rollup/rollup-darwin-arm64': 4.59.0 - '@rollup/rollup-darwin-x64': 4.59.0 - '@rollup/rollup-freebsd-arm64': 4.59.0 - '@rollup/rollup-freebsd-x64': 4.59.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 - '@rollup/rollup-linux-arm-musleabihf': 4.59.0 - '@rollup/rollup-linux-arm64-gnu': 4.59.0 - '@rollup/rollup-linux-arm64-musl': 4.59.0 - '@rollup/rollup-linux-loong64-gnu': 4.59.0 - '@rollup/rollup-linux-loong64-musl': 4.59.0 - '@rollup/rollup-linux-ppc64-gnu': 4.59.0 - '@rollup/rollup-linux-ppc64-musl': 4.59.0 - '@rollup/rollup-linux-riscv64-gnu': 4.59.0 - '@rollup/rollup-linux-riscv64-musl': 4.59.0 - '@rollup/rollup-linux-s390x-gnu': 4.59.0 - '@rollup/rollup-linux-x64-gnu': 4.59.0 - '@rollup/rollup-linux-x64-musl': 4.59.0 - '@rollup/rollup-openbsd-x64': 4.59.0 - '@rollup/rollup-openharmony-arm64': 4.59.0 - '@rollup/rollup-win32-arm64-msvc': 4.59.0 - '@rollup/rollup-win32-ia32-msvc': 4.59.0 - '@rollup/rollup-win32-x64-gnu': 4.59.0 - '@rollup/rollup-win32-x64-msvc': 4.59.0 - fsevents: 2.3.3 + '@rolldown/binding-android-arm64': 1.0.1 + '@rolldown/binding-darwin-arm64': 1.0.1 + '@rolldown/binding-darwin-x64': 1.0.1 + '@rolldown/binding-freebsd-x64': 1.0.1 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.1 + '@rolldown/binding-linux-arm64-gnu': 1.0.1 + '@rolldown/binding-linux-arm64-musl': 1.0.1 + '@rolldown/binding-linux-ppc64-gnu': 1.0.1 + '@rolldown/binding-linux-s390x-gnu': 1.0.1 + '@rolldown/binding-linux-x64-gnu': 1.0.1 + '@rolldown/binding-linux-x64-musl': 1.0.1 + '@rolldown/binding-openharmony-arm64': 1.0.1 + '@rolldown/binding-wasm32-wasi': 1.0.1 + '@rolldown/binding-win32-arm64-msvc': 1.0.1 + '@rolldown/binding-win32-x64-msvc': 1.0.1 safe-regex2@5.1.1: dependencies: @@ -4405,11 +3786,7 @@ snapshots: secure-json-parse@4.1.0: {} - semver@7.5.4: - dependencies: - lru-cache: 6.0.0 - - semver@7.7.4: {} + semver@7.8.0: {} set-cookie-parser@2.7.2: {} @@ -4419,7 +3796,7 @@ snapshots: dependencies: '@img/colour': 1.1.0 detect-libc: 2.1.2 - semver: 7.7.4 + semver: 7.8.0 optionalDependencies: '@img/sharp-darwin-arm64': 0.34.5 '@img/sharp-darwin-x64': 0.34.5 @@ -4462,38 +3839,26 @@ snapshots: source-map-js@1.2.1: {} - source-map@0.6.1: {} - split2@4.2.0: {} - sprintf-js@1.0.3: {} - stackback@0.0.2: {} statuses@2.0.2: {} - std-env@3.10.0: {} + std-env@4.1.0: {} stdin-discarder@0.2.2: {} - string-argv@0.3.2: {} - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.2.0 - string-width@7.2.0: dependencies: emoji-regex: 10.6.0 - get-east-asian-width: 1.5.0 + get-east-asian-width: 1.6.0 strip-ansi: 7.2.0 strip-ansi@6.0.1: @@ -4510,10 +3875,6 @@ snapshots: strip-json-comments@5.0.3: {} - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 - strtok3@10.3.5: dependencies: '@tokenizer/token': 0.3.0 @@ -4522,36 +3883,20 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - - test-exclude@7.0.2: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 10.5.0 - minimatch: 10.2.4 - thread-stream@3.1.0: dependencies: real-require: 0.2.0 tinybench@2.9.0: {} - tinyexec@0.3.2: {} + tinyexec@1.1.2: {} - tinyglobby@0.2.15: + tinyglobby@0.2.16: dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 - tinyspy@4.0.4: {} + tinyrainbow@3.1.0: {} toad-cache@3.7.1: {} @@ -4566,7 +3911,7 @@ snapshots: tslib@2.8.1: optional: true - tsx@4.22.0: + tsx@4.22.1: dependencies: esbuild: 0.28.0 optionalDependencies: @@ -4582,121 +3927,101 @@ snapshots: media-typer: 1.1.0 mime-types: 3.0.2 - typescript@5.8.2: {} - typescript@5.9.3: {} - ufo@1.6.3: {} + ufo@1.6.4: {} uint8array-extras@1.5.0: {} - undici-types@6.21.0: {} - undici-types@7.16.0: {} unicorn-magic@0.3.0: {} - universalify@2.0.1: {} - - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - vary@1.1.2: {} - - vite-node@3.2.4(@types/node@22.19.15)(tsx@4.22.0): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - vite-plugin-dts@4.5.4(@types/node@22.19.15)(rollup@4.59.0)(typescript@5.9.3)(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)): + unplugin-dts@1.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)): dependencies: - '@microsoft/api-extractor': 7.57.7(@types/node@22.19.15) - '@rollup/pluginutils': 5.3.0(rollup@4.59.0) + '@rollup/pluginutils': 5.3.0 '@volar/typescript': 2.4.28 - '@vue/language-core': 2.2.0(typescript@5.9.3) compare-versions: 6.1.1 debug: 4.4.3 kolorist: 1.8.0 local-pkg: 1.1.2 magic-string: 0.30.21 typescript: 5.9.3 + unplugin: 2.3.11 optionalDependencies: - vite: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) + esbuild: 0.28.0 + rolldown: 1.0.1 + vite: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) transitivePeerDependencies: - - '@types/node' - - rollup - supports-color - vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0): + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + vary@1.1.2: {} + + vite-plugin-dts@5.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)): dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.8 - rollup: 4.59.0 - tinyglobby: 0.2.15 + unplugin-dts: 1.0.0(esbuild@0.28.0)(rolldown@1.0.1)(typescript@5.9.3)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) optionalDependencies: - '@types/node': 22.19.15 - fsevents: 2.3.3 - tsx: 4.22.0 + vite: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) + transitivePeerDependencies: + - '@rspack/core' + - '@vue/language-core' + - esbuild + - rolldown + - supports-color + - typescript + - webpack - vitest@3.2.4(@types/node@22.19.15)(tsx@4.22.0): + vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1): dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.4.1(@types/node@22.19.15)(tsx@4.22.0)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.2.4 - '@vitest/snapshot': 3.2.4 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - debug: 4.4.3 + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.14 + rolldown: 1.0.1 + tinyglobby: 0.2.16 + optionalDependencies: + '@types/node': 24.12.4 + esbuild: 0.28.0 + fsevents: 2.3.3 + tsx: 4.22.1 + + vitest@4.1.6(@types/node@24.12.4)(@vitest/coverage-v8@4.1.6)(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)): + dependencies: + '@vitest/expect': 4.1.6 + '@vitest/mocker': 4.1.6(vite@8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1)) + '@vitest/pretty-format': 4.1.6 + '@vitest/runner': 4.1.6 + '@vitest/snapshot': 4.1.6 + '@vitest/spy': 4.1.6 + '@vitest/utils': 4.1.6 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 + obug: 2.1.1 pathe: 2.0.3 - picomatch: 4.0.3 - std-env: 3.10.0 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 0.3.2 - tinyglobby: 0.2.15 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 - vite: 6.4.1(@types/node@22.19.15)(tsx@4.22.0) - vite-node: 3.2.4(@types/node@22.19.15)(tsx@4.22.0) + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 8.0.13(@types/node@24.12.4)(esbuild@0.28.0)(tsx@4.22.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.19.15 + '@types/node': 24.12.4 + '@vitest/coverage-v8': 4.1.6(vitest@4.1.6) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml vscode-uri@3.1.0: {} @@ -4706,16 +4031,18 @@ snapshots: '@vue/language-core': 2.2.12(typescript@5.9.3) typescript: 5.9.3 - vue@3.5.30(typescript@5.9.3): + vue@3.5.34(typescript@5.9.3): dependencies: - '@vue/compiler-dom': 3.5.30 - '@vue/compiler-sfc': 3.5.30 - '@vue/runtime-dom': 3.5.30 - '@vue/server-renderer': 3.5.30(vue@3.5.30(typescript@5.9.3)) - '@vue/shared': 3.5.30 + '@vue/compiler-dom': 3.5.34 + '@vue/compiler-sfc': 3.5.34 + '@vue/runtime-dom': 3.5.34 + '@vue/server-renderer': 3.5.34(vue@3.5.34(typescript@5.9.3)) + '@vue/shared': 3.5.34 optionalDependencies: typescript: 5.9.3 + webpack-virtual-modules@0.6.2: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -4733,22 +4060,8 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.2.0 - wrappy@1.0.2: {} - yallist@4.0.0: {} - yocto-queue@0.1.0: {} yoctocolors-cjs@2.1.3: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index be01758a..dfc77860 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -5,5 +5,6 @@ packages: - 'extensions/*/packages/*' allowBuilds: + argon2: true esbuild: true sharp: false diff --git a/pom.xml b/pom.xml index 95797d86..6e69f34b 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 4.0.0 tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 pom Dynamia Soluciones IT SAS @@ -63,7 +63,7 @@ 10.2.1-jakarta - 1.1.0 + 1.2.0 2.44.5 8.5.17 diff --git a/themes/pom.xml b/themes/pom.xml index 85de2ed5..9a95a3d8 100644 --- a/themes/pom.xml +++ b/themes/pom.xml @@ -6,7 +6,7 @@ tools.dynamia tools.dynamia.parent - 26.5.1 + 26.5.2 ../pom.xml diff --git a/themes/theme-dynamical/sources/pom.xml b/themes/theme-dynamical/sources/pom.xml index 17c37bfe..9b694a07 100644 --- a/themes/theme-dynamical/sources/pom.xml +++ b/themes/theme-dynamical/sources/pom.xml @@ -24,7 +24,7 @@ tools.dynamia.themes tools.dynamia.themes.parent - 26.5.1 + 26.5.2 ../../pom.xml @@ -102,7 +102,7 @@ tools.dynamia tools.dynamia.zk - 26.5.1 + 26.5.2 provided diff --git a/tsconfig.base.json b/tsconfig.base.json index a8b019bb..71ab6912 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,9 +1,9 @@ { "compilerOptions": { - "target": "ES2022", + "target": "ES2023", "module": "ESNext", "moduleResolution": "bundler", - "lib": ["ES2022", "DOM"], + "lib": ["ES2023", "DOM"], "strict": true, "exactOptionalPropertyTypes": true, "noUncheckedIndexedAccess": true,