diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6c0e966..ac74e58 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,6 +30,9 @@ jobs:
- name: Run frontend checks
run: pnpm check
+ - name: Validate OpenAPI contract
+ run: pnpm api:lint
+
test:
name: PHP ${{ matrix.php }}
runs-on: ubuntu-latest
diff --git a/.spectral.yaml b/.spectral.yaml
new file mode 100644
index 0000000..47000fd
--- /dev/null
+++ b/.spectral.yaml
@@ -0,0 +1,9 @@
+extends:
+ - spectral:oas
+
+rules:
+ operation-description: off
+ operation-tags: error
+ operation-operationId: error
+ operation-operationId-unique: error
+ path-params: error
diff --git a/README.md b/README.md
index a31744e..14f9490 100644
--- a/README.md
+++ b/README.md
@@ -159,6 +159,7 @@ Start your web server and navigate to:
See:
- `docs/public-api.md` (HTTP + WebSocket + frontend entrypoints + reusable PHP APIs)
+- `docs/openapi.yaml` (machine-readable OpenAPI 3.1 contract, rendered at `/api/docs`)
- `docs/api.md` (message reaction HTTP and WebSocket contracts)
- `docs/user-profiles.md` (profile settings, avatars, themes, and WebSocket presence)
- `docs/channels.md` (public channels, private DMs, APIs, WebSocket routing, and migration operations)
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index 785f5da..57d5334 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -31,6 +31,8 @@
$routes->get('chat/svelte', 'Chat::svelte');
// Stable, machine-consumed API routes.
+$routes->get('api/docs', 'ApiDocs::index');
+
$routes->group('api/v1', ['namespace' => 'App\Controllers\Api\V1'], static function (RouteCollection $routes): void {
$routes->get('messages', 'MessagesController::list', ['filter' => ['apiFormat', 'auth']]);
$routes->get('messages/search', 'MessagesController::search', ['filter' => ['apiFormat', 'auth']]);
diff --git a/app/Config/Services.php b/app/Config/Services.php
index 5ec37ba..b699084 100644
--- a/app/Config/Services.php
+++ b/app/Config/Services.php
@@ -15,6 +15,7 @@
use App\Controllers\Api\V1\MessagesController;
use App\Controllers\Api\V1\PushSubscriptionsController;
use App\Controllers\Api\V1\ReactionsController;
+use App\Controllers\ApiDocs;
use App\Controllers\AuditLog;
use App\Controllers\Auth;
use App\Controllers\Chat;
@@ -72,6 +73,7 @@ public static function controller(string $controllerClass): Controller
return match ($controllerClass) {
Home::class => new Home(),
+ ApiDocs::class => new ApiDocs(),
Chat::class => new Chat(static::chatRepository(), static::chatFormatter()),
MessagesController::class => new MessagesController(static::chatRepository(), static::chatFormatter()),
ChannelsController::class => new ChannelsController(static::channelRepository(), static::chatRepository(), static::userRepository()),
diff --git a/app/Controllers/ApiDocs.php b/app/Controllers/ApiDocs.php
new file mode 100644
index 0000000..e1390d3
--- /dev/null
+++ b/app/Controllers/ApiDocs.php
@@ -0,0 +1,23 @@
+response
+ ->setStatusCode(500)
+ ->setHeader('Content-Type', 'text/plain; charset=UTF-8')
+ ->setBody('The OpenAPI specification is unavailable.');
+ }
+
+ return $this->respondWithView('api/docs', [
+ 'openapiBase64' => base64_encode($spec),
+ ], cacheable: true, cacheTime: 300);
+ }
+}
diff --git a/app/Views/api/docs.php b/app/Views/api/docs.php
new file mode 100644
index 0000000..cd32a21
--- /dev/null
+++ b/app/Views/api/docs.php
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ CodeIgniter Chat API documentation
+
+ = vite_css_tag('src/js/api-docs.js') ?>
+
+
+
+
+
+ = vite_js_tag('src/js/api-docs.js') ?>
+
+
diff --git a/docs/contributing.md b/docs/contributing.md
index 8e66564..d076d38 100755
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -64,6 +64,23 @@ pnpm format
Please ensure the PHP and frontend checks pass before submitting a pull request. Biome covers repository JavaScript and TypeScript; framework-aware diagnostics are handled separately by `svelte-check` and `vue-tsc`.
+### API contract
+
+`docs/openapi.yaml` is the reviewed source of truth for every `/api/v1/*`
+operation. When a pull request adds, removes, or changes a versioned endpoint,
+update the OpenAPI operation, schemas, status codes, and concrete examples in
+the same pull request.
+
+Validate the contract locally with:
+
+```bash
+pnpm api:lint
+```
+
+This runs Spectral's OpenAPI 3.1 rules and compares the documented operations
+with the CodeIgniter route group. CI rejects invalid specifications and route
+drift. The rendered contract is available at `/api/docs` in a running app.
+
## Code Style Guidelines
- Follow PSR-12 coding standards (enforced by PHP-CS-Fixer)
diff --git a/docs/openapi.yaml b/docs/openapi.yaml
new file mode 100644
index 0000000..81864f5
--- /dev/null
+++ b/docs/openapi.yaml
@@ -0,0 +1,1458 @@
+openapi: 3.1.0
+info:
+ title: CodeIgniter Chat API
+ version: 1.0.0
+ description: |
+ Contract for the versioned HTTP API. Browser clients authenticate with the
+ CodeIgniter session cookie. Mutating requests also send the current CSRF
+ token in the `X-CSRF-TOKEN` header or form body.
+
+ The YAML file is the source of truth. Generated client SDKs are a possible
+ follow-up and are intentionally not shipped by this project.
+ contact:
+ name: CodeIgniter Chat maintainers
+ url: https://github.com/llbbl/codeigniter-chat
+servers:
+ - url: /
+ description: Current application origin
+ - url: http://localhost:8080
+ description: Local development
+ - url: https://chat.example.com
+ description: Production placeholder
+tags:
+ - name: Messages
+ - name: Channels
+ - name: Reactions
+ - name: Push subscriptions
+ - name: Profiles
+security:
+ - sessionAuth: []
+paths:
+ /api/v1/messages:
+ get:
+ operationId: listMessages
+ tags: [Messages]
+ summary: List messages in the general channel
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PerPage'
+ responses:
+ '200':
+ $ref: '#/components/responses/GeneralMessagePage'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ post:
+ operationId: createGeneralMessage
+ tags: [Messages]
+ summary: Create a message in the general channel
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/x-www-form-urlencoded:
+ schema:
+ type: object
+ required: [message]
+ properties:
+ message:
+ type: string
+ minLength: 1
+ maxLength: 500
+ example:
+ message: Hello from the API
+ responses:
+ '200':
+ description: Message created.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Success'
+ example:
+ success: true
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/messages/search:
+ get:
+ operationId: searchMessages
+ tags: [Messages]
+ summary: Search live messages in the general channel
+ description: At least one of `text`, `user`, `from`, or `to` is required.
+ parameters:
+ - $ref: '#/components/parameters/SearchText'
+ - $ref: '#/components/parameters/SearchUser'
+ - $ref: '#/components/parameters/FromTimestamp'
+ - $ref: '#/components/parameters/ToTimestamp'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PerPage'
+ responses:
+ '200':
+ description: Matching messages, pagination, and normalized filters.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/MessageSearchResult'
+ example:
+ messages:
+ - id: 42
+ channel_id: 1
+ user: alice
+ msg: Hello from class
+ time: 1700000000
+ pagination:
+ page: 1
+ perPage: 10
+ totalItems: 1
+ totalPages: 1
+ hasNext: false
+ hasPrev: false
+ filters:
+ text: Hello
+ user: alice
+ from: 1699990000
+ to: 1700010000
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ /api/v1/messages/xml:
+ get:
+ operationId: listMessagesXml
+ tags: [Messages]
+ summary: List general-channel messages as XML
+ parameters:
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PerPage'
+ responses:
+ '200':
+ description: XML message page.
+ content:
+ text/xml:
+ schema:
+ type: string
+ example: '111011falsefalse42aliceHello'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ /api/v1/channels:
+ get:
+ operationId: listChannels
+ tags: [Channels]
+ summary: List channels visible to the current user
+ responses:
+ '200':
+ description: Visible public channels and joined direct messages.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [channels]
+ properties:
+ channels:
+ type: array
+ items:
+ $ref: '#/components/schemas/Channel'
+ example:
+ channels:
+ - id: 1
+ name: General
+ slug: general
+ channel_type: public
+ topic: General conversation
+ created_by: null
+ archived_at: null
+ created_at: '2026-09-18 10:00:00'
+ updated_at: '2026-09-18 10:00:00'
+ last_read_message_id: 41
+ unread_count: 1
+ is_member: true
+ members: [alice, bob]
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ post:
+ operationId: createChannel
+ tags: [Channels]
+ summary: Create a public channel
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ChannelCreateInput'
+ example:
+ name: Project Room
+ slug: project-room
+ topic: Planning the next release
+ responses:
+ '201':
+ $ref: '#/components/responses/ChannelResult'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '409':
+ $ref: '#/components/responses/Conflict'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/channels/{channelId}:
+ patch:
+ operationId: updateChannel
+ tags: [Channels]
+ summary: Update a public channel as its creator
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ChannelUpdateInput'
+ example:
+ name: Release Room
+ topic: Release coordination
+ archived: false
+ responses:
+ '200':
+ $ref: '#/components/responses/ChannelResult'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '409':
+ $ref: '#/components/responses/Conflict'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/channels/{channelId}/join:
+ post:
+ operationId: joinChannel
+ tags: [Channels]
+ summary: Join an active public channel
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/CsrfToken'
+ responses:
+ '200':
+ $ref: '#/components/responses/ChannelResult'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/channels/{channelId}/leave:
+ post:
+ operationId: leaveChannel
+ tags: [Channels]
+ summary: Leave a public channel
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/CsrfToken'
+ responses:
+ '200':
+ description: Membership removed.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Success'
+ example:
+ success: true
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ /api/v1/channels/{channelId}/messages:
+ get:
+ operationId: listChannelMessages
+ tags: [Messages]
+ summary: List live or cursor-based channel history
+ description: Use `before`/`limit` for live plus archived cursor history, or `page`/`per_page` for live-message pagination.
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/BeforeMessageId'
+ - $ref: '#/components/parameters/Limit'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PerPage'
+ responses:
+ '200':
+ $ref: '#/components/responses/ChannelMessagePage'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ post:
+ operationId: createChannelMessage
+ tags: [Messages]
+ summary: Create a message in a joined channel
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [message]
+ properties:
+ message:
+ type: string
+ minLength: 1
+ maxLength: 500
+ example:
+ message: Channel-only update
+ responses:
+ '201':
+ description: Created message.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [message]
+ properties:
+ message:
+ $ref: '#/components/schemas/CreatedMessage'
+ example:
+ message:
+ id: 43
+ channel_id: 7
+ user: alice
+ msg: Channel-only update
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/channels/{channelId}/messages/search:
+ get:
+ operationId: searchChannelMessages
+ tags: [Messages]
+ summary: Search live messages in a joined channel
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/SearchText'
+ - $ref: '#/components/parameters/SearchUser'
+ - $ref: '#/components/parameters/FromTimestamp'
+ - $ref: '#/components/parameters/ToTimestamp'
+ - $ref: '#/components/parameters/Page'
+ - $ref: '#/components/parameters/PerPage'
+ responses:
+ '200':
+ description: Channel-scoped search result.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/MessageSearchResult'
+ example:
+ messages:
+ - id: 43
+ channel_id: 7
+ user: alice
+ msg: Channel-only update
+ time: 1700000001
+ pagination:
+ page: 1
+ perPage: 10
+ totalItems: 1
+ totalPages: 1
+ hasNext: false
+ hasPrev: false
+ filters:
+ text: update
+ user: alice
+ from: null
+ to: null
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ /api/v1/channels/{channelId}/export:
+ get:
+ operationId: exportChannelMessages
+ tags: [Messages]
+ summary: Download all live and archived messages in a joined channel
+ parameters:
+ - $ref: '#/components/parameters/ChannelId'
+ - $ref: '#/components/parameters/ExportFormat'
+ responses:
+ '200':
+ $ref: '#/components/responses/MessageExport'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '403':
+ $ref: '#/components/responses/Forbidden'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/users/me/export:
+ get:
+ operationId: exportMyMessages
+ tags: [Messages]
+ summary: Download all live and archived messages authored by the current user
+ parameters:
+ - $ref: '#/components/parameters/ExportFormat'
+ responses:
+ '200':
+ $ref: '#/components/responses/MessageExport'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/dms:
+ post:
+ operationId: createDirectMessage
+ tags: [Channels]
+ summary: Find or create a direct-message channel
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - type: object
+ required: [user_id]
+ properties:
+ user_id:
+ type: integer
+ minimum: 1
+ - type: object
+ required: [username]
+ properties:
+ username:
+ type: string
+ minLength: 3
+ maxLength: 30
+ example:
+ username: bob
+ responses:
+ '201':
+ $ref: '#/components/responses/ChannelResult'
+ '400':
+ $ref: '#/components/responses/BadRequest'
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/messages/{messageId}/reactions:
+ get:
+ operationId: listMessageReactions
+ tags: [Reactions]
+ summary: List reactions for an accessible live message
+ parameters:
+ - $ref: '#/components/parameters/MessageId'
+ responses:
+ '200':
+ description: Aggregated reaction groups.
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Reaction'
+ example:
+ - emoji: 👍
+ count: 2
+ users: [alice, bob]
+ reacted_by_current_user: true
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ post:
+ operationId: createMessageReaction
+ tags: [Reactions]
+ summary: Add the current user's reaction
+ parameters:
+ - $ref: '#/components/parameters/MessageId'
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [emoji]
+ properties:
+ emoji:
+ type: string
+ minLength: 1
+ maxLength: 10
+ example:
+ emoji: 👍
+ responses:
+ '201':
+ description: Current aggregate for the saved emoji.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [message_id, reaction]
+ properties:
+ message_id:
+ type: integer
+ reaction:
+ $ref: '#/components/schemas/Reaction'
+ example:
+ message_id: 42
+ reaction:
+ emoji: 👍
+ count: 2
+ users: [alice, bob]
+ reacted_by_current_user: true
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/messages/{messageId}/reactions/{emoji}:
+ delete:
+ operationId: deleteMessageReaction
+ tags: [Reactions]
+ summary: Remove the current user's reaction
+ parameters:
+ - $ref: '#/components/parameters/MessageId'
+ - name: emoji
+ in: path
+ required: true
+ description: URL-encoded emoji.
+ schema:
+ type: string
+ minLength: 1
+ maxLength: 10
+ example: 👍
+ - $ref: '#/components/parameters/CsrfToken'
+ responses:
+ '204':
+ description: Reaction removed; no response body.
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ /api/v1/push-subscriptions:
+ post:
+ operationId: savePushSubscription
+ tags: [Push subscriptions]
+ summary: Save or replace a browser push subscription
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PushSubscriptionInput'
+ example:
+ endpoint: https://push.example.test/subscriptions/abc123
+ keys:
+ p256dh: BPV1_public_key_material
+ auth: auth_secret
+ responses:
+ '201':
+ description: Subscription saved.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Success'
+ example:
+ success: true
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ delete:
+ operationId: deletePushSubscription
+ tags: [Push subscriptions]
+ summary: Delete a browser push subscription
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [endpoint]
+ properties:
+ endpoint:
+ type: string
+ format: uri
+ maxLength: 2048
+ example:
+ endpoint: https://push.example.test/subscriptions/abc123
+ responses:
+ '204':
+ description: Subscription removed; no response body.
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ /api/v1/profile:
+ get:
+ operationId: getCurrentProfile
+ tags: [Profiles]
+ summary: Get the current user's private profile
+ responses:
+ '200':
+ description: Current profile and a fresh CSRF token.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [profile, csrf_token]
+ properties:
+ profile:
+ $ref: '#/components/schemas/PrivateProfile'
+ csrf_token:
+ type: string
+ example:
+ profile:
+ id: 7
+ username: alice
+ display_name: Alice Example
+ avatar_url: https://chat.example.com/profile/avatar/7
+ presence: online
+ last_seen_at: '2026-09-18 10:00:00'
+ email: alice@example.com
+ theme: dark
+ notification_prefs:
+ desktop: true
+ sound: false
+ csrf_token: 8e90d72f31e54e9aa26760cf6f26a06f
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '404':
+ $ref: '#/components/responses/NotFound'
+ post:
+ operationId: updateCurrentProfile
+ tags: [Profiles]
+ summary: Update the current user's profile preferences
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProfileUpdateInput'
+ example:
+ display_name: Alice Example
+ theme: dark
+ presence: online
+ notification_prefs:
+ desktop: true
+ sound: false
+ responses:
+ '200':
+ description: Updated profile and fresh CSRF token.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [profile, csrf_token]
+ properties:
+ profile:
+ $ref: '#/components/schemas/PrivateProfile'
+ csrf_token:
+ type: string
+ example:
+ profile:
+ id: 7
+ username: alice
+ display_name: Alice Example
+ avatar_url: null
+ presence: online
+ last_seen_at: '2026-09-18 10:00:00'
+ email: alice@example.com
+ theme: dark
+ notification_prefs:
+ desktop: true
+ sound: false
+ csrf_token: 8e90d72f31e54e9aa26760cf6f26a06f
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/profile/avatar:
+ post:
+ operationId: uploadProfileAvatar
+ tags: [Profiles]
+ summary: Upload and normalize the current user's avatar
+ parameters:
+ - $ref: '#/components/parameters/CsrfToken'
+ requestBody:
+ required: true
+ content:
+ multipart/form-data:
+ schema:
+ type: object
+ required: [avatar]
+ properties:
+ avatar:
+ type: string
+ format: binary
+ encoding:
+ avatar:
+ contentType: image/jpeg, image/png, image/webp
+ responses:
+ '201':
+ description: Avatar saved and resized to WebP.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [avatar_url, csrf_token]
+ properties:
+ avatar_url:
+ type: string
+ format: uri
+ csrf_token:
+ type: string
+ example:
+ avatar_url: https://chat.example.com/profile/avatar/7
+ csrf_token: 8e90d72f31e54e9aa26760cf6f26a06f
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+ '422':
+ $ref: '#/components/responses/UnprocessableEntity'
+ '429':
+ $ref: '#/components/responses/RateLimited'
+ '500':
+ $ref: '#/components/responses/ServerError'
+ /api/v1/profiles:
+ get:
+ operationId: listPublicProfiles
+ tags: [Profiles]
+ summary: Resolve up to 50 public profiles by username
+ parameters:
+ - name: usernames
+ in: query
+ required: true
+ description: Comma-separated usernames; at most the first 50 are used.
+ schema:
+ type: string
+ example: alice,bob
+ responses:
+ '200':
+ description: Matching public profiles and a fresh CSRF token.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [profiles, csrf_token]
+ properties:
+ profiles:
+ type: array
+ items:
+ $ref: '#/components/schemas/PublicProfile'
+ csrf_token:
+ type: string
+ example:
+ profiles:
+ - id: 7
+ username: alice
+ display_name: Alice Example
+ avatar_url: https://chat.example.com/profile/avatar/7
+ presence: online
+ last_seen_at: '2026-09-18 10:00:00'
+ - id: 8
+ username: bob
+ display_name: bob
+ avatar_url: null
+ presence: away
+ last_seen_at: '2026-09-18 09:55:00'
+ csrf_token: 8e90d72f31e54e9aa26760cf6f26a06f
+ '401':
+ $ref: '#/components/responses/Unauthorized'
+components:
+ securitySchemes:
+ sessionAuth:
+ type: apiKey
+ in: cookie
+ name: ci_session
+ description: CodeIgniter browser session cookie.
+ apiKeyAuth:
+ type: apiKey
+ in: header
+ name: X-API-Key
+ description: Reserved for a future non-browser authentication flow; not currently accepted.
+ parameters:
+ ChannelId:
+ name: channelId
+ in: path
+ required: true
+ schema:
+ type: integer
+ minimum: 1
+ example: 7
+ MessageId:
+ name: messageId
+ in: path
+ required: true
+ schema:
+ type: integer
+ minimum: 1
+ example: 42
+ CsrfToken:
+ name: X-CSRF-TOKEN
+ in: header
+ required: true
+ schema:
+ type: string
+ example: 8e90d72f31e54e9aa26760cf6f26a06f
+ Page:
+ name: page
+ in: query
+ schema:
+ type: integer
+ minimum: 1
+ default: 1
+ example: 1
+ PerPage:
+ name: per_page
+ in: query
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 10
+ example: 10
+ BeforeMessageId:
+ name: before
+ in: query
+ description: Return messages with IDs lower than this cursor.
+ schema:
+ type: integer
+ minimum: 1
+ example: 100
+ Limit:
+ name: limit
+ in: query
+ schema:
+ type: integer
+ minimum: 1
+ maximum: 100
+ default: 25
+ example: 25
+ SearchText:
+ name: text
+ in: query
+ schema:
+ type: string
+ minLength: 1
+ maxLength: 500
+ example: release notes
+ SearchUser:
+ name: user
+ in: query
+ schema:
+ type: string
+ minLength: 1
+ maxLength: 30
+ example: alice
+ FromTimestamp:
+ name: from
+ in: query
+ schema:
+ type: integer
+ minimum: 0
+ example: 1699990000
+ ToTimestamp:
+ name: to
+ in: query
+ schema:
+ type: integer
+ minimum: 0
+ example: 1700010000
+ ExportFormat:
+ name: format
+ in: query
+ schema:
+ type: string
+ enum: [json, csv]
+ default: json
+ example: json
+ schemas:
+ Success:
+ type: object
+ required: [success]
+ properties:
+ success:
+ type: boolean
+ const: true
+ Message:
+ type: object
+ required: [id, channel_id, user, msg, time]
+ properties:
+ id:
+ type: integer
+ channel_id:
+ type: integer
+ user:
+ type: string
+ description: Current username, or `[deleted]` after account deletion.
+ msg:
+ type: string
+ minLength: 1
+ maxLength: 500
+ time:
+ type: integer
+ minimum: 1
+ archived:
+ type: integer
+ enum: [0, 1]
+ description: Present on cursor history and exports.
+ CreatedMessage:
+ type: object
+ required: [id, channel_id, user, msg]
+ properties:
+ id:
+ type: integer
+ channel_id:
+ type: integer
+ user:
+ type: string
+ msg:
+ type: string
+ minLength: 1
+ maxLength: 500
+ Pagination:
+ type: object
+ required: [page, perPage, totalItems, totalPages, hasNext, hasPrev]
+ properties:
+ page:
+ type: integer
+ minimum: 1
+ perPage:
+ type: integer
+ minimum: 1
+ totalItems:
+ type: integer
+ minimum: 0
+ totalPages:
+ type: integer
+ minimum: 0
+ hasNext:
+ type: boolean
+ hasPrev:
+ type: boolean
+ MessagePage:
+ type: object
+ required: [messages, pagination]
+ properties:
+ messages:
+ type: array
+ items:
+ $ref: '#/components/schemas/Message'
+ pagination:
+ $ref: '#/components/schemas/Pagination'
+ GeneralMessagePage:
+ allOf:
+ - $ref: '#/components/schemas/MessagePage'
+ - type: object
+ required: [status, time]
+ properties:
+ status:
+ type: integer
+ enum: [1, 2]
+ description: "1 when messages are present and 2 when the page is empty."
+ time:
+ type: integer
+ minimum: 1
+ CursorPagination:
+ type: object
+ required: [limit, nextBefore, hasMore]
+ properties:
+ limit:
+ type: integer
+ minimum: 1
+ maximum: 100
+ nextBefore:
+ type: [integer, 'null']
+ minimum: 1
+ hasMore:
+ type: boolean
+ ChannelMessagePage:
+ oneOf:
+ - $ref: '#/components/schemas/MessagePage'
+ - type: object
+ required: [messages, pagination]
+ properties:
+ messages:
+ type: array
+ items:
+ $ref: '#/components/schemas/Message'
+ pagination:
+ $ref: '#/components/schemas/CursorPagination'
+ MessageSearchResult:
+ allOf:
+ - $ref: '#/components/schemas/MessagePage'
+ - type: object
+ required: [filters]
+ properties:
+ filters:
+ type: object
+ required: [text, user, from, to]
+ properties:
+ text:
+ type: [string, 'null']
+ user:
+ type: [string, 'null']
+ from:
+ type: [integer, 'null']
+ minimum: 0
+ to:
+ type: [integer, 'null']
+ minimum: 0
+ Channel:
+ type: object
+ required: [id, name, slug, channel_type]
+ properties:
+ id:
+ type: integer
+ name:
+ type: string
+ maxLength: 80
+ slug:
+ type: string
+ pattern: '^[a-z0-9-]{3,50}$'
+ channel_type:
+ type: string
+ enum: [public, dm]
+ topic:
+ type: [string, 'null']
+ maxLength: 200
+ created_by:
+ type: [integer, 'null']
+ archived_at:
+ type: [string, 'null']
+ created_at:
+ type: [string, 'null']
+ updated_at:
+ type: [string, 'null']
+ last_read_message_id:
+ type: [integer, 'null']
+ unread_count:
+ type: integer
+ minimum: 0
+ is_member:
+ type: boolean
+ members:
+ type: array
+ items:
+ type: string
+ ChannelCreateInput:
+ type: object
+ required: [name, slug]
+ properties:
+ name:
+ type: string
+ minLength: 1
+ maxLength: 80
+ slug:
+ type: string
+ pattern: '^[a-z0-9-]{3,50}$'
+ topic:
+ type: [string, 'null']
+ maxLength: 200
+ ChannelUpdateInput:
+ type: object
+ minProperties: 1
+ properties:
+ name:
+ type: string
+ minLength: 1
+ maxLength: 80
+ slug:
+ type: string
+ pattern: '^[a-z0-9-]{3,50}$'
+ topic:
+ type: [string, 'null']
+ maxLength: 200
+ archived:
+ type: boolean
+ Reaction:
+ type: object
+ required: [emoji, count, users, reacted_by_current_user]
+ properties:
+ emoji:
+ type: string
+ minLength: 1
+ maxLength: 10
+ count:
+ type: integer
+ minimum: 0
+ users:
+ type: array
+ items:
+ type: string
+ reacted_by_current_user:
+ type: boolean
+ PushSubscriptionInput:
+ type: object
+ required: [endpoint, keys]
+ properties:
+ endpoint:
+ type: string
+ format: uri
+ maxLength: 2048
+ keys:
+ type: object
+ required: [p256dh, auth]
+ properties:
+ p256dh:
+ type: string
+ minLength: 1
+ maxLength: 255
+ auth:
+ type: string
+ minLength: 1
+ maxLength: 255
+ PublicProfile:
+ type: object
+ required: [id, username, display_name, avatar_url, presence, last_seen_at]
+ properties:
+ id:
+ type: integer
+ username:
+ type: string
+ pattern: '^[A-Za-z0-9_]{3,30}$'
+ display_name:
+ type: string
+ maxLength: 100
+ avatar_url:
+ type: [string, 'null']
+ format: uri
+ presence:
+ type: string
+ enum: [online, away, busy, offline]
+ last_seen_at:
+ type: [string, 'null']
+ PrivateProfile:
+ allOf:
+ - $ref: '#/components/schemas/PublicProfile'
+ - type: object
+ required: [email, theme, notification_prefs]
+ properties:
+ email:
+ type: string
+ format: email
+ theme:
+ type: string
+ enum: [system, light, dark]
+ notification_prefs:
+ $ref: '#/components/schemas/NotificationPreferences'
+ NotificationPreferences:
+ type: object
+ required: [desktop, sound]
+ properties:
+ desktop:
+ type: boolean
+ sound:
+ type: boolean
+ ProfileUpdateInput:
+ type: object
+ properties:
+ display_name:
+ type: string
+ maxLength: 100
+ theme:
+ type: string
+ enum: [system, light, dark]
+ presence:
+ type: string
+ enum: [online, away, busy]
+ notification_prefs:
+ $ref: '#/components/schemas/NotificationPreferences'
+ ErrorEnvelope:
+ type: object
+ required: [error]
+ properties:
+ error:
+ type: object
+ required: [type, message]
+ properties:
+ type:
+ type: string
+ enum: [validation, database, storage, export, conflict, authentication, authorization, not_found, rate_limit, server]
+ message:
+ type: string
+ details:
+ type: object
+ additionalProperties: true
+ correlation_id:
+ type: string
+ description: Present on errors emitted by shared filters and the central error handler.
+ responses:
+ GeneralMessagePage:
+ description: Paginated general-channel messages with legacy status metadata.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GeneralMessagePage'
+ example:
+ messages:
+ - id: 42
+ channel_id: 1
+ user: alice
+ msg: Hello from class
+ time: 1700000000
+ status: 1
+ time: 1700000001
+ pagination:
+ page: 1
+ perPage: 10
+ totalItems: 1
+ totalPages: 1
+ hasNext: false
+ hasPrev: false
+ ChannelMessagePage:
+ description: Live-message page or live-plus-archive cursor history.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ChannelMessagePage'
+ examples:
+ page:
+ summary: Page-based live messages
+ value:
+ messages:
+ - id: 42
+ channel_id: 7
+ user: alice
+ msg: Hello from class
+ time: 1700000000
+ pagination:
+ page: 1
+ perPage: 10
+ totalItems: 1
+ totalPages: 1
+ hasNext: false
+ hasPrev: false
+ cursor:
+ summary: Cursor history including archived messages
+ value:
+ messages:
+ - id: 42
+ channel_id: 7
+ user: alice
+ msg: Hello from class
+ time: 1700000000
+ archived: 0
+ pagination:
+ limit: 25
+ nextBefore: null
+ hasMore: false
+ ChannelResult:
+ description: Channel state.
+ content:
+ application/json:
+ schema:
+ type: object
+ required: [channel]
+ properties:
+ channel:
+ $ref: '#/components/schemas/Channel'
+ example:
+ channel:
+ id: 7
+ name: Project Room
+ slug: project-room
+ channel_type: public
+ topic: Planning the next release
+ created_by: 7
+ archived_at: null
+ created_at: '2026-09-18 10:00:00'
+ updated_at: '2026-09-18 10:00:00'
+ MessageExport:
+ description: Downloaded message history in the selected format.
+ headers:
+ Content-Disposition:
+ schema:
+ type: string
+ description: Attachment filename.
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Message'
+ example:
+ - id: 42
+ channel_id: 7
+ user: alice
+ msg: Exported message
+ time: 1700000000
+ archived: 0
+ text/csv:
+ schema:
+ type: string
+ example: |-
+ id,channel_id,user,msg,time,archived
+ 42,7,alice,"Exported message",1700000000,0
+ BadRequest:
+ description: Invalid query, form, or JSON input.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: validation
+ message: Provide at least one search filter.
+ Unauthorized:
+ description: A valid logged-in session is required.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: authentication
+ message: Authentication required
+ details: {}
+ correlation_id: 8fbc0e2d79d745569abeb2f5335c1712
+ Forbidden:
+ description: The current user cannot perform this action.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: authorization
+ message: You are not a channel member.
+ NotFound:
+ description: The requested resource is missing or inaccessible.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: not_found
+ message: Channel not found.
+ Conflict:
+ description: A unique resource value is already in use.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: conflict
+ message: The channel slug is already in use.
+ UnprocessableEntity:
+ description: The submitted entity has invalid fields.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: validation
+ message: Choose a valid theme.
+ RateLimited:
+ description: The endpoint's rate limit was exceeded.
+ headers:
+ Retry-After:
+ schema:
+ type: integer
+ description: Seconds until another request is allowed.
+ X-Correlation-ID:
+ schema:
+ type: string
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: rate_limit
+ message: Too many requests. Please try again later.
+ details:
+ retry_after: 60
+ correlation_id: 8fbc0e2d79d745569abeb2f5335c1712
+ ServerError:
+ description: Storage or server failure.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorEnvelope'
+ example:
+ error:
+ type: server
+ message: An unexpected error occurred.
diff --git a/docs/public-api.md b/docs/public-api.md
index f631e32..3426865 100644
--- a/docs/public-api.md
+++ b/docs/public-api.md
@@ -1,5 +1,9 @@
# Public API Reference (Backend + WebSocket + Frontend)
+The machine-readable OpenAPI 3.1 contract for every `/api/v1/*` route is in
+[`openapi.yaml`](openapi.yaml) and is rendered as interactive Swagger UI at
+`/api/docs`.
+
This document describes the **public surface area** of this repository:
- **HTTP endpoints** (CodeIgniter routes/controllers)
diff --git a/e2e/api-docs.spec.ts b/e2e/api-docs.spec.ts
new file mode 100644
index 0000000..b206dc7
--- /dev/null
+++ b/e2e/api-docs.spec.ts
@@ -0,0 +1,17 @@
+import { expect, test } from '@playwright/test';
+
+test('renders the embedded OpenAPI contract with Swagger UI', async ({ page }) => {
+ const consoleErrors: string[] = [];
+ page.on('console', (message) => {
+ if (message.type() === 'error') {
+ consoleErrors.push(message.text());
+ }
+ });
+
+ await page.goto('/api/docs');
+
+ await expect(page).toHaveTitle('CodeIgniter Chat API documentation');
+ await expect(page.locator('.swagger-ui .info .title')).toContainText('CodeIgniter Chat API');
+ await expect(page.locator('.swagger-ui .opblock')).toHaveCount(24);
+ expect(consoleErrors).toEqual([]);
+});
diff --git a/package.json b/package.json
index 333b566..931ff3b 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,7 @@
"scripts": {
"dev": "vite",
"build": "vite build",
+ "api:lint": "spectral lint docs/openapi.yaml --fail-severity=warn && node scripts/check-openapi-routes.mjs",
"pwa:assets": "pwa-assets-generator --preset minimal-2023 public/pwa-icon.svg",
"preview": "vite preview",
"bench:post": "k6 run bench/post-messages.js",
@@ -29,12 +30,14 @@
"@axe-core/playwright": "^4.13.0",
"@biomejs/biome": "^2.5.13",
"@playwright/test": "^1.63.0",
+ "@stoplight/spectral-cli": "^6.16.3",
"@sveltejs/vite-plugin-svelte": "^7.3.0",
"@vite-pwa/assets-generator": "^1.0.4",
"@vitejs/plugin-vue": "^6.0.9",
"sass": "^1.104.1",
"svelte": "^5.57.0",
"svelte-check": "^4.7.6",
+ "swagger-ui-dist": "^5.33.0",
"typescript": "^6.0.3",
"vite": "^8.3.0",
"vite-plugin-pwa": "^1.3.0",
@@ -48,6 +51,7 @@
"workbox-precaching": "^7.4.1",
"workbox-routing": "^7.4.1",
"workbox-strategies": "^7.4.1",
- "workbox-window": "^7.4.1"
+ "workbox-window": "^7.4.1",
+ "yaml": "^2.9.1"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0e43513..b6b35da 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -20,15 +20,18 @@ importers:
'@playwright/test':
specifier: ^1.63.0
version: 1.63.0
+ '@stoplight/spectral-cli':
+ specifier: ^6.16.3
+ version: 6.16.3
'@sveltejs/vite-plugin-svelte':
specifier: ^7.3.0
- version: 7.3.0(svelte@5.57.0)(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))
+ version: 7.3.0(svelte@5.57.0)(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))
'@vite-pwa/assets-generator':
specifier: ^1.0.4
- version: 1.0.4
+ version: 1.0.4(@types/node@26.6.1)
'@vitejs/plugin-vue':
specifier: ^6.0.9
- version: 6.0.9(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))(vue@3.5.42(typescript@6.0.3))
+ version: 6.0.9(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))(vue@3.5.42(typescript@6.0.3))
sass:
specifier: ^1.104.1
version: 1.104.1
@@ -38,15 +41,18 @@ importers:
svelte-check:
specifier: ^4.7.6
version: 4.7.6(picomatch@4.0.7)(svelte@5.57.0)(typescript@6.0.3)
+ swagger-ui-dist:
+ specifier: ^5.33.0
+ version: 5.33.0
typescript:
specifier: ^6.0.3
version: 6.0.3
vite:
specifier: ^8.3.0
- version: 8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)
+ version: 8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)
vite-plugin-pwa:
specifier: ^1.3.0
- version: 1.3.0(@vite-pwa/assets-generator@1.0.4)(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))(workbox-build@7.4.1)(workbox-window@7.4.1)
+ version: 1.3.0(@vite-pwa/assets-generator@1.0.4(@types/node@26.6.1))(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))(workbox-build@7.4.1)(workbox-window@7.4.1)
vue:
specifier: ^3.5.42
version: 3.5.42(typescript@6.0.3)
@@ -80,6 +86,9 @@ importers:
workbox-window:
specifier: ^7.4.1
version: 7.4.1
+ yaml:
+ specifier: ^2.9.1
+ version: 2.9.1
packages:
@@ -89,6 +98,9 @@ packages:
peerDependencies:
ajv: '>=8'
+ '@asyncapi/specs@6.11.1':
+ resolution: {integrity: sha512-A3WBLqAKGoJ2+6FWFtpjBlCQ1oFCcs4GxF7zsIGvNqp/klGUHjlA3aAcZ9XMMpLGE8zPeYDz2x9FmO6DSuKraQ==}
+
'@axe-core/playwright@4.13.0':
resolution: {integrity: sha512-6YLx+kxXu5GJceG4ozFg+33a2EMTdjYwWGloJ3sb9Kta5pp+ZNS53uxGVog5JetIY8s++P5UrtX+cri+u0VAVg==}
peerDependencies:
@@ -846,6 +858,24 @@ packages:
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+ '@jsep-plugin/assignment@1.3.0':
+ resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==}
+ engines: {node: '>= 10.16.0'}
+ peerDependencies:
+ jsep: ^0.4.0||^1.0.0
+
+ '@jsep-plugin/regex@1.0.4':
+ resolution: {integrity: sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==}
+ engines: {node: '>= 10.16.0'}
+ peerDependencies:
+ jsep: ^0.4.0||^1.0.0
+
+ '@jsep-plugin/ternary@1.1.4':
+ resolution: {integrity: sha512-ck5wiqIbqdMX6WRQztBL7ASDty9YLgJ3sSAK5ZpBzXeySvFGCzIvM6UiAI4hTZ22fEcYQVV/zhUbNscggW+Ukg==}
+ engines: {node: '>= 10.16.0'}
+ peerDependencies:
+ jsep: ^0.4.0||^1.0.0
+
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==}
engines: {node: ^22.20 || ^24.12 || >=25}
@@ -853,6 +883,18 @@ packages:
os: [linux]
libc: [glibc]
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
'@oxc-project/types@0.149.0':
resolution: {integrity: sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==}
@@ -1058,6 +1100,12 @@ packages:
rollup:
optional: true
+ '@rollup/plugin-commonjs@22.0.2':
+ resolution: {integrity: sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==}
+ engines: {node: '>= 12.0.0'}
+ peerDependencies:
+ rollup: ^2.68.0
+
'@rollup/plugin-node-resolve@16.0.3':
resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==}
engines: {node: '>=14.0.0'}
@@ -1085,6 +1133,12 @@ packages:
rollup:
optional: true
+ '@rollup/pluginutils@3.1.0':
+ resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
+ engines: {node: '>= 8.0.0'}
+ peerDependencies:
+ rollup: ^1.20.0||^2.0.0
+
'@rollup/pluginutils@5.4.0':
resolution: {integrity: sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==}
engines: {node: '>=14.0.0'}
@@ -1232,6 +1286,106 @@ packages:
cpu: [x64]
os: [win32]
+ '@scarf/scarf@1.4.0':
+ resolution: {integrity: sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==}
+
+ '@stoplight/better-ajv-errors@1.0.3':
+ resolution: {integrity: sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA==}
+ engines: {node: ^12.20 || >= 14.13}
+ peerDependencies:
+ ajv: '>=8'
+
+ '@stoplight/json-ref-readers@1.2.2':
+ resolution: {integrity: sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ==}
+ engines: {node: '>=8.3.0'}
+
+ '@stoplight/json-ref-resolver@3.1.6':
+ resolution: {integrity: sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A==}
+ engines: {node: '>=8.3.0'}
+
+ '@stoplight/json@3.21.7':
+ resolution: {integrity: sha512-xcJXgKFqv/uCEgtGlPxy3tPA+4I+ZI4vAuMJ885+ThkTHFVkC+0Fm58lA9NlsyjnkpxFh4YiQWpH+KefHdbA0A==}
+ engines: {node: '>=8.3.0'}
+
+ '@stoplight/ordered-object-literal@1.0.5':
+ resolution: {integrity: sha512-COTiuCU5bgMUtbIFBuyyh2/yVVzlr5Om0v5utQDgBCuQUOPgU1DwoffkTfg4UBQOvByi5foF4w4T+H9CoRe5wg==}
+ engines: {node: '>=8'}
+
+ '@stoplight/path@1.3.2':
+ resolution: {integrity: sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ==}
+ engines: {node: '>=8'}
+
+ '@stoplight/spectral-cli@6.16.3':
+ resolution: {integrity: sha512-corAOQ/WhGoPJOQ3Tcipyn64TgKYDkEhsDplS6vNSGys3kzi9+zzxiVOlbzk9mWuafovzoW+TpGCoNwIZvFf5w==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+ hasBin: true
+
+ '@stoplight/spectral-core@1.23.1':
+ resolution: {integrity: sha512-VLC8OhpO/pMJKb6IHhurxJjXO1qB56Ng1unIb8b+hNxdw0+SEcASvmR+RpjfHYX/jv/DfSaA1x8QhFBJBmqBOQ==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-formats@1.8.5':
+ resolution: {integrity: sha512-xaC0rCH0p7/bzNJsz+JgLSj+Cp6uwYGWpePQxdLkF2G6a8Zyp3OyS7umkGYNiimEwKrOjvCNNTFJpeuiENZSBA==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-formatters@1.5.1':
+ resolution: {integrity: sha512-mGXaiIrPglPokSnbFqbkWN3DoozIbwrZAA6OgqSIl+djeD5+e6PMELg0g6r3ot3ZzntO+6/GXaDnxEQ/p9M/EQ==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-functions@1.10.5':
+ resolution: {integrity: sha512-vDCd0NJ93715bcUpZZ5vNHiyxd4cgHF6tuXsDiXOXKAByg+I1fR5/dMijEo6Ce1Lz95a+RZ22JKYhF1YuzVvuA==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-parsers@1.0.5':
+ resolution: {integrity: sha512-ANDTp2IHWGvsQDAY85/jQi9ZrF4mRrA5bciNHX+PUxPr4DwS6iv4h+FVWJMVwcEYdpyoIdyL+SRmHdJfQEPmwQ==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-ref-resolver@1.0.5':
+ resolution: {integrity: sha512-gj3TieX5a9zMW29z3mBlAtDOCgN3GEc1VgZnCVlr5irmR4Qi5LuECuFItAq4pTn5Zu+sW5bqutsCH7D4PkpyAA==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-ruleset-bundler@1.7.0':
+ resolution: {integrity: sha512-PpIdj5Wje0T7ktxY8EUzBWLU0+mGGQHznT8nlQxTMnRhWLNYsm6HvSZDXLtMi+86yqvTuf7loJy6JvLBDzHGAA==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-ruleset-migrator@1.12.2':
+ resolution: {integrity: sha512-9hTcyXnBGppM1kMA8vVvY6aWzF3vXbU7+mZvvd9wdPE8QdHj9NO//1s+A/TfiWOKdH9GOERC5NITCnVvbEYEWg==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-rulesets@1.22.7':
+ resolution: {integrity: sha512-cT1B6Ly21923lvr235lu7iIgmcnoCTJaN3ANOyTqr4D5GA/4p2k0+yhjhdfj/1ks/Os3kUzSFnFkzpWH7WszFA==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/spectral-runtime@1.1.6':
+ resolution: {integrity: sha512-Y8rEDyMN4bSMJCrDs2shdcVHYyCnH3FvXRP4dBhha4Z8iJv+JPp7KqOV/hwVB/hWFC209upiwj2oDmLfR0qCDg==}
+ engines: {node: ^16.20 || ^18.18 || >= 20.17}
+
+ '@stoplight/types@13.20.0':
+ resolution: {integrity: sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA==}
+ engines: {node: ^12.20 || >=14.13}
+
+ '@stoplight/types@13.6.0':
+ resolution: {integrity: sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ==}
+ engines: {node: ^12.20 || >=14.13}
+
+ '@stoplight/types@14.1.1':
+ resolution: {integrity: sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g==}
+ engines: {node: ^12.20 || >=14.13}
+
+ '@stoplight/yaml-ast-parser@0.0.48':
+ resolution: {integrity: sha512-sV+51I7WYnLJnKPn2EMWgS4EUfoP4iWEbrWwbXsj0MZCB/xOK8j6+C9fntIdOM50kpx45ZLC3s6kwKivWuqvyg==}
+
+ '@stoplight/yaml-ast-parser@0.0.50':
+ resolution: {integrity: sha512-Pb6M8TDO9DtSVla9yXSTAxmo9GVEouq5P40DWXdOie69bXogZTkgvopCq+yEvTMA0F6PEvdJmbtTV3ccIp11VQ==}
+
+ '@stoplight/yaml@4.2.3':
+ resolution: {integrity: sha512-Mx01wjRAR9C7yLMUyYFTfbUf5DimEpHMkRDQ1PKLe9dfNILbgdxyrncsOXM3vCpsQ1Hfj4bPiGl+u4u6e9Akqw==}
+ engines: {node: '>=10.8'}
+
+ '@stoplight/yaml@4.3.0':
+ resolution: {integrity: sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w==}
+ engines: {node: '>=10.8'}
+
'@sveltejs/acorn-typescript@1.0.13':
resolution: {integrity: sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ==}
peerDependencies:
@@ -1252,15 +1406,36 @@ packages:
resolution: {integrity: sha512-/67zpWDBLV+oYAEL682s1ktXL0HgqX76f6gaVGkGnVZlBbm1zd0v4Bz8MFF2GGhoX9rvfq3KSQHubFHwa6w6/Q==}
engines: {node: '>=12'}
+ '@types/es-aggregate-error@1.0.6':
+ resolution: {integrity: sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg==}
+
+ '@types/estree@0.0.39':
+ resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
+
'@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/markdown-escape@1.1.3':
+ resolution: {integrity: sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw==}
+
+ '@types/node@26.6.1':
+ resolution: {integrity: sha512-VqGJBMCtdhqkBUCcBLvywI0NJ+KLuVzgNnlBUNFOQjqVxzo2lxLUNg1DSey8+u2u6ktswSAxg+s68QLzWHNOuA==}
+
'@types/resolve@1.20.2':
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
+ '@types/sarif@2.1.7':
+ resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==}
+
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
+ '@types/urijs@1.19.26':
+ resolution: {integrity: sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg==}
+
'@vite-pwa/assets-generator@1.0.4':
resolution: {integrity: sha512-LlYM5CEmFmdl7le4B0Pr9+NPipQgStFOslvfxEQ/1LW3wUquZ3s3ec2z132lzfVEYAiJAmfFhQ0EVs6ntO7RKw==}
engines: {node: '>=16.14.0'}
@@ -1317,12 +1492,41 @@ 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-errors@3.0.0:
+ resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==}
+ peerDependencies:
+ ajv: ^8.0.1
+
+ ajv-formats@2.1.1:
+ resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
+ peerDependencies:
+ ajv: ^8.0.0
+ peerDependenciesMeta:
+ ajv:
+ optional: true
+
ajv@8.20.0:
resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==}
alien-signals@3.2.1:
resolution: {integrity: sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==}
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
aria-query@5.3.1:
resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==}
engines: {node: '>= 0.4'}
@@ -1335,6 +1539,17 @@ packages:
resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
engines: {node: '>= 0.4'}
+ as-table@1.0.55:
+ resolution: {integrity: sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ==}
+
+ ast-types@0.14.2:
+ resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==}
+ engines: {node: '>=4'}
+
+ astring@1.9.0:
+ resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
+ hasBin: true
+
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
@@ -1385,6 +1600,9 @@ packages:
engines: {node: '>=6.0.0'}
hasBin: true
+ brace-expansion@1.1.21:
+ resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==}
+
brace-expansion@2.1.4:
resolution: {integrity: sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==}
@@ -1392,6 +1610,10 @@ packages:
resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==}
engines: {node: 20 || >=22}
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
browserslist@4.28.9:
resolution: {integrity: sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg==}
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
@@ -1400,6 +1622,9 @@ packages:
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ builtins@1.0.3:
+ resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==}
+
cac@6.7.14:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
@@ -1419,6 +1644,10 @@ packages:
caniuse-lite@1.0.30001810:
resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==}
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
@@ -1427,10 +1656,24 @@ packages:
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
engines: {node: '>= 20.19.0'}
+ cliui@7.0.4:
+ resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+
+ cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+
clsx@2.1.1:
resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
engines: {node: '>=6'}
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
colorette@2.0.20:
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
@@ -1441,6 +1684,12 @@ packages:
resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==}
engines: {node: '>=4.0.0'}
+ commondir@1.0.1:
+ resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
consola@3.4.2:
resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==}
engines: {node: ^14.18.0 || >=16.10.0}
@@ -1463,6 +1712,9 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ data-uri-to-buffer@2.0.2:
+ resolution: {integrity: sha512-ND9qDTLc6diwj+Xe5cdAgVTbLVdXbtxTJRXRhli8Mowuaan+0EJOtdqJ0QCHNSSPyoXGx9HX2/VMnKeC34AChA==}
+
data-view-buffer@1.0.2:
resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
engines: {node: '>= 0.4'}
@@ -1507,6 +1759,10 @@ packages:
defu@6.1.7:
resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
+ dependency-graph@0.11.0:
+ resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==}
+ engines: {node: '>= 0.6.0'}
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
@@ -1526,6 +1782,9 @@ packages:
electron-to-chromium@1.5.427:
resolution: {integrity: sha512-n14zb3FdsChZ2BNobqNHAJMcP3ifFv4paox2LvCrfVAQcqGiSURgbJl+PfMpHVCNFkStnNc+RRVtPBTVW5PDgw==}
+ emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+
entities@7.0.1:
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
engines: {node: '>=0.12'}
@@ -1538,6 +1797,10 @@ packages:
resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==}
engines: {node: '>= 0.4'}
+ es-aggregate-error@1.0.14:
+ resolution: {integrity: sha512-3YxX6rVb07B5TV11AV5wsL7nQCHXNwoHPsQC8S4AmBiqYhyNCJ5BRKXkXyDJvs8QzXN20NgRtxe3dEEQD9NLHA==}
+ engines: {node: '>= 0.4'}
+
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
@@ -1573,6 +1836,9 @@ packages:
'@typescript-eslint/types':
optional: true
+ estree-walker@1.0.1:
+ resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==}
+
estree-walker@2.0.2:
resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
@@ -1584,15 +1850,29 @@ packages:
resolution: {integrity: sha512-lW6is4T1NFOYnmqGZIfvixqj7A7sSvScF+DN8EK6K58xI5MZ5UvYe0GjopxOXQtZvUn4eDdVuZ8XSoYWTMEKwA==}
engines: {node: '>=20'}
+ expr-eval-fork@3.0.3:
+ resolution: {integrity: sha512-BhC+hbc5lIVjygr840n5DEkW3MQq7H9o+mc1/N7Z5uIiCFVyESLL5DIE7LNq4CYUNxy+XjA+3jRrL/h0Kt2xcg==}
+ engines: {node: '>=16.9.0'}
+
fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ fast-glob@3.2.12:
+ resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
+ engines: {node: '>=8.6.0'}
+
fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ fast-memoize@2.5.2:
+ resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==}
+
fast-uri@3.1.7:
resolution: {integrity: sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==}
+ fastq@1.20.3:
+ resolution: {integrity: sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -1605,6 +1885,10 @@ packages:
filelist@1.0.6:
resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==}
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
for-each@0.3.5:
resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
engines: {node: '>= 0.4'}
@@ -1613,10 +1897,17 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
+ fs-extra@10.1.0:
+ resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+ engines: {node: '>=12'}
+
fs-extra@9.1.0:
resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
engines: {node: '>=10'}
+ fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1640,6 +1931,10 @@ packages:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
get-intrinsic@1.3.0:
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
engines: {node: '>= 0.4'}
@@ -1651,16 +1946,27 @@ packages:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
+ get-source@2.0.12:
+ resolution: {integrity: sha512-X5+4+iD+HoSeEED+uwrQ07BOQr0kEDFMVqqpBuI+RaZBpBpHCuXxo70bjar6f0b0u/DQJsJ7ssurpP0V60Az+w==}
+
get-symbol-description@1.1.0:
resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
engines: {node: '>= 0.4'}
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
glob@11.1.0:
resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==}
engines: {node: 20 || >=22}
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
+ glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ 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
+
globalthis@1.0.4:
resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
engines: {node: '>= 0.4'}
@@ -1676,6 +1982,10 @@ packages:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
@@ -1695,15 +2005,29 @@ packages:
resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==}
engines: {node: '>= 0.4'}
+ hpagent@1.2.0:
+ resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==}
+ engines: {node: '>=14'}
+
ico-endec@0.1.6:
resolution: {integrity: sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==}
idb@7.1.1:
resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==}
+ immer@9.0.21:
+ resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==}
+
immutable@5.1.9:
resolution: {integrity: sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==}
+ inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.
+
+ inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+
internal-slot@1.1.0:
resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
engines: {node: '>= 0.4'}
@@ -1752,6 +2076,10 @@ packages:
resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
engines: {node: '>= 0.4'}
+ is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+
is-generator-function@1.1.2:
resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
engines: {node: '>= 0.4'}
@@ -1775,10 +2103,17 @@ packages:
resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
engines: {node: '>= 0.4'}
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
is-obj@1.0.1:
resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==}
engines: {node: '>=0.10.0'}
+ is-reference@1.2.1:
+ resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
+
is-reference@3.0.3:
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
@@ -1848,6 +2183,10 @@ packages:
js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ jsep@1.4.0:
+ resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==}
+ engines: {node: '>= 10.16.0'}
+
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
engines: {node: '>=6'}
@@ -1861,9 +2200,17 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jsonc-parser@2.2.1:
+ resolution: {integrity: sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==}
+
jsonfile@6.2.1:
resolution: {integrity: sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==}
+ jsonpath-plus@10.4.0:
+ resolution: {integrity: sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==}
+ engines: {node: '>=18.0.0'}
+ hasBin: true
+
jsonpointer@5.0.1:
resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
engines: {node: '>=0.10.0'}
@@ -1952,6 +2299,12 @@ packages:
lodash.debounce@4.0.8:
resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
+ lodash.topath@4.5.2:
+ resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==}
+
+ lodash@4.18.1:
+ resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==}
+
lru-cache@11.5.2:
resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==}
engines: {node: 20 || >=22}
@@ -1959,20 +2312,37 @@ packages:
lru-cache@5.1.1:
resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ magic-string@0.25.9:
+ resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
+
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
magic-string@1.2.0:
resolution: {integrity: sha512-ptco+HFxTLgjafSLim2LojBSwfg5feBjd+SqyiwdGkzC38UPdZy3zgrHMI2CoTf5fJL38tbHMYWVzIH8BxGqJw==}
+ markdown-escape@2.0.0:
+ resolution: {integrity: sha512-Trz4v0+XWlwy68LJIyw3bLbsJiC8XAbRCKF9DbEtZjyndKOGVx6n+wNB0VfoRmY2LKboQLeniap3xrb6LGSJ8A==}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
minimatch@10.2.6:
resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==}
engines: {node: 18 || 20 || >=22}
+ minimatch@3.1.5:
+ resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==}
+
minimatch@5.1.9:
resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==}
engines: {node: '>=10'}
@@ -1996,13 +2366,30 @@ packages:
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ nimma@0.2.3:
+ resolution: {integrity: sha512-1ZOI8J+1PKKGceo/5CT5GfQOG6H8I2BencSK06YarZ2wXwH37BSSUWldqJmMJYA5JfqDqffxDXynt6f11AyKcA==}
+ engines: {node: ^12.20 || >=14.13}
+
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
+ node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+
node-releases@2.0.55:
resolution: {integrity: sha512-mIrE/Cw9y+9Au6dS5vDKDhQza9YvG6w+ZrS6X+ZzA7yFW/soAeaups4Qzn1bL6g5FVy8WtP79+0j82oPIbqRjQ==}
engines: {node: '>=18'}
+ node-sarif-builder@2.0.3:
+ resolution: {integrity: sha512-Pzr3rol8fvhG/oJjIq2NTVB0vmdNNlz22FENhhPojYRZ4/ee08CfK4YuKmuL54V9MLhI1kpzxfOJ/63LzmZzDg==}
+ engines: {node: '>=14'}
+
object-inspect@1.13.4:
resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
engines: {node: '>= 0.4'}
@@ -2019,6 +2406,9 @@ packages:
resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==}
engines: {node: '>=12.20.0'}
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
own-keys@1.0.2:
resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==}
engines: {node: '>= 0.4'}
@@ -2029,6 +2419,10 @@ packages:
path-browserify@1.0.1:
resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+ path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+
path-key@3.1.1:
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
engines: {node: '>=8'}
@@ -2057,6 +2451,10 @@ packages:
engines: {node: '>=20'}
hasBin: true
+ pony-cause@1.1.1:
+ resolution: {integrity: sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g==}
+ engines: {node: '>=12.0.0'}
+
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -2073,9 +2471,15 @@ packages:
resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==}
engines: {node: ^14.13.1 || >=16.0.0}
+ printable-characters@1.0.42:
+ resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==}
+
quansync@1.0.0:
resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==}
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
@@ -2110,25 +2514,45 @@ packages:
resolution: {integrity: sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==}
hasBin: true
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
+ reserved@0.1.2:
+ resolution: {integrity: sha512-/qO54MWj5L8WCBP9/UNe2iefJc+L9yETbH32xO/ft/EYPOTCR5k+azvDUgdCOKwZH8hXwPd0b8XBL78Nn2U69g==}
+ engines: {node: '>=0.8'}
+
resolve@1.22.12:
resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
engines: {node: '>= 0.4'}
hasBin: true
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
rolldown@1.2.8:
resolution: {integrity: sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==}
engines: {node: ^20.19.0 || >=22.12.0}
hasBin: true
+ rollup@2.80.0:
+ resolution: {integrity: sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==}
+ engines: {node: '>=10.0.0'}
+ hasBin: true
+
rollup@4.63.2:
resolution: {integrity: sha512-l5eyksV4tPBj6lJyEa37YzIOCSOV7lkZzEHUdpjWZbtD7wTcFYmEYXSgm5bT4vV+dZLb9rBG1W9GROOG4NS4Ew==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
sade@1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
@@ -2145,6 +2569,9 @@ packages:
resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
engines: {node: '>= 0.4'}
+ safe-stable-stringify@1.1.1:
+ resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==}
+
sass@1.104.1:
resolution: {integrity: sha512-yDA+1aIG3EHgN4V/BvuhCvu61FF6hEd4e+9DxikUm9U0CAGuvdIZ/UYy7qbOxjhbbWQraoyLlMuzdRGOSV5Bmw==}
engines: {node: '>=20.19.0'}
@@ -2234,10 +2661,21 @@ packages:
resolution: {integrity: sha512-d8EqvL+k/SOXCreS/SUzg2ciyHqBBLcN/yuRjFsbvVhHTE2pgei7oAhmPM7kWFbkX6OSMQfUq4KbkF3au9lhYQ==}
engines: {node: '>= 12'}
+ sourcemap-codec@1.4.8:
+ resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
+ deprecated: Please use @jridgewell/sourcemap-codec instead
+
+ stacktracey@2.2.0:
+ resolution: {integrity: sha512-ETyQEz+CzXiLjEbyJqpbp+/T79RQD/6wqFucRBIlVNZfYq2Ay7wbretD4cxpbymZlaPWx58aIhPEY1Cr8DlVvg==}
+
stop-iteration-iterator@1.1.0:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
+ string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+
string.prototype.matchall@4.1.0:
resolution: {integrity: sha512-tHNHTxInrYLCga9O9YGxWA3G9/nnzQw8UGAyqGx3Ar1pSTTzIuM4woFSq4SowkXCjJIwq5sIiQvEfRI9tCH1qQ==}
engines: {node: '>= 0.4'}
@@ -2258,10 +2696,18 @@ packages:
resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==}
engines: {node: '>=4'}
+ strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+
strip-comments@2.0.1:
resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==}
engines: {node: '>=10'}
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -2278,6 +2724,9 @@ packages:
resolution: {integrity: sha512-NdbDn7fl4be1ViUG0oq/lvG6OZy3oENolV2ONjiqqsfVoeAfzaQAKUcEX3MrQod/Bebv1PgwET9rfXhgn9s4Kg==}
engines: {node: '>=18'}
+ swagger-ui-dist@5.33.0:
+ resolution: {integrity: sha512-wpdK+m6BU5yj6pmUdMskZVTSWYG4DLglAx3sIhylloY37i8O37IrH+YEpqdXNfpaTGxILRBFzUqLF2jKqbfI7A==}
+
temp-dir@2.0.0:
resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
engines: {node: '>=8'}
@@ -2291,6 +2740,9 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ text-table@0.2.0:
+ resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+
tinyglobby@0.2.17:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
@@ -2298,6 +2750,16 @@ packages:
to-data-view@1.1.0:
resolution: {integrity: sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==}
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+
+ tslib@1.14.1:
+ resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
+
tslib@2.8.1:
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
@@ -2336,6 +2798,9 @@ packages:
unconfig@7.5.0:
resolution: {integrity: sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==}
+ undici-types@8.9.0:
+ resolution: {integrity: sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==}
+
unicode-canonical-property-names-ecmascript@2.0.1:
resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
engines: {node: '>=4'}
@@ -2370,6 +2835,16 @@ packages:
peerDependencies:
browserslist: '>= 4.21.0'
+ urijs@1.19.11:
+ resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==}
+
+ utility-types@3.11.0:
+ resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==}
+ engines: {node: '>= 4'}
+
+ validate-npm-package-name@3.0.0:
+ resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==}
+
vite-plugin-pwa@1.3.0:
resolution: {integrity: sha512-c5kMgN+ITrOtHXp8PAtk2uOIEea6XjP/unCGxOWWBzQ6qa65qj/awHg0wf+QF9E/2u9vh86LqxPwzEPNbM2r5A==}
engines: {node: '>=16.0.0'}
@@ -2450,6 +2925,12 @@ packages:
typescript:
optional: true
+ webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+
+ whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+
which-boxed-primitive@1.1.1:
resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
engines: {node: '>= 0.4'}
@@ -2520,9 +3001,33 @@ packages:
workbox-window@7.4.1:
resolution: {integrity: sha512-notZDH2u8VXaqyuD7xaqIfEFi6SRM4SUSd7ewe9PDsVqADuepxX2ZMY3uvuZGxzY5ZOsGC/vD3A/3smFtJt4/A==}
+ wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
+ y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+
yallist@3.1.1:
resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ yaml@2.9.1:
+ resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==}
+ engines: {node: '>= 14.6'}
+ hasBin: true
+
+ yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+
+ yargs@17.7.3:
+ resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==}
+ engines: {node: '>=12'}
+
zimmerframe@1.1.4:
resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==}
@@ -2534,6 +3039,10 @@ snapshots:
jsonpointer: 5.0.1
leven: 3.1.0
+ '@asyncapi/specs@6.11.1':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
'@axe-core/playwright@4.13.0(playwright-core@1.63.0)':
dependencies:
axe-core: 4.13.0
@@ -3378,9 +3887,33 @@ snapshots:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.6.0
+ '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)':
+ dependencies:
+ jsep: 1.4.0
+
+ '@jsep-plugin/regex@1.0.4(jsep@1.4.0)':
+ dependencies:
+ jsep: 1.4.0
+
+ '@jsep-plugin/ternary@1.1.4(jsep@1.4.0)':
+ dependencies:
+ jsep: 1.4.0
+
'@napi-rs/lzma-linux-x64-gnu@1.5.1':
optional: true
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.3
+
'@oxc-project/types@0.149.0': {}
'@parcel/watcher-android-arm64@2.6.0':
@@ -3505,6 +4038,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@rollup/plugin-commonjs@22.0.2(rollup@2.80.0)':
+ dependencies:
+ '@rollup/pluginutils': 3.1.0(rollup@2.80.0)
+ commondir: 1.0.1
+ estree-walker: 2.0.2
+ glob: 7.2.3
+ is-reference: 1.2.1
+ magic-string: 0.25.9
+ resolve: 1.22.12
+ rollup: 2.80.0
+
'@rollup/plugin-node-resolve@16.0.3(rollup@4.63.2)':
dependencies:
'@rollup/pluginutils': 5.4.0(rollup@4.63.2)
@@ -3530,6 +4074,13 @@ snapshots:
optionalDependencies:
rollup: 4.63.2
+ '@rollup/pluginutils@3.1.0(rollup@2.80.0)':
+ dependencies:
+ '@types/estree': 0.0.39
+ estree-walker: 1.0.1
+ picomatch: 4.0.7
+ rollup: 2.80.0
+
'@rollup/pluginutils@5.4.0(rollup@4.63.2)':
dependencies:
'@types/estree': 1.0.9
@@ -3613,20 +4164,280 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.63.2':
optional: true
+ '@scarf/scarf@1.4.0': {}
+
+ '@stoplight/better-ajv-errors@1.0.3(ajv@8.20.0)':
+ dependencies:
+ ajv: 8.20.0
+ jsonpointer: 5.0.1
+ leven: 3.1.0
+
+ '@stoplight/json-ref-readers@1.2.2':
+ dependencies:
+ node-fetch: 2.7.0
+ tslib: 1.14.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/json-ref-resolver@3.1.6':
+ dependencies:
+ '@stoplight/json': 3.21.7
+ '@stoplight/path': 1.3.2
+ '@stoplight/types': 13.20.0
+ '@types/urijs': 1.19.26
+ dependency-graph: 0.11.0
+ fast-memoize: 2.5.2
+ immer: 9.0.21
+ lodash: 4.18.1
+ tslib: 2.8.1
+ urijs: 1.19.11
+
+ '@stoplight/json@3.21.7':
+ dependencies:
+ '@stoplight/ordered-object-literal': 1.0.5
+ '@stoplight/path': 1.3.2
+ '@stoplight/types': 13.20.0
+ jsonc-parser: 2.2.1
+ lodash: 4.18.1
+ safe-stable-stringify: 1.1.1
+
+ '@stoplight/ordered-object-literal@1.0.5': {}
+
+ '@stoplight/path@1.3.2': {}
+
+ '@stoplight/spectral-cli@6.16.3':
+ dependencies:
+ '@scarf/scarf': 1.4.0
+ '@stoplight/json': 3.21.7
+ '@stoplight/path': 1.3.2
+ '@stoplight/spectral-core': 1.23.1
+ '@stoplight/spectral-formatters': 1.5.1
+ '@stoplight/spectral-parsers': 1.0.5
+ '@stoplight/spectral-ref-resolver': 1.0.5
+ '@stoplight/spectral-ruleset-bundler': 1.7.0
+ '@stoplight/spectral-ruleset-migrator': 1.12.2
+ '@stoplight/spectral-rulesets': 1.22.7
+ '@stoplight/spectral-runtime': 1.1.6
+ '@stoplight/types': 13.20.0
+ chalk: 4.1.2
+ fast-glob: 3.2.12
+ hpagent: 1.2.0
+ lodash: 4.18.1
+ pony-cause: 1.1.1
+ stacktracey: 2.2.0
+ tslib: 2.8.1
+ yargs: 17.7.3
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-core@1.23.1':
+ dependencies:
+ '@scarf/scarf': 1.4.0
+ '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0)
+ '@stoplight/json': 3.21.7
+ '@stoplight/path': 1.3.2
+ '@stoplight/spectral-parsers': 1.0.5
+ '@stoplight/spectral-ref-resolver': 1.0.5
+ '@stoplight/spectral-runtime': 1.1.6
+ '@stoplight/types': 13.6.0
+ '@types/es-aggregate-error': 1.0.6
+ '@types/json-schema': 7.0.15
+ ajv: 8.20.0
+ ajv-errors: 3.0.0(ajv@8.20.0)
+ ajv-formats: 2.1.1(ajv@8.20.0)
+ es-aggregate-error: 1.0.14
+ expr-eval-fork: 3.0.3
+ jsonpath-plus: 10.4.0
+ lodash: 4.18.1
+ lodash.topath: 4.5.2
+ minimatch: 3.1.5
+ nimma: 0.2.3
+ pony-cause: 1.1.1
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-formats@1.8.5':
+ dependencies:
+ '@scarf/scarf': 1.4.0
+ '@stoplight/json': 3.21.7
+ '@stoplight/spectral-core': 1.23.1
+ '@types/json-schema': 7.0.15
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-formatters@1.5.1':
+ dependencies:
+ '@stoplight/path': 1.3.2
+ '@stoplight/spectral-core': 1.23.1
+ '@stoplight/spectral-runtime': 1.1.6
+ '@stoplight/types': 13.20.0
+ '@types/markdown-escape': 1.1.3
+ chalk: 4.1.2
+ cliui: 7.0.4
+ lodash: 4.18.1
+ markdown-escape: 2.0.0
+ node-sarif-builder: 2.0.3
+ strip-ansi: 6.0.1
+ text-table: 0.2.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-functions@1.10.5':
+ dependencies:
+ '@scarf/scarf': 1.4.0
+ '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0)
+ '@stoplight/json': 3.21.7
+ '@stoplight/spectral-core': 1.23.1
+ '@stoplight/spectral-formats': 1.8.5
+ '@stoplight/spectral-runtime': 1.1.6
+ ajv: 8.20.0
+ ajv-draft-04: 1.0.0(ajv@8.20.0)
+ ajv-errors: 3.0.0(ajv@8.20.0)
+ ajv-formats: 2.1.1(ajv@8.20.0)
+ lodash: 4.18.1
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-parsers@1.0.5':
+ dependencies:
+ '@stoplight/json': 3.21.7
+ '@stoplight/types': 14.1.1
+ '@stoplight/yaml': 4.3.0
+ tslib: 2.8.1
+
+ '@stoplight/spectral-ref-resolver@1.0.5':
+ dependencies:
+ '@stoplight/json-ref-readers': 1.2.2
+ '@stoplight/json-ref-resolver': 3.1.6
+ '@stoplight/spectral-runtime': 1.1.6
+ dependency-graph: 0.11.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-ruleset-bundler@1.7.0':
+ dependencies:
+ '@rollup/plugin-commonjs': 22.0.2(rollup@2.80.0)
+ '@stoplight/path': 1.3.2
+ '@stoplight/spectral-core': 1.23.1
+ '@stoplight/spectral-formats': 1.8.5
+ '@stoplight/spectral-functions': 1.10.5
+ '@stoplight/spectral-parsers': 1.0.5
+ '@stoplight/spectral-ref-resolver': 1.0.5
+ '@stoplight/spectral-ruleset-migrator': 1.12.2
+ '@stoplight/spectral-rulesets': 1.22.7
+ '@stoplight/spectral-runtime': 1.1.6
+ '@stoplight/types': 13.20.0
+ '@types/node': 26.6.1
+ pony-cause: 1.1.1
+ rollup: 2.80.0
+ tslib: 2.8.1
+ validate-npm-package-name: 3.0.0
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-ruleset-migrator@1.12.2':
+ dependencies:
+ '@stoplight/json': 3.21.7
+ '@stoplight/ordered-object-literal': 1.0.5
+ '@stoplight/path': 1.3.2
+ '@stoplight/spectral-functions': 1.10.5
+ '@stoplight/spectral-runtime': 1.1.6
+ '@stoplight/types': 13.20.0
+ '@stoplight/yaml': 4.2.3
+ '@types/node': 26.6.1
+ ajv: 8.20.0
+ ast-types: 0.14.2
+ astring: 1.9.0
+ reserved: 0.1.2
+ tslib: 2.8.1
+ validate-npm-package-name: 3.0.0
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-rulesets@1.22.7':
+ dependencies:
+ '@asyncapi/specs': 6.11.1
+ '@scarf/scarf': 1.4.0
+ '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0)
+ '@stoplight/json': 3.21.7
+ '@stoplight/spectral-core': 1.23.1
+ '@stoplight/spectral-formats': 1.8.5
+ '@stoplight/spectral-functions': 1.10.5
+ '@stoplight/spectral-runtime': 1.1.6
+ '@stoplight/types': 13.20.0
+ '@types/json-schema': 7.0.15
+ ajv: 8.20.0
+ ajv-formats: 2.1.1(ajv@8.20.0)
+ json-schema-traverse: 1.0.0
+ leven: 3.1.0
+ lodash: 4.18.1
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/spectral-runtime@1.1.6':
+ dependencies:
+ '@stoplight/json': 3.21.7
+ '@stoplight/path': 1.3.2
+ '@stoplight/types': 13.20.0
+ lodash: 4.18.1
+ node-fetch: 2.7.0
+ tslib: 2.8.1
+ transitivePeerDependencies:
+ - encoding
+
+ '@stoplight/types@13.20.0':
+ dependencies:
+ '@types/json-schema': 7.0.15
+ utility-types: 3.11.0
+
+ '@stoplight/types@13.6.0':
+ dependencies:
+ '@types/json-schema': 7.0.15
+ utility-types: 3.11.0
+
+ '@stoplight/types@14.1.1':
+ dependencies:
+ '@types/json-schema': 7.0.15
+ utility-types: 3.11.0
+
+ '@stoplight/yaml-ast-parser@0.0.48': {}
+
+ '@stoplight/yaml-ast-parser@0.0.50': {}
+
+ '@stoplight/yaml@4.2.3':
+ dependencies:
+ '@stoplight/ordered-object-literal': 1.0.5
+ '@stoplight/types': 13.20.0
+ '@stoplight/yaml-ast-parser': 0.0.48
+ tslib: 2.8.1
+
+ '@stoplight/yaml@4.3.0':
+ dependencies:
+ '@stoplight/ordered-object-literal': 1.0.5
+ '@stoplight/types': 14.1.1
+ '@stoplight/yaml-ast-parser': 0.0.50
+ tslib: 2.8.1
+
'@sveltejs/acorn-typescript@1.0.13(acorn@8.18.0)':
dependencies:
acorn: 8.18.0
'@sveltejs/load-config@0.2.3': {}
- '@sveltejs/vite-plugin-svelte@7.3.0(svelte@5.57.0)(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))':
+ '@sveltejs/vite-plugin-svelte@7.3.0(svelte@5.57.0)(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))':
dependencies:
deepmerge: 4.3.1
magic-string: 1.2.0
obug: 2.1.4
svelte: 5.57.0
- vite: 8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)
- vitefu: 1.1.3(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))
+ vite: 8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)
+ vitefu: 1.1.3(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))
'@trickfilm400/rollup-plugin-off-main-thread@3.0.0-pre1':
dependencies:
@@ -3635,27 +4446,45 @@ snapshots:
magic-string: 0.30.21
string.prototype.matchall: 4.1.0
+ '@types/es-aggregate-error@1.0.6':
+ dependencies:
+ '@types/node': 26.6.1
+
+ '@types/estree@0.0.39': {}
+
'@types/estree@1.0.9': {}
+ '@types/json-schema@7.0.15': {}
+
+ '@types/markdown-escape@1.1.3': {}
+
+ '@types/node@26.6.1':
+ dependencies:
+ undici-types: 8.9.0
+
'@types/resolve@1.20.2': {}
+ '@types/sarif@2.1.7': {}
+
'@types/trusted-types@2.0.7': {}
- '@vite-pwa/assets-generator@1.0.4':
+ '@types/urijs@1.19.26': {}
+
+ '@vite-pwa/assets-generator@1.0.4(@types/node@26.6.1)':
dependencies:
cac: 6.7.14
colorette: 2.0.20
consola: 3.4.2
- sharp: 0.35.4
- sharp-ico: 0.1.5
+ sharp: 0.35.4(@types/node@26.6.1)
+ sharp-ico: 0.1.5(@types/node@26.6.1)
unconfig: 7.5.0
transitivePeerDependencies:
- '@types/node'
- '@vitejs/plugin-vue@6.0.9(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))(vue@3.5.42(typescript@6.0.3))':
+ '@vitejs/plugin-vue@6.0.9(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))(vue@3.5.42(typescript@6.0.3))':
dependencies:
'@rolldown/pluginutils': 1.0.1
- vite: 8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)
+ vite: 8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)
vue: 3.5.42(typescript@6.0.3)
'@volar/language-core@2.4.28':
@@ -3736,6 +4565,18 @@ snapshots:
acorn@8.18.0: {}
+ ajv-draft-04@1.0.0(ajv@8.20.0):
+ optionalDependencies:
+ ajv: 8.20.0
+
+ ajv-errors@3.0.0(ajv@8.20.0):
+ dependencies:
+ ajv: 8.20.0
+
+ ajv-formats@2.1.1(ajv@8.20.0):
+ optionalDependencies:
+ ajv: 8.20.0
+
ajv@8.20.0:
dependencies:
fast-deep-equal: 3.1.3
@@ -3745,6 +4586,12 @@ snapshots:
alien-signals@3.2.1: {}
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
aria-query@5.3.1: {}
array-buffer-byte-length@1.0.2:
@@ -3762,6 +4609,16 @@ snapshots:
get-intrinsic: 1.3.0
is-array-buffer: 3.0.5
+ as-table@1.0.55:
+ dependencies:
+ printable-characters: 1.0.42
+
+ ast-types@0.14.2:
+ dependencies:
+ tslib: 2.8.1
+
+ astring@1.9.0: {}
+
async-function@1.0.0: {}
async@3.2.6: {}
@@ -3806,6 +4663,11 @@ snapshots:
baseline-browser-mapping@2.11.23: {}
+ brace-expansion@1.1.21:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
brace-expansion@2.1.4:
dependencies:
balanced-match: 1.0.2
@@ -3814,6 +4676,10 @@ snapshots:
dependencies:
balanced-match: 4.0.4
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
browserslist@4.28.9:
dependencies:
baseline-browser-mapping: 2.11.23
@@ -3824,6 +4690,8 @@ snapshots:
buffer-from@1.1.2: {}
+ builtins@1.0.3: {}
+
cac@6.7.14: {}
call-bind-apply-helpers@1.0.2:
@@ -3845,6 +4713,11 @@ snapshots:
caniuse-lite@1.0.30001810: {}
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
@@ -3853,14 +4726,36 @@ snapshots:
dependencies:
readdirp: 5.1.1
+ cliui@7.0.4:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
+ cliui@8.0.1:
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+
clsx@2.1.1: {}
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.4: {}
+
colorette@2.0.20: {}
commander@2.20.3: {}
common-tags@1.8.2: {}
+ commondir@1.0.1: {}
+
+ concat-map@0.0.1: {}
+
consola@3.4.2: {}
convert-source-map@2.0.0: {}
@@ -3879,6 +4774,8 @@ snapshots:
csstype@3.2.3: {}
+ data-uri-to-buffer@2.0.2: {}
+
data-view-buffer@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -3928,6 +4825,8 @@ snapshots:
defu@6.1.7: {}
+ dependency-graph@0.11.0: {}
+
detect-libc@2.1.2: {}
devalue@5.9.2: {}
@@ -3944,6 +4843,8 @@ snapshots:
electron-to-chromium@1.5.427: {}
+ emoji-regex@8.0.0: {}
+
entities@7.0.1: {}
es-abstract-get@1.0.0:
@@ -4010,6 +4911,17 @@ snapshots:
unbox-primitive: 1.1.0
which-typed-array: 1.1.22
+ es-aggregate-error@1.0.14:
+ dependencies:
+ define-data-property: 1.1.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.2
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ globalthis: 1.0.4
+ has-property-descriptors: 1.0.2
+ set-function-name: 2.0.2
+
es-define-property@1.0.1: {}
es-errors@1.3.0: {}
@@ -4042,18 +4954,36 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.6.0
+ estree-walker@1.0.1: {}
+
estree-walker@2.0.2: {}
esutils@2.0.3: {}
eta@4.6.0: {}
+ expr-eval-fork@3.0.3: {}
+
fast-deep-equal@3.1.3: {}
+ fast-glob@3.2.12:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
fast-json-stable-stringify@2.1.0: {}
+ fast-memoize@2.5.2: {}
+
fast-uri@3.1.7: {}
+ fastq@1.20.3:
+ dependencies:
+ reusify: 1.1.0
+
fdir@6.5.0(picomatch@4.0.7):
optionalDependencies:
picomatch: 4.0.7
@@ -4062,6 +4992,10 @@ snapshots:
dependencies:
minimatch: 5.1.9
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
for-each@0.3.5:
dependencies:
is-callable: 1.2.7
@@ -4071,6 +5005,12 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
+ fs-extra@10.1.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.2.1
+ universalify: 2.0.1
+
fs-extra@9.1.0:
dependencies:
at-least-node: 1.0.0
@@ -4078,6 +5018,8 @@ snapshots:
jsonfile: 6.2.1
universalify: 2.0.1
+ fs.realpath@1.0.0: {}
+
fsevents@2.3.3:
optional: true
@@ -4101,6 +5043,8 @@ snapshots:
gensync@1.0.0-beta.2: {}
+ get-caller-file@2.0.5: {}
+
get-intrinsic@1.3.0:
dependencies:
call-bind-apply-helpers: 1.0.2
@@ -4121,12 +5065,21 @@ snapshots:
dunder-proto: 1.0.1
es-object-atoms: 1.1.2
+ get-source@2.0.12:
+ dependencies:
+ data-uri-to-buffer: 2.0.2
+ source-map: 0.6.1
+
get-symbol-description@1.1.0:
dependencies:
call-bound: 1.0.4
es-errors: 1.3.0
get-intrinsic: 1.3.0
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
glob@11.1.0:
dependencies:
foreground-child: 3.3.1
@@ -4136,6 +5089,15 @@ snapshots:
package-json-from-dist: 1.0.1
path-scurry: 2.0.2
+ glob@7.2.3:
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.5
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+
globalthis@1.0.4:
dependencies:
define-properties: 1.2.1
@@ -4147,6 +5109,8 @@ snapshots:
has-bigints@1.1.0: {}
+ has-flag@4.0.0: {}
+
has-property-descriptors@1.0.2:
dependencies:
es-define-property: 1.0.1
@@ -4165,12 +5129,23 @@ snapshots:
dependencies:
function-bind: 1.1.2
+ hpagent@1.2.0: {}
+
ico-endec@0.1.6: {}
idb@7.1.1: {}
+ immer@9.0.21: {}
+
immutable@5.1.9: {}
+ inflight@1.0.6:
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+
+ inherits@2.0.4: {}
+
internal-slot@1.1.0:
dependencies:
es-errors: 1.3.0
@@ -4221,13 +5196,14 @@ snapshots:
dependencies:
call-bound: 1.0.4
- is-extglob@2.1.1:
- optional: true
+ is-extglob@2.1.1: {}
is-finalizationregistry@1.1.1:
dependencies:
call-bound: 1.0.4
+ is-fullwidth-code-point@3.0.0: {}
+
is-generator-function@1.1.2:
dependencies:
call-bound: 1.0.4
@@ -4239,7 +5215,6 @@ snapshots:
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
- optional: true
is-map@2.0.3: {}
@@ -4252,8 +5227,14 @@ snapshots:
call-bound: 1.0.4
has-tostringtag: 1.0.2
+ is-number@7.0.0: {}
+
is-obj@1.0.1: {}
+ is-reference@1.2.1:
+ dependencies:
+ '@types/estree': 1.0.9
+
is-reference@3.0.3:
dependencies:
'@types/estree': 1.0.9
@@ -4319,18 +5300,28 @@ snapshots:
js-tokens@4.0.0: {}
+ jsep@1.4.0: {}
+
jsesc@3.1.0: {}
json-schema-traverse@1.0.0: {}
json5@2.2.3: {}
+ jsonc-parser@2.2.1: {}
+
jsonfile@6.2.1:
dependencies:
universalify: 2.0.1
optionalDependencies:
graceful-fs: 4.2.11
+ jsonpath-plus@10.4.0:
+ dependencies:
+ '@jsep-plugin/assignment': 1.3.0(jsep@1.4.0)
+ '@jsep-plugin/regex': 1.0.4(jsep@1.4.0)
+ jsep: 1.4.0
+
jsonpointer@5.0.1: {}
leven@3.1.0: {}
@@ -4388,12 +5379,20 @@ snapshots:
lodash.debounce@4.0.8: {}
+ lodash.topath@4.5.2: {}
+
+ lodash@4.18.1: {}
+
lru-cache@11.5.2: {}
lru-cache@5.1.1:
dependencies:
yallist: 3.1.1
+ magic-string@0.25.9:
+ dependencies:
+ sourcemap-codec: 1.4.8
+
magic-string@0.30.21:
dependencies:
'@jridgewell/sourcemap-codec': 1.6.0
@@ -4402,12 +5401,25 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ markdown-escape@2.0.0: {}
+
math-intrinsics@1.1.0: {}
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 4.0.7
+
minimatch@10.2.6:
dependencies:
brace-expansion: 5.0.9
+ minimatch@3.1.5:
+ dependencies:
+ brace-expansion: 1.1.21
+
minimatch@5.1.9:
dependencies:
brace-expansion: 2.1.4
@@ -4422,11 +5434,30 @@ snapshots:
nanoid@3.3.19: {}
+ nimma@0.2.3:
+ dependencies:
+ '@jsep-plugin/regex': 1.0.4(jsep@1.4.0)
+ '@jsep-plugin/ternary': 1.1.4(jsep@1.4.0)
+ astring: 1.9.0
+ jsep: 1.4.0
+ optionalDependencies:
+ jsonpath-plus: 10.4.0
+ lodash.topath: 4.5.2
+
node-addon-api@7.1.1:
optional: true
+ node-fetch@2.7.0:
+ dependencies:
+ whatwg-url: 5.0.0
+
node-releases@2.0.55: {}
+ node-sarif-builder@2.0.3:
+ dependencies:
+ '@types/sarif': 2.1.7
+ fs-extra: 10.1.0
+
object-inspect@1.13.4: {}
object-keys@1.1.1: {}
@@ -4442,6 +5473,10 @@ snapshots:
obug@2.1.4: {}
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
own-keys@1.0.2:
dependencies:
call-bound: 1.0.4
@@ -4453,6 +5488,8 @@ snapshots:
path-browserify@1.0.1: {}
+ path-is-absolute@1.0.1: {}
+
path-key@3.1.1: {}
path-parse@1.0.7: {}
@@ -4472,6 +5509,8 @@ snapshots:
dependencies:
playwright-core: 1.63.0
+ pony-cause@1.1.1: {}
+
possible-typed-array-names@1.1.0: {}
postcss@8.5.28:
@@ -4484,8 +5523,12 @@ snapshots:
pretty-bytes@6.1.1: {}
+ printable-characters@1.0.42: {}
+
quansync@1.0.0: {}
+ queue-microtask@1.2.3: {}
+
readdirp@4.1.2: {}
readdirp@5.1.1: {}
@@ -4531,8 +5574,12 @@ snapshots:
dependencies:
jsesc: 3.1.0
+ require-directory@2.1.1: {}
+
require-from-string@2.0.2: {}
+ reserved@0.1.2: {}
+
resolve@1.22.12:
dependencies:
es-errors: 1.3.0
@@ -4540,6 +5587,8 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ reusify@1.1.0: {}
+
rolldown@1.2.8:
dependencies:
'@oxc-project/types': 0.149.0
@@ -4561,6 +5610,10 @@ snapshots:
'@rolldown/binding-win32-arm64-msvc': 1.2.8
'@rolldown/binding-win32-x64-msvc': 1.2.8
+ rollup@2.80.0:
+ optionalDependencies:
+ fsevents: 2.3.3
+
rollup@4.63.2:
dependencies:
'@types/estree': 1.0.9
@@ -4593,6 +5646,10 @@ snapshots:
'@rollup/rollup-win32-x64-msvc': 4.63.2
fsevents: 2.3.3
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
sade@1.8.1:
dependencies:
mri: 1.2.0
@@ -4616,6 +5673,8 @@ snapshots:
es-errors: 1.3.0
is-regex: 1.2.1
+ safe-stable-stringify@1.1.1: {}
+
sass@1.104.1:
dependencies:
chokidar: 5.0.0
@@ -4652,15 +5711,15 @@ snapshots:
es-errors: 1.3.0
es-object-atoms: 1.1.2
- sharp-ico@0.1.5:
+ sharp-ico@0.1.5(@types/node@26.6.1):
dependencies:
decode-ico: 0.4.1
ico-endec: 0.1.6
- sharp: 0.35.4
+ sharp: 0.35.4(@types/node@26.6.1)
transitivePeerDependencies:
- '@types/node'
- sharp@0.35.4:
+ sharp@0.35.4(@types/node@26.6.1):
dependencies:
'@img/colour': 1.1.0
detect-libc: 2.1.2
@@ -4691,6 +5750,7 @@ snapshots:
'@img/sharp-win32-arm64': 0.35.4
'@img/sharp-win32-ia32': 0.35.4
'@img/sharp-win32-x64': 0.35.4
+ '@types/node': 26.6.1
shebang-command@2.0.0:
dependencies:
@@ -4741,11 +5801,24 @@ snapshots:
source-map@0.8.0: {}
+ sourcemap-codec@1.4.8: {}
+
+ stacktracey@2.2.0:
+ dependencies:
+ as-table: 1.0.55
+ get-source: 2.0.12
+
stop-iteration-iterator@1.1.0:
dependencies:
es-errors: 1.3.0
internal-slot: 1.1.0
+ string-width@4.2.3:
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+
string.prototype.matchall@4.1.0:
dependencies:
call-bind: 1.0.9
@@ -4792,8 +5865,16 @@ snapshots:
is-obj: 1.0.1
is-regexp: 1.0.0
+ strip-ansi@6.0.1:
+ dependencies:
+ ansi-regex: 5.0.1
+
strip-comments@2.0.1: {}
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
supports-preserve-symlinks-flag@1.0.0: {}
svelte-check@4.7.6(picomatch@4.0.7)(svelte@5.57.0)(typescript@6.0.3):
@@ -4829,6 +5910,10 @@ snapshots:
transitivePeerDependencies:
- '@typescript-eslint/types'
+ swagger-ui-dist@5.33.0:
+ dependencies:
+ '@scarf/scarf': 1.4.0
+
temp-dir@2.0.0: {}
tempy@0.6.0:
@@ -4845,6 +5930,8 @@ snapshots:
commander: 2.20.3
source-map-support: 0.5.21
+ text-table@0.2.0: {}
+
tinyglobby@0.2.17:
dependencies:
fdir: 6.5.0(picomatch@4.0.7)
@@ -4852,8 +5939,15 @@ snapshots:
to-data-view@1.1.0: {}
- tslib@2.8.1:
- optional: true
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ tr46@0.0.3: {}
+
+ tslib@1.14.1: {}
+
+ tslib@2.8.1: {}
type-fest@0.16.0: {}
@@ -4912,6 +6006,8 @@ snapshots:
quansync: 1.0.0
unconfig-core: 7.5.0
+ undici-types@8.9.0: {}
+
unicode-canonical-property-names-ecmascript@2.0.1: {}
unicode-match-property-ecmascript@2.0.0:
@@ -4937,20 +6033,28 @@ snapshots:
escalade: 3.2.0
picocolors: 1.1.1
- vite-plugin-pwa@1.3.0(@vite-pwa/assets-generator@1.0.4)(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2))(workbox-build@7.4.1)(workbox-window@7.4.1):
+ urijs@1.19.11: {}
+
+ utility-types@3.11.0: {}
+
+ validate-npm-package-name@3.0.0:
+ dependencies:
+ builtins: 1.0.3
+
+ vite-plugin-pwa@1.3.0(@vite-pwa/assets-generator@1.0.4(@types/node@26.6.1))(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1))(workbox-build@7.4.1)(workbox-window@7.4.1):
dependencies:
debug: 4.4.3
pretty-bytes: 6.1.1
tinyglobby: 0.2.17
- vite: 8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)
+ vite: 8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)
workbox-build: 7.4.1
workbox-window: 7.4.1
optionalDependencies:
- '@vite-pwa/assets-generator': 1.0.4
+ '@vite-pwa/assets-generator': 1.0.4(@types/node@26.6.1)
transitivePeerDependencies:
- supports-color
- vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2):
+ vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1):
dependencies:
lightningcss: 1.33.0
picomatch: 4.0.7
@@ -4958,14 +6062,16 @@ snapshots:
rolldown: 1.2.8
tinyglobby: 0.2.17
optionalDependencies:
+ '@types/node': 26.6.1
fsevents: 2.3.3
jiti: 2.7.0
sass: 1.104.1
terser: 5.51.2
+ yaml: 2.9.1
- vitefu@1.1.3(vite@8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)):
+ vitefu@1.1.3(vite@8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)):
optionalDependencies:
- vite: 8.3.0(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)
+ vite: 8.3.0(@types/node@26.6.1)(jiti@2.7.0)(sass@1.104.1)(terser@5.51.2)(yaml@2.9.1)
vscode-uri@3.2.0: {}
@@ -4985,6 +6091,13 @@ snapshots:
optionalDependencies:
typescript: 6.0.3
+ webidl-conversions@3.0.1: {}
+
+ whatwg-url@5.0.0:
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+
which-boxed-primitive@1.1.1:
dependencies:
is-bigint: 1.1.0
@@ -5143,6 +6256,30 @@ snapshots:
'@types/trusted-types': 2.0.7
workbox-core: 7.4.1
+ wrap-ansi@7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+
+ wrappy@1.0.2: {}
+
+ y18n@5.0.8: {}
+
yallist@3.1.1: {}
+ yaml@2.9.1: {}
+
+ yargs-parser@21.1.1: {}
+
+ yargs@17.7.3:
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.2.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+
zimmerframe@1.1.4: {}
diff --git a/scripts/check-openapi-routes.mjs b/scripts/check-openapi-routes.mjs
new file mode 100644
index 0000000..ea0d785
--- /dev/null
+++ b/scripts/check-openapi-routes.mjs
@@ -0,0 +1,58 @@
+import { readFileSync } from 'node:fs';
+import { parse } from 'yaml';
+
+const routesSource = readFileSync(new URL('../app/Config/Routes.php', import.meta.url), 'utf8');
+const spec = parse(readFileSync(new URL('../docs/openapi.yaml', import.meta.url), 'utf8'));
+const groupStart = routesSource.indexOf("$routes->group('api/v1'");
+const groupEnd = routesSource.indexOf('// Compatibility shims', groupStart);
+
+if (groupStart === -1 || groupEnd === -1) {
+ throw new Error('Unable to locate the api/v1 route group.');
+}
+
+const routeOperations = new Set();
+const routePattern = /\$routes->(get|post|patch|delete)\('([^']+)'/g;
+
+for (const match of routesSource.slice(groupStart, groupEnd).matchAll(routePattern)) {
+ const [, method, route] = match;
+ const parameters = route.startsWith('channels/')
+ ? ['channelId']
+ : route.startsWith('messages/')
+ ? ['messageId', 'emoji']
+ : [];
+ let parameterIndex = 0;
+ const normalizedRoute = route.replace(/\(:(?:num|segment)\)/g, () => {
+ const parameter = parameters[parameterIndex];
+ parameterIndex += 1;
+ if (!parameter) {
+ throw new Error(`No OpenAPI parameter mapping exists for ${route}.`);
+ }
+ return `{${parameter}}`;
+ });
+
+ routeOperations.add(`${method.toUpperCase()} /api/v1/${normalizedRoute}`);
+}
+
+const specOperations = new Set();
+const operationMethods = new Set(['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace']);
+
+for (const [path, pathItem] of Object.entries(spec.paths ?? {})) {
+ for (const method of Object.keys(pathItem ?? {})) {
+ if (operationMethods.has(method)) {
+ specOperations.add(`${method.toUpperCase()} ${path}`);
+ }
+ }
+}
+
+const missing = [...routeOperations].filter((operation) => !specOperations.has(operation)).sort();
+const extra = [...specOperations].filter((operation) => !routeOperations.has(operation)).sort();
+
+if (missing.length > 0 || extra.length > 0) {
+ const details = [
+ missing.length > 0 ? `Missing from docs/openapi.yaml:\n- ${missing.join('\n- ')}` : '',
+ extra.length > 0 ? `Not present in the api/v1 route group:\n- ${extra.join('\n- ')}` : '',
+ ].filter(Boolean);
+ throw new Error(details.join('\n'));
+}
+
+console.log(`OpenAPI route coverage is complete (${routeOperations.size} operations).`);
diff --git a/src/js/api-docs.js b/src/js/api-docs.js
new file mode 100644
index 0000000..87365b3
--- /dev/null
+++ b/src/js/api-docs.js
@@ -0,0 +1,31 @@
+import SwaggerUIBundle from 'swagger-ui-dist/swagger-ui-bundle.js';
+import 'swagger-ui-dist/swagger-ui.css';
+import { parse } from 'yaml';
+
+const root = document.querySelector('#swagger-ui');
+
+if (!(root instanceof HTMLElement)) {
+ throw new Error('Swagger UI mount point is missing.');
+}
+
+const encodedSpec = root.dataset.openapiBase64;
+
+if (!encodedSpec) {
+ throw new Error('The embedded OpenAPI specification is missing.');
+}
+
+const binarySpec = atob(encodedSpec);
+const specBytes = Uint8Array.from(binarySpec, (character) => character.charCodeAt(0));
+const spec = parse(new TextDecoder().decode(specBytes));
+
+SwaggerUIBundle({
+ deepLinking: true,
+ displayRequestDuration: true,
+ dom_id: '#swagger-ui',
+ filter: true,
+ requestInterceptor(request) {
+ request.credentials = 'same-origin';
+ return request;
+ },
+ spec,
+});
diff --git a/tests/Tests/Feature/ApiDocsTest.php b/tests/Tests/Feature/ApiDocsTest.php
new file mode 100644
index 0000000..a183ea9
--- /dev/null
+++ b/tests/Tests/Feature/ApiDocsTest.php
@@ -0,0 +1,35 @@
+call('get', '/api/docs');
+
+ $result->assertOK();
+ $this->assertStringContainsString('public, max-age=300', $result->response()->getHeaderLine('Cache-Control'));
+ $body = $result->getBody();
+ $this->assertStringContainsString('id="swagger-ui"', $body);
+ $this->assertMatchesRegularExpression('#/dist/(?:(?:js/)?api-docs(?:-[A-Za-z0-9_-]+)?|src/js/api-docs)\\.js#', $body);
+ $this->assertStringNotContainsString('cdn.jsdelivr.net', $body);
+
+ preg_match('/data-openapi-base64="([^"]+)"/', $body, $matches);
+ $this->assertArrayHasKey(1, $matches);
+ $spec = base64_decode(html_entity_decode($matches[1], ENT_QUOTES), true);
+ $this->assertIsString($spec);
+ $this->assertStringContainsString('openapi: 3.1.0', $spec);
+ $this->assertStringContainsString('title: CodeIgniter Chat API', $spec);
+ }
+}
diff --git a/vite.config.js b/vite.config.js
index e747490..ec984b1 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -38,6 +38,9 @@ export default defineConfig({
'maskable-icon-512x512.png',
'apple-touch-icon-180x180.png',
],
+ // Swagger UI is only needed on /api/docs. Keep its large, docs-only
+ // bundles out of the install-time cache used by regular chat clients.
+ globIgnores: ['dist/js/api-docs-*.js', 'dist/css/api-docs-*.css'],
},
}),
],
@@ -70,6 +73,7 @@ export default defineConfig({
'chat-html': resolve(import.meta.dirname, 'src/js/chat-html.js'),
'chat-vue': resolve(import.meta.dirname, 'src/vue/main.js'), // Vue.js entry point
'chat-svelte': resolve(import.meta.dirname, 'src/svelte/main.js'), // Svelte entry point
+ 'api-docs': resolve(import.meta.dirname, 'src/js/api-docs.js'),
styles: resolve(import.meta.dirname, 'src/css/chat.scss'),
zipcodes: resolve(import.meta.dirname, 'src/css/zipcodes.scss'),
},