diff --git a/.github/workflows/spec-validate.yml b/.github/workflows/spec-validate.yml new file mode 100644 index 000000000..1ed65cdde --- /dev/null +++ b/.github/workflows/spec-validate.yml @@ -0,0 +1,38 @@ +name: Validate canonical OpenAPI spec + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10.18.1 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Validate OpenAPI spec + run: pnpm spec:validate + + - name: Check generated reference is up to date + run: | + pnpm spec:generate-reference + git diff --exit-code docs/endpoints.md + + - name: Dry-run breaking-change detection + run: pnpm spec:diff diff --git a/.spectral.yaml b/.spectral.yaml new file mode 100644 index 000000000..2b65064c6 --- /dev/null +++ b/.spectral.yaml @@ -0,0 +1,10 @@ +extends: ["spectral:oas"] + +rules: + operation-operationId: error + operation-description: warn + operation-tags: error + operation-tag-defined: error + openapi-tags: warn + info-contact: warn + info-license: warn diff --git a/README.md b/README.md index 59c100d39..90d17385b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,33 @@ # Plex Media Server OpenAPI Specification -An Open Source OpenAPI Specification for Plex Media Server +An open source OpenAPI 3.1 specification for the Plex Media Server API. -Automation and SDKs provided by [Speakeasy](https://speakeasyapi.dev/) +- **Live docs:** [plexapi.dev](https://plexapi.dev) +- **Docs repository:** [LukasParke/plex-mintlify-docs](https://github.com/LukasParke/plex-mintlify-docs) +- **Original developer docs (being consolidated):** [LukasParke/plexapi-dev-docs](https://github.com/LukasParke/plexapi-dev-docs) -## Documentation +## What's in this repository -[API Documentation](https://plexapi.dev) +| File / directory | Purpose | +|------------------|---------| +| `plex-api-spec.yaml` | Canonical OpenAPI 3.1 contract for the Plex Media Server API. | +| `docs/` | Contributor documentation: contract decisions and SDK generation strategy. | +| `scripts/` | Validation, lint, diff, and reference-generation tooling. | +| `.github/workflows/spec-validate.yml` | CI that validates the spec on every PR and push to `main`. | + +## Validation + +```bash +pnpm install +pnpm spec:validate +pnpm spec:lint +pnpm spec:diff +``` ## SDKs -The following SDKs are generated from the OpenAPI Specification. They are automatically generated and may not be fully tested. If you find any issues, please open an issue on the respective repository. +Automation and SDKs are provided by [Speakeasy](https://www.speakeasyapi.dev/). +The following community SDKs are generated from this specification: | Language | Repository | Releases | Other | | --------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------- | @@ -22,3 +39,9 @@ The following SDKs are generated from the OpenAPI Specification. They are automa | PHP | [GitHub](https://github.com/LukeHagar/plexphp) | [Releases](https://github.com/LukeHagar/plexphp/releases) | - | | Java | [GitHub](https://github.com/LukeHagar/plexjava) | [Releases](https://github.com/LukeHagar/plexjava/releases) | - | | C# | [GitHub](https://github.com/LukeHagar/plexcsharp) | [Releases](https://github.com/LukeHagar/plexcsharp/releases) | - | + +## Contributing + +See [docs/api-contract.md](./docs/api-contract.md) and [docs/sdk-generation-strategy.md](./docs/sdk-generation-strategy.md) for design context. + +To propose changes to the spec, open a pull request. The CI check `spec:validate` must pass before merge. diff --git a/docs/api-contract.md b/docs/api-contract.md new file mode 100644 index 000000000..f52f65084 --- /dev/null +++ b/docs/api-contract.md @@ -0,0 +1,40 @@ +# Plex API Contract + +## Decision: OpenAPI 3.1 + +PlexAPI.dev describes the Plex Media Server HTTP API as a curated, versioned [OpenAPI 3.1](https://spec.openapis.org/oas/v3.1.0.html) contract. This decision is aligned with the [SDK generation strategy](./sdk-generation-strategy), which calls for a single source of truth that feeds both reference documentation and SDK generation. + +### Why OpenAPI 3.1 + +| Consideration | Rationale | +|---------------|-----------| +| **Tooling maturity** | OpenAPI 3.1 is supported by Swagger Parser, OpenAPI Generator, Spectral, and many documentation generators. | +| **JSON Schema alignment** | OpenAPI 3.1 schemas are valid JSON Schema 2020-12 drafts, making it easy to reuse models for validation and SDK types. | +| **SDK generation** | OpenAPI Generator and Microsoft Kiota both consume OpenAPI 3.1, matching the hybrid SDK strategy. | +| **Documentation generation** | Reference pages can be generated or hand-written from the same contract, keeping docs and code in sync. | + +## Contract location + +The canonical contract lives at: + +```text +plex-api-spec.yaml +``` + +This file is the single source of truth for the Plex Media Server API. The [PlexAPI.dev documentation site](https://plexapi.dev) and the community SDKs consume this contract. + +## Validation + +The contract is validated on every change via: + +```bash +pnpm install +pnpm spec:validate +pnpm spec:lint +``` + +## Security notes + +- The contract declares `X-Plex-Token` as an `apiKey` security scheme. +- Token values are never included in the spec or generated examples. +- Examples and guides instruct users to load tokens from environment variables or secure configuration. diff --git a/docs/endpoints.md b/docs/endpoints.md new file mode 100644 index 000000000..ebfe0890b --- /dev/null +++ b/docs/endpoints.md @@ -0,0 +1,262 @@ +--- +title: API Endpoints +--- + +# API Endpoints + +This page is generated from [`plex-api-spec.yaml`](./plex-api-spec.yaml). +Do not edit it by hand; run `pnpm run spec:generate-reference` to regenerate it. + +## Overview + +| Method | Path | Summary | Operation ID | +| ------ | ---- | ------- | ------------ | +| GET | `/` | Get PMS info | `getServerInfo` | +| GET | `/:/eventsource/notifications` | Connect to Eventsource | `getNotifications` | +| GET | `/:/prefs` | Get all preferences | `getAllPreferences` | +| PUT | `/:/prefs` | Set preferences | `setPreferences` | +| GET | `/:/prefs/get` | Get a preferences | `getPreference` | +| PUT | `/:/rate` | Rate an item | `setRating` | +| PUT | `/:/scrobble` | Mark an item as played | `markPlayed` | +| POST | `/:/timeline` | Report media timeline | `report` | +| PUT | `/:/unscrobble` | Mark an item as unplayed | `unscrobble` | +| GET | `/:/websocket/notifications` | Connect to WebSocket | `connectWebSocket` | +| GET | `/{transcodeType}/:/transcode/universal/decision` | Make a decision on media playback | `makeDecision` | +| POST | `/{transcodeType}/:/transcode/universal/fallback` | Manually trigger a transcoder fallback | `triggerFallback` | +| GET | `/{transcodeType}/:/transcode/universal/start.{extension}` | Start A Transcoding Session | `startTranscodeSession` | +| GET | `/{transcodeType}/:/transcode/universal/subtitles` | Transcode subtitles | `transcodeSubtitles` | +| GET | `/activities` | Get all activities | `listActivities` | +| DELETE | `/activities/{activityId}` | Cancel a running activity | `cancelActivity` | +| DELETE | `/butler` | Stop all Butler tasks | `stopTasks` | +| GET | `/butler` | Get all Butler tasks | `getTasks` | +| POST | `/butler` | Start all Butler tasks | `startTasks` | +| DELETE | `/butler/{butlerTask}` | Stop a single Butler task | `stopTask` | +| POST | `/butler/{butlerTask}` | Start a single Butler task | `startTask` | +| POST | `/downloadQueue` | Create download queue | `createDownloadQueue` | +| GET | `/downloadQueue/{queueId}` | Get a download queue | `getDownloadQueue` | +| POST | `/downloadQueue/{queueId}/add` | Add to download queue | `addDownloadQueueItems` | +| GET | `/downloadQueue/{queueId}/item/{itemId}/decision` | Grab download queue item decision | `getItemDecision` | +| GET | `/downloadQueue/{queueId}/item/{itemId}/media` | Grab download queue media | `getDownloadQueueMedia` | +| GET | `/downloadQueue/{queueId}/items` | Get download queue items | `listDownloadQueueItems` | +| DELETE | `/downloadQueue/{queueId}/items/{itemId}` | Delete download queue items | `removeDownloadQueueItems` | +| GET | `/downloadQueue/{queueId}/items/{itemId}` | Get download queue items | `getDownloadQueueItems` | +| POST | `/downloadQueue/{queueId}/items/{itemId}/restart` | Restart processing of items from the decision | `restartProcessingDownloadQueueItems` | +| GET | `/hubs` | Get global hubs | `getAllHubs` | +| GET | `/hubs/continueWatching` | Get the continue watching hub | `getContinueWatching` | +| GET | `/hubs/items` | Get a hub's items | `getHubItems` | +| GET | `/hubs/metadata/{metadataId}` | Get hubs for section by metadata item | `getMetadataHubs` | +| GET | `/hubs/metadata/{metadataId}/postplay` | Get postplay hubs | `getPostplayHubs` | +| GET | `/hubs/metadata/{metadataId}/related` | Get related hubs | `getRelatedHubs` | +| GET | `/hubs/promoted` | Get the hubs which are promoted | `getPromotedHubs` | +| GET | `/hubs/search` | Search Hub | `searchHubs` | +| GET | `/hubs/search/voice` | Voice Search Hub | `voiceSearchHubs` | +| GET | `/hubs/sections/{sectionId}` | Get section hubs | `getSectionHubs` | +| DELETE | `/hubs/sections/{sectionId}/manage` | Reset hubs to defaults | `resetSectionDefaults` | +| GET | `/hubs/sections/{sectionId}/manage` | Get hubs | `listHubs` | +| POST | `/hubs/sections/{sectionId}/manage` | Create a custom hub | `createCustomHub` | +| DELETE | `/hubs/sections/{sectionId}/manage/{identifier}` | Delete a custom hub | `deleteCustomHub` | +| PUT | `/hubs/sections/{sectionId}/manage/{identifier}` | Change hub visibility | `updateHubVisibility` | +| PUT | `/hubs/sections/{sectionId}/manage/move` | Move Hub | `moveHub` | +| GET | `/identity` | Get PMS identity | `getIdentity` | +| GET | `/library/all` | Get all items in library | `getLibraryItems` | +| DELETE | `/library/caches` | Delete library caches | `deleteCaches` | +| PUT | `/library/clean/bundles` | Clean bundles | `cleanBundles` | +| POST | `/library/collections` | Create collection | `createCollection` | +| GET | `/library/collections/{collectionId}/composite/{updatedAt}` | Get a collection's image | `getCollectionImage` | +| GET | `/library/collections/{collectionId}/items` | Get items in a collection | `getCollectionItems` | +| PUT | `/library/collections/{collectionId}/items` | Add items to a collection | `addCollectionItems` | +| PUT | `/library/collections/{collectionId}/items/{itemId}` | Delete an item from a collection | `deleteCollectionItem` | +| PUT | `/library/collections/{collectionId}/items/{itemId}/move` | Reorder an item in the collection | `moveCollectionItem` | +| POST | `/library/file` | Ingest a transient item | `ingestTransientItem` | +| GET | `/library/matches` | Get library matches | `getLibraryMatches` | +| GET | `/library/media/{mediaId}/chapterImages/{chapter}` | Get a chapter image | `getChapterImage` | +| DELETE | `/library/metadata/{ids}` | Delete a metadata item | `deleteMetadataItem` | +| GET | `/library/metadata/{ids}` | Get a metadata item | `getMetadataItem` | +| PUT | `/library/metadata/{ids}` | Edit a metadata item | `editMetadataItem` | +| POST | `/library/metadata/{ids}/{element}` | Set an item's artwork, theme, etc | `setItemArtwork` | +| PUT | `/library/metadata/{ids}/{element}` | Set an item's artwork, theme, etc | `updateItemArtwork` | +| GET | `/library/metadata/{ids}/{element}/{timestamp}` | Get an item's artwork, theme, etc | `getItemArtwork` | +| PUT | `/library/metadata/{ids}/addetect` | Ad-detect an item | `detectAds` | +| GET | `/library/metadata/{ids}/allLeaves` | Get the leaves of an item | `getAllItemLeaves` | +| PUT | `/library/metadata/{ids}/analyze` | Analyze an item | `analyzeMetadata` | +| PUT | `/library/metadata/{ids}/chapterThumbs` | Generate thumbs of chapters for an item | `generateThumbs` | +| PUT | `/library/metadata/{ids}/credits` | Credit detect a metadata item | `detectCredits` | +| GET | `/library/metadata/{ids}/extras` | Get an item's extras | `getExtras` | +| POST | `/library/metadata/{ids}/extras` | Add to an item's extras | `addExtras` | +| GET | `/library/metadata/{ids}/file` | Get a file from a metadata or media bundle | `getFile` | +| PUT | `/library/metadata/{ids}/index` | Start BIF generation of an item | `startBifGeneration` | +| PUT | `/library/metadata/{ids}/intro` | Intro detect an item | `detectIntros` | +| POST | `/library/metadata/{ids}/marker` | Create a marker | `createMarker` | +| DELETE | `/library/metadata/{ids}/marker/{marker}` | Delete a marker | `deleteMarker` | +| PUT | `/library/metadata/{ids}/marker/{marker}` | Edit a marker | `editMarker` | +| PUT | `/library/metadata/{ids}/match` | Match a metadata item | `matchItem` | +| PUT | `/library/metadata/{ids}/matches` | Get metadata matches for an item | `listMatches` | +| DELETE | `/library/metadata/{ids}/media/{mediaItem}` | Delete a media item | `deleteMediaItem` | +| PUT | `/library/metadata/{ids}/merge` | Merge a metadata item | `mergeItems` | +| GET | `/library/metadata/{ids}/nearest` | Get nearest tracks to metadata item | `listSonicallySimilar` | +| PUT | `/library/metadata/{ids}/prefs` | Set metadata preferences | `setItemPreferences` | +| PUT | `/library/metadata/{ids}/refresh` | Refresh a metadata item | `refreshItemsMetadata` | +| GET | `/library/metadata/{ids}/related` | Get related items | `getRelatedItems` | +| GET | `/library/metadata/{ids}/similar` | Get similar items | `listSimilar` | +| PUT | `/library/metadata/{ids}/split` | Split a metadata item | `splitItem` | +| GET | `/library/metadata/{ids}/subtitles` | Add subtitles | `addSubtitles` | +| GET | `/library/metadata/{ids}/tree` | Get metadata items as a tree | `getItemTree` | +| PUT | `/library/metadata/{ids}/unmatch` | Unmatch a metadata item | `unmatch` | +| GET | `/library/metadata/{ids}/users/top` | Get metadata top users | `listTopUsers` | +| PUT | `/library/metadata/{ids}/voiceActivity` | Detect voice activity | `detectVoiceActivity` | +| GET | `/library/metadata/augmentations/{augmentationId}` | Get augmentation status | `getAugmentationStatus` | +| PUT | `/library/optimize` | Optimize the Database | `optimizeDatabase` | +| PUT | `/library/parts/{partId}` | Set stream selection | `setStreamSelection` | +| GET | `/library/parts/{partId}/{changestamp}/{filename}` | Get a media part | `getMediaPart` | +| GET | `/library/parts/{partId}/indexes/{index}` | Get BIF index for a part | `getPartIndex` | +| GET | `/library/parts/{partId}/indexes/{index}/{offset}` | Get an image from part BIF | `getImageFromBif` | +| GET | `/library/people/{personId}` | Get person details | `getPerson` | +| GET | `/library/people/{personId}/media` | Get media for a person | `listPersonMedia` | +| GET | `/library/randomArtwork` | Get random artwork | `getRandomArtwork` | +| DELETE | `/library/sections/{sectionId}` | Delete a library section | `deleteLibrarySection` | +| GET | `/library/sections/{sectionId}` | Get a library section by id | `getLibraryDetails` | +| PUT | `/library/sections/{sectionId}` | Edit a library section | `editSection` | +| GET | `/library/sections/{sectionId}/albums` | Set section albums | `getAlbums` | +| GET | `/library/sections/{sectionId}/all` | Get items in the section | `listContent` | +| PUT | `/library/sections/{sectionId}/all` | Set the fields of the filtered items | `updateItems` | +| GET | `/library/sections/{sectionId}/allLeaves` | Set section leaves | `getAllLeaves` | +| PUT | `/library/sections/{sectionId}/analyze` | Analyze a section | `startAnalysis` | +| GET | `/library/sections/{sectionId}/arts` | Set section artwork | `getArts` | +| GET | `/library/sections/{sectionId}/autocomplete` | Get autocompletions for search | `autocomplete` | +| GET | `/library/sections/{sectionId}/categories` | Set section categories | `getCategories` | +| GET | `/library/sections/{sectionId}/cluster` | Set section clusters | `getCluster` | +| DELETE | `/library/sections/{sectionId}/collection/{collectionId}` | Delete a collection | `deleteCollection` | +| GET | `/library/sections/{sectionId}/collections` | Get collections in a section | `getCollections` | +| GET | `/library/sections/{sectionId}/common` | Get common fields for items | `getCommon` | +| GET | `/library/sections/{sectionId}/composite/{updatedAt}` | Get a section composite image | `getSectionImage` | +| GET | `/library/sections/{sectionId}/computePath` | Similar tracks to transition from one to another | `getSonicPath` | +| PUT | `/library/sections/{sectionId}/emptyTrash` | Empty section trash | `emptyTrash` | +| GET | `/library/sections/{sectionId}/filters` | Get section filters | `getSectionFilters` | +| GET | `/library/sections/{sectionId}/firstCharacters` | Get list of first characters | `getFirstCharacters` | +| DELETE | `/library/sections/{sectionId}/indexes` | Delete section indexes | `deleteIndexes` | +| DELETE | `/library/sections/{sectionId}/intros` | Delete section intro markers | `deleteIntros` | +| GET | `/library/sections/{sectionId}/location` | Get all folder locations | `getFolders` | +| GET | `/library/sections/{sectionId}/moment` | Set section moments | `listMoments` | +| GET | `/library/sections/{sectionId}/nearest` | The nearest audio tracks | `getSonicallySimilar` | +| GET | `/library/sections/{sectionId}/prefs` | Get section prefs | `getSectionPreferences` | +| PUT | `/library/sections/{sectionId}/prefs` | Set section prefs | `setSectionPreferences` | +| DELETE | `/library/sections/{sectionId}/refresh` | Cancel section refresh | `cancelRefresh` | +| POST | `/library/sections/{sectionId}/refresh` | Refresh section | `refreshSection` | +| GET | `/library/sections/{sectionId}/sorts` | Get a section sorts | `getAvailableSorts` | +| GET | `/library/sections/all` | Get library sections (main Media Provider Only) | `getSections` | +| POST | `/library/sections/all` | Add a library section | `addSection` | +| DELETE | `/library/sections/all/refresh` | Stop refresh | `stopAllRefreshes` | +| GET | `/library/sections/prefs` | Get section prefs | `getSectionsPrefs` | +| POST | `/library/sections/refresh` | Refresh all sections | `refreshSectionsMetadata` | +| DELETE | `/library/streams/{streamId}.{ext}` | Delete a stream | `deleteStream` | +| GET | `/library/streams/{streamId}.{ext}` | Get a stream | `getStream` | +| PUT | `/library/streams/{streamId}.{ext}` | Set a stream offset | `setStreamOffset` | +| GET | `/library/streams/{streamId}/levels` | Get loudness about a stream in json | `getStreamLevels` | +| GET | `/library/streams/{streamId}/loudness` | Get loudness about a stream | `getStreamLoudness` | +| GET | `/library/tags` | Get all library tags of a type | `getTags` | +| GET | `/livetv/dvrs` | Get DVRs | `listDVRs` | +| POST | `/livetv/dvrs` | Create a DVR | `createDVR` | +| DELETE | `/livetv/dvrs/{dvrId}` | Delete a single DVR | `deleteDVR` | +| GET | `/livetv/dvrs/{dvrId}` | Get a single DVR | `getDVR` | +| POST | `/livetv/dvrs/{dvrId}/channels/{channel}/tune` | Tune a channel on a DVR | `tuneChannel` | +| DELETE | `/livetv/dvrs/{dvrId}/devices/{deviceId}` | Remove a device from an existing DVR | `removeDeviceFromDVR` | +| PUT | `/livetv/dvrs/{dvrId}/devices/{deviceId}` | Add a device to an existing DVR | `addDeviceToDVR` | +| DELETE | `/livetv/dvrs/{dvrId}/lineups` | Delete a DVR Lineup | `deleteLineup` | +| PUT | `/livetv/dvrs/{dvrId}/lineups` | Add a DVR Lineup | `addLineup` | +| PUT | `/livetv/dvrs/{dvrId}/prefs` | Set DVR preferences | `setDVRPreferences` | +| DELETE | `/livetv/dvrs/{dvrId}/reloadGuide` | Tell a DVR to stop reloading program guide | `stopDVRReload` | +| POST | `/livetv/dvrs/{dvrId}/reloadGuide` | Tell a DVR to reload program guide | `reloadGuide` | +| GET | `/livetv/epg/channelmap` | Compute the best channel map | `computeChannelMap` | +| GET | `/livetv/epg/channels` | Get channels for a lineup | `getChannels` | +| GET | `/livetv/epg/countries` | Get all countries | `getCountries` | +| GET | `/livetv/epg/countries/{country}/{epgId}/lineups` | Get lineups for a country via postal code | `getCountriesLineups` | +| GET | `/livetv/epg/countries/{country}/{epgId}/regions` | Get regions for a country | `getCountryRegions` | +| GET | `/livetv/epg/countries/{country}/{epgId}/regions/{region}/lineups` | Get lineups for a region | `listLineups` | +| GET | `/livetv/epg/languages` | Get all languages | `getAllLanguages` | +| GET | `/livetv/epg/lineup` | Compute the best lineup | `getLineup` | +| GET | `/livetv/epg/lineupchannels` | Get the channels for mulitple lineups | `getLineupChannels` | +| GET | `/livetv/sessions` | Get all sessions | `getSessions` | +| GET | `/livetv/sessions/{sessionId}` | Get a single session | `getLiveTVSession` | +| GET | `/livetv/sessions/{sessionId}/{consumerId}/{segmentId}` | Get a single session segment | `getSessionSegment` | +| GET | `/livetv/sessions/{sessionId}/{consumerId}/index.m3u8` | Get a session playlist index | `getSessionPlaylistIndex` | +| POST | `/log` | Logging a multi-line message to the Plex Media Server log | `writeLog` | +| PUT | `/log` | Logging a single-line message to the Plex Media Server log | `writeMessage` | +| POST | `/log/networked` | Enabling Papertrail | `enablePapertrail` | +| GET | `/media/grabbers` | Get available grabbers | `getAvailableGrabbers` | +| GET | `/media/grabbers/devices` | Get all devices | `listDevices` | +| POST | `/media/grabbers/devices` | Add a device | `addDevice` | +| DELETE | `/media/grabbers/devices/{deviceId}` | Remove a device | `removeDevice` | +| GET | `/media/grabbers/devices/{deviceId}` | Get device details | `getDeviceDetails` | +| PUT | `/media/grabbers/devices/{deviceId}` | Enable or disable a device | `modifyDevice` | +| PUT | `/media/grabbers/devices/{deviceId}/channelmap` | Set a device's channel mapping | `setChannelmap` | +| GET | `/media/grabbers/devices/{deviceId}/channels` | Get a device's channels | `getDevicesChannels` | +| PUT | `/media/grabbers/devices/{deviceId}/prefs` | Set device preferences | `setDevicePreferences` | +| DELETE | `/media/grabbers/devices/{deviceId}/scan` | Tell a device to stop scanning for channels | `stopScan` | +| POST | `/media/grabbers/devices/{deviceId}/scan` | Tell a device to scan for channels | `scan` | +| GET | `/media/grabbers/devices/{deviceId}/thumb/{version}` | Get device thumb | `getThumb` | +| POST | `/media/grabbers/devices/discover` | Tell grabbers to discover devices | `discoverDevices` | +| DELETE | `/media/grabbers/operations/{operationId}` | Cancel an existing grab | `cancelGrab` | +| GET | `/media/providers` | Get the list of available media providers | `listProviders` | +| POST | `/media/providers` | Add a media provider | `addProvider` | +| DELETE | `/media/providers/{provider}` | Delete a media provider | `deleteMediaProvider` | +| POST | `/media/providers/refresh` | Refresh media providers | `refreshProviders` | +| GET | `/media/subscriptions` | Get all subscriptions | `getAllSubscriptions` | +| POST | `/media/subscriptions` | Create a subscription | `createSubscription` | +| DELETE | `/media/subscriptions/{subscriptionId}` | Delete a subscription | `deleteSubscription` | +| GET | `/media/subscriptions/{subscriptionId}` | Get a single subscription | `getSubscription` | +| PUT | `/media/subscriptions/{subscriptionId}` | Edit a subscription | `editSubscriptionPreferences` | +| PUT | `/media/subscriptions/{subscriptionId}/move` | Re-order a subscription | `reorderSubscription` | +| POST | `/media/subscriptions/process` | Process all subscriptions | `processSubscriptions` | +| GET | `/media/subscriptions/scheduled` | Get all scheduled recordings | `getScheduledRecordings` | +| GET | `/media/subscriptions/template` | Get the subscription template | `getTemplate` | +| GET | `/photo/:/transcode` | Transcode an image | `transcodeImage` | +| GET | `/playlists` | List playlists | `listPlaylists` | +| POST | `/playlists` | Create a Playlist | `createPlaylist` | +| DELETE | `/playlists/{playlistId}` | Delete a Playlist | `deletePlaylist` | +| GET | `/playlists/{playlistId}` | Retrieve Playlist | `getPlaylist` | +| PUT | `/playlists/{playlistId}` | Editing a Playlist | `updatePlaylist` | +| GET | `/playlists/{playlistId}/generators` | Get a playlist's generators | `getPlaylistGenerators` | +| DELETE | `/playlists/{playlistId}/items` | Clearing a playlist | `clearPlaylistItems` | +| GET | `/playlists/{playlistId}/items` | Retrieve Playlist Contents | `getPlaylistItems` | +| PUT | `/playlists/{playlistId}/items` | Adding to a Playlist | `addPlaylistItems` | +| DELETE | `/playlists/{playlistId}/items/{generatorId}` | Delete a Generator | `deletePlaylistItem` | +| GET | `/playlists/{playlistId}/items/{generatorId}` | Get a playlist generator | `getPlaylistGenerator` | +| PUT | `/playlists/{playlistId}/items/{generatorId}` | Modify a Generator | `modifyPlaylistGenerator` | +| PUT | `/playlists/{playlistId}/items/{generatorId}/{metadataId}/{action}` | Reprocess a generator | `refreshPlaylist` | +| GET | `/playlists/{playlistId}/items/{generatorId}/items` | Get a playlist generator's items | `getPlaylistGeneratorItems` | +| PUT | `/playlists/{playlistId}/items/{playlistItemId}/move` | Moving items in a playlist | `movePlaylistItem` | +| POST | `/playlists/upload` | Upload | `uploadPlaylist` | +| POST | `/playQueues` | Create a play queue | `createPlayQueue` | +| GET | `/playQueues/{playQueueId}` | Retrieve a play queue | `getPlayQueue` | +| PUT | `/playQueues/{playQueueId}` | Add a generator or playlist to a play queue | `addToPlayQueue` | +| DELETE | `/playQueues/{playQueueId}/items` | Clear a play queue | `clearPlayQueue` | +| DELETE | `/playQueues/{playQueueId}/items/{playQueueItemId}` | Delete an item from a play queue | `deletePlayQueueItem` | +| PUT | `/playQueues/{playQueueId}/items/{playQueueItemId}/move` | Move an item in a play queue | `movePlayQueueItem` | +| PUT | `/playQueues/{playQueueId}/reset` | Reset a play queue | `resetPlayQueue` | +| PUT | `/playQueues/{playQueueId}/shuffle` | Shuffle a play queue | `shuffle` | +| PUT | `/playQueues/{playQueueId}/unshuffle` | Unshuffle a play queue | `unshuffle` | +| GET | `/resources` | Get Server Resources | `get-server-resources` | +| GET | `/security/resources` | Get Source Connection Information | `getSourceConnectionInformation` | +| POST | `/security/token` | Get Transient Tokens | `getTransientToken` | +| GET | `/services/ultrablur/colors` | Get UltraBlur Colors | `getColors` | +| GET | `/services/ultrablur/image` | Get UltraBlur Image | `getImage` | +| GET | `/status/sessions` | List Sessions | `listSessions` | +| GET | `/status/sessions/background` | Get background tasks | `getBackgroundTasks` | +| DELETE | `/status/sessions/history/{historyId}` | Delete Single History Item | `deleteHistory` | +| GET | `/status/sessions/history/{historyId}` | Get Single History Item | `getHistoryItem` | +| GET | `/status/sessions/history/all` | List Playback History | `listPlaybackHistory` | +| POST | `/status/sessions/terminate` | Terminate a session | `terminateSession` | +| PUT | `/updater/apply` | Applying updates | `applyUpdates` | +| PUT | `/updater/check` | Checking for updates | `checkUpdates` | +| GET | `/updater/status` | Querying status of updates | `getUpdatesStatus` | +| GET | `/user` | Get Token Details | `getTokenDetails` | +| GET | `/users` | Get list of all connected users | `get-users` | +| POST | `/users/signin` | Get User Sign In Data | `post-users-sign-in-data` | + +## Authentication + +Most endpoints require an `X-Plex-Token` header or `X-Plex-Token` query parameter. + +## Response format + +Responses default to XML. Request JSON by sending `Accept: application/json`. diff --git a/docs/sdk-generation-strategy.md b/docs/sdk-generation-strategy.md new file mode 100644 index 000000000..d7ae489ef --- /dev/null +++ b/docs/sdk-generation-strategy.md @@ -0,0 +1,267 @@ +--- +title: SDK Generation Strategy +description: How PlexAPI.dev produces, publishes, and maintains SDKs for the Plex Media Server API. +--- + +# PlexAPI.dev SDK Generation Strategy + +## Status +Draft v1.0 — ready for technical review and implementation planning. + +## Objective +Define how [PlexAPI.dev](https://plexapi.dev) produces, publishes, and maintains idiomatic software development kits (SDKs) for the Plex Media Server API. + +## Decision summary + +| Dimension | Decision | +|-----------|----------| +| **Approach** | **Hybrid**: OpenAPI-generated core clients + hand-written ergonomic wrappers, resource models, and helpers. | +| **Spec source** | Maintain the curated, versioned OpenAPI 3.1 description in this repository (`plex-api-spec.yaml`). | +| **Primary generator** | **OpenAPI Generator** for the initial multi-language rollout; evaluate **Microsoft Kiota** and **Speakeasy** as the platform matures. | +| **Target languages (phase 1)** | TypeScript/JavaScript, Python, Go | +| **Target languages (phase 2)** | C#, Java, Ruby, Rust, PHP | +| **Release/versioning** | Independent SemVer per SDK; compatibility matrix maps SDK versions to Plex server versions. | +| **Distribution** | Language-native package managers (npm, PyPI, Go modules, NuGet, Maven, etc.). | +| **License** | MIT (community-friendly, permissive). | + +--- + +## 1. Background and constraints + +Plex Media Server exposes a rich HTTP/XML/JSON API, but it is not officially documented as a machine-readable contract. The PlexAPI.dev site captures endpoints, parameters, and response shapes. Turning that knowledge into reliable SDKs requires: + +1. A single source of truth for the API contract (`plex-api-spec.yaml` in this repository). +2. A generator toolchain that can target multiple languages without rewriting each SDK from scratch. +3. Idiomatic, hand-finished layers on top of generated code so each SDK feels native. +4. Automated pipelines that regenerate clients when the contract changes. +5. Clear versioning so users know which SDK works with which Plex server release. + +### Non-goals for this design +- Rebuilding the Plex Media Server itself. +- Supporting every programming language immediately. +- Guaranteeing 100 % feature parity with every undocumented/private endpoint on day one. + +--- + +## 2. Target languages + +### Phase 1 — launch languages + +These languages cover the largest Plex developer communities and existing tooling: + +| Language | Rationale | Existing ecosystem signal | +|----------|-----------|---------------------------| +| **Python** | Dominant Plex automation community (`python-plexapi`, `Tautulli`, custom scripts). | High | +| **TypeScript / JavaScript** | Web apps, Node automation, browser extensions, modern UI frameworks. | High | +| **Go** | CLI tools, server-side integrations, infrastructure projects, binary distribution. | Medium-High | + +### Phase 2 — expansion languages + +| Language | Rationale | +|----------|-----------| +| **C# / .NET** | Windows ecosystem, media center integrations, game modding. | +| **Java** | Enterprise/media management backends, Android-adjacent tooling. | +| **Ruby** | Home automation and scripting community. | +| **Rust** | Performance-sensitive CLI/tools, cross-platform binaries. | +| **PHP** | Web hosting ecosystem, WordPress/plugins. | + +### Selection criteria + +1. **Community size** in the Plex / media-server / home-automation space. +2. **Package-manager maturity** and discoverability. +3. **Generator support** in the chosen toolchain. +4. **Maintenance bandwidth** — each language adds CI, release, and support cost. +5. **Strategic value** for partners and integrations. + +--- + +## 3. Generated vs. hand-written vs. hybrid + +### Option A — fully hand-written +- **Pros** perfect ergonomics, full control. +- **Cons** unsustainable across 5+ languages; every endpoint change must be manually ported. +- **Verdict** rejected for core clients. + +### Option B — fully generated +- **Pros** fast propagation of API changes, broad language coverage. +- **Cons** generated code is often unidiomatic, lacks helper methods, error context, and resource-oriented abstractions. +- **Verdict** rejected as the user-facing surface. + +### Option C — hybrid (selected) +- **Generated layer** (`plexapi-{lang}-generated` or internal package) handles HTTP transport, serialization, request/response models, and authentication headers from the OpenAPI spec. +- **Hand-written layer** (`plexapi-{lang}`) provides: + - Resource-oriented fluent interfaces (e.g., `client.libraries.movies()`). + - Convenience methods for common workflows (search, playback, transcoding). + - Retry, rate-limit, and connection-pool defaults tuned for Plex. + - Token-safe credential helpers and configuration builders. + - Idiomatic error types and documentation. +- **Verdict** selected. It balances velocity with developer experience. + +--- + +## 4. OpenAPI contract and parser toolchain + +### Spec curation + +1. The canonical OpenAPI 3.1 document lives in this repository as `plex-api-spec.yaml`. +2. Document endpoints already covered on PlexAPI.dev plus high-value undocumented endpoints validated by the community. +3. Tag each operation with `x-plex-api-since` (server version introduced) and `x-plex-api-deprecated` where applicable. +4. Add `x-plex-resource` tags to group endpoints by domain (Library, Server, Sessions, Playlists, etc.). + +### Parser / generator options + +| Tool | Strengths | Concerns | +|------|-----------|----------| +| **OpenAPI Generator** | Mature, 50+ languages, active community, customizable templates. | Templates vary in quality; requires tuning for idiomatic output. | +| **Microsoft Kiota** | Clean abstraction layer, strong TypeScript/C#/Java/Go/Ruby/PHP support, auth-agnostic. | Younger ecosystem; Python support is newer. | +| **Speakeasy** | Managed, high-quality idiomatic SDKs, docs, and changelogs. | Commercial cost at scale; less control over templates. | + +### Recommended toolchain + +- **Start with OpenAPI Generator** because it gives full control, is free/open-source, and supports all Phase 1 languages well. +- Maintain custom generator templates per language in `sdk-templates/{language}` so output stays idiomatic. +- Run a **6-month evaluation of Kiota** (and optionally Speakeasy) using the TypeScript SDK as a pilot. The decision to switch one or more languages will be data-driven. + +### Validation pipeline + +Every spec change triggers: +1. OpenAPI linting (`spectral`). +2. Example validation against real or recorded Plex responses. +3. Generator dry-run for all Phase 1 languages. +4. Breaking-change detection with `openapi-diff`. + +--- + +## 5. Repository and package structure + +This repository (`LukasParke/plex-api-spec`) owns the canonical contract and the tooling that validates it: + +``` +. +├── plex-api-spec.yaml # canonical contract +├── docs/ +│ ├── api-contract.md # contract decisions +│ └── sdk-generation-strategy.md # this document +├── scripts/ +│ ├── validate-spec.mjs # OpenAPI validation +│ ├── openapi-diff.mjs # breaking-change detection +│ └── generate-reference.mjs # static operation list +├── sdk-templates/ +│ ├── typescript/ +│ ├── python/ +│ └── go/ +└── README.md +``` + +Language-specific SDKs live in their own repositories and are published independently: + +| Language | Package name | +|----------|--------------| +| TypeScript | `@plexapi/sdk` | +| Python | `plexapi-sdk` | +| Go | `github.com/plexapi/plexapi-go` | +| C# | `PlexApi.Sdk` | +| Java | `dev.plexapi:plexapi-sdk` | + +--- + +## 6. Release and versioning strategy + +### Independent SemVer + +Each SDK follows [SemVer 2.0](https://semver.org/) independently. The SDK version is **not** tied to the Plex Media Server version. + +- **Major** — breaking changes to public SDK API or dropped Plex server compatibility. +- **Minor** — new endpoints/features, backward-compatible. +- **Patch** — bug fixes, generated updates from non-breaking spec changes. + +### Compatibility matrix + +Publish a `COMPATIBILITY.md` per SDK and a central matrix on PlexAPI.dev: + +| SDK version | Plex server min | Plex server max | Notes | +|-------------|-----------------|-----------------|-------| +| `python-plexapi-sdk 1.0.0` | `1.31.0` | `1.40.x` | Initial release | +| `python-plexapi-sdk 1.1.0` | `1.31.0` | `1.41.x` | Added playlist endpoints | + +### Spec version + +The OpenAPI spec itself uses `major.minor` versioning: +- **Spec major** increments on breaking endpoint/contract changes. +- **Spec minor** increments on additive changes. + +SDK generator config pins the spec revision used to build a release. + +### Release cadence + +- **On spec minor change** — regenerate and release patch/minor SDKs automatically. +- **On spec major change** — manual review; release new SDK major with migration guide. +- **Quarterly** — review Phase 2 language candidates and template quality. + +--- + +## 7. Security and authentication + +1. **Token handling** — SDKs accept Plex tokens via environment variables, configuration files, or runtime arguments; never embed tokens in generated code or examples. +2. **HTTPS by default** — require explicit opt-in for HTTP (local servers). +3. **No credential logging** — redact `X-Plex-Token` and `Plex-Token` from debug logs. +4. **Pinned base URLs** — default to `https://plex.tv` for account endpoints and `https://` for local server endpoints. + +--- + +## 8. Developer experience (DX) standards + +Every Phase 1 SDK must provide: + +1. **Installation** via native package manager. +2. **Quickstart example** covering discovery of a local server and listing libraries. +3. **Typed models** for request/response payloads. +4. **Resource-oriented API** where practical. +5. **Consistent error hierarchy** (`PlexApiError`, `PlexApiAuthError`, `PlexApiTimeoutError`, etc.). +6. **Retry configuration** with sensible defaults for local-media-server workloads. +7. **Changelog** generated from conventional commits and spec changes. +8. **API reference docs** generated from OpenAPI + hand-written guides. + +--- + +## 9. Community and contribution model + +1. Open-source all SDKs under the MIT license. +2. Use GitHub Issues for bug reports and feature requests; use GitHub Discussions for language proposals. +3. Require CLA or DCO for external contributions. +4. Publish a `CONTRIBUTING.md` per language covering generator templates, local development, and testing. +5. Add a Code of Conduct and Security Policy. + +--- + +## 10. Implementation roadmap + +| Milestone | Deliverable | Owner | Estimated effort | +|-----------|-------------|-------|------------------| +| M1 | Expand canonical OpenAPI 3.1 spec covering top endpoints. | API Docs / Coder | 2–3 weeks | +| M2 | OpenAPI Generator config + custom templates for TypeScript. | Coder | 1–2 weeks | +| M3 | Hand-written ergonomic layer for TypeScript SDK + examples. | Coder | 2 weeks | +| M4 | Python SDK (generated + hand-written layer). | Coder | 2 weeks | +| M5 | Go SDK (generated + hand-written layer). | Coder | 2 weeks | +| M6 | CI/CD pipelines for spec validation, generation, and release. | Coder / DevOps | 2 weeks | +| M7 | Public docs site integration, compatibility matrix, and announcement. | CTO / Docs | 1 week | +| M8 | Evaluate Kiota/Speakeasy pilot and decide on Phase 2 languages. | CTO | Ongoing | + +--- + +## 11. Risks and mitigations + +| Risk | Impact | Mitigation | +|------|--------|------------| +| Plex changes undocumented endpoints without notice. | High | Build a community-driven spec diff/validation pipeline; maintain deprecation windows. | +| Generated code is unidiomatic. | Medium | Invest in custom templates and a thick hand-written layer. | +| Maintenance burden across languages. | Medium | Start with 3 languages; gate expansion on community demand and maintainer bandwidth. | +| Commercial generator lock-in. | Low | Keep the spec canonical and portable; evaluate open-source generators first. | + +--- + +## 12. Next steps + +1. Create child issues for M1–M6 and assign owners. +2. Expand the canonical OpenAPI spec (`plex-api-spec.yaml`) from existing PlexAPI.dev documentation. +3. Build the first TypeScript SDK end-to-end as a proof of concept. diff --git a/package.json b/package.json new file mode 100644 index 000000000..a9eb72295 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "@plexapi/plex-api-spec", + "version": "0.1.0", + "private": true, + "type": "module", + "description": "Canonical OpenAPI specification for Plex Media Server", + "packageManager": "pnpm@10.18.1", + "scripts": { + "spec:validate": "node scripts/validate-spec.mjs", + "spec:lint": "spectral lint plex-api-spec.yaml", + "spec:diff": "node scripts/openapi-diff.mjs", + "spec:generate-reference": "node scripts/generate-reference.mjs", + "format": "prettier --write ." + }, + "devDependencies": { + "@apidevtools/swagger-parser": "^12.1.0", + "@stoplight/spectral-cli": "^6.14.5", + "prettier": "^3.5.3" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/plex-api-spec.yaml b/plex-api-spec.yaml index 71803e99f..29576b217 100644 --- a/plex-api-spec.yaml +++ b/plex-api-spec.yaml @@ -9,29 +9,22 @@ servers: - url: "https://{IP-description}.{identifier}.plex.direct:{port}" variables: identifier: - description: The unique identifier of this particular PMS default: 0123456789abcdef0123456789abcdef IP-description: - description: A `-` separated string of the IPv4 or IPv6 address components default: 1-2-3-4 port: - description: The Port number configured on the PMS. Typically (`32400`). default: '32400' - url: "{protocol}://{host}:{port}" variables: protocol: - description: The network protocol to use. Typically (`http` or `https`) default: http host: - description: "The Host of the PMS.\nIf using on a local network, this is the internal IP address of the server hosting the PMS.\nIf using on an external network, this is the external IP address for your network, and requires port forwarding.\nIf using a reverse proxy, this would be the external DNS domain for your network, and requires the proxy handle port forwarding. \n" default: localhost port: - description: "The Port number configured on the PMS. Typically (`32400`). \nIf using a reverse proxy, this would be the port number configured on the proxy.\n" default: '32400' - url: "{full_server_url}" variables: full_server_url: - description: The full manual URL to access the PMS default: http://localhost:32400 security: - token: @@ -157,6 +150,12 @@ tags: description: | This describes the API for searching and applying updates to the Plex Media Server. Updates to the status can be observed via the Event API. + - name: Authentication + description: Authentication-related endpoints. + - name: Plex + description: General Plex endpoints. + - name: Users + description: User account endpoints. x-tagGroups: - name: General tags: @@ -507,7 +506,7 @@ paths: in: query schema: type: string - example: 123 + example: "123" - name: time description: The current time offset of playback in ms. in: query @@ -1374,7 +1373,7 @@ paths: in: query schema: type: string - format: url + format: uri example: file:///storage%2Femulated%2F0%2FArcher-S01E01.mkv - name: virtualFilePath description: A virtual path to use when the url is opaque. @@ -1931,7 +1930,7 @@ paths: type: array items: type: string - example: device[]=device://tv.plex.grabbers.hdhomerun/1053C0CA + example: ["device[]=device://tv.plex.grabbers.hdhomerun/1053C0CA"] - name: language description: The language. in: query @@ -3751,7 +3750,7 @@ paths: type: array items: type: string - example: viewedAt:desc,accountID + example: ["viewedAt:desc,accountID"] responses: '200': description: OK @@ -4156,7 +4155,7 @@ paths: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 - name: protocol description: | @@ -4196,7 +4195,7 @@ paths: - embedded - segmented - unknown - example: Burn + example: burn - name: videoBitrate description: Target video bitrate (in kbps). in: query @@ -4217,7 +4216,7 @@ paths: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 - name: X-Plex-Client-Identifier description: Unique per client. @@ -4260,7 +4259,7 @@ paths: in: header schema: type: string - example: 135 + example: "135" - name: X-Plex-Session-Identifier description: Unique per client playback session. Used if a client can playback multiple items at a time (such as a browser with multiple tabs) in: header @@ -4447,7 +4446,7 @@ paths: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 - name: protocol description: | @@ -4487,7 +4486,7 @@ paths: - embedded - segmented - unknown - example: Burn + example: burn - name: videoBitrate description: Target video bitrate (in kbps). in: query @@ -4508,7 +4507,7 @@ paths: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 - name: X-Plex-Client-Identifier description: Unique per client. @@ -4551,7 +4550,7 @@ paths: in: header schema: type: string - example: 135 + example: "135" - name: X-Plex-Session-Identifier description: Unique per client playback session. Used if a client can playback multiple items at a time (such as a browser with multiple tabs) in: header @@ -4694,7 +4693,7 @@ paths: default: false verificationCode: type: string - example: 123456 + example: "123456" description: Login credentials responses: '201': @@ -9776,7 +9775,7 @@ paths: type: array items: type: string - example: 46.1,44.1,45.1 + example: ["46.1", "44.1", "45.1"] responses: '200': description: OK @@ -10989,7 +10988,7 @@ paths: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 - name: protocol description: | @@ -11029,7 +11028,7 @@ paths: - embedded - segmented - unknown - example: Burn + example: burn - name: videoBitrate description: Target video bitrate (in kbps). in: query @@ -11050,7 +11049,7 @@ paths: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 - name: X-Plex-Client-Identifier description: Unique per client. @@ -11093,7 +11092,7 @@ paths: in: header schema: type: string - example: 135 + example: "135" - name: X-Plex-Session-Identifier description: Unique per client playback session. Used if a client can playback multiple items at a time (such as a browser with multiple tabs) in: header @@ -12935,7 +12934,7 @@ paths: uri: library://82503060-0d68-4603-b594-8b071d54819e/item/%2Flibrary%2Fmetadata%2F146 locationID: -1 Policy: - value: '' + value: 0 scope: all unwatched: 0 target: '' @@ -13743,7 +13742,7 @@ components: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 protocol: name: protocol @@ -13785,7 +13784,7 @@ components: - embedded - segmented - unknown - example: Burn + example: burn subtitleSize: name: subtitleSize description: Percentage of original subtitle size to use when burning subtitles (100 is equivalent to original size, 50 is half, ect) @@ -13861,7 +13860,7 @@ components: in: query schema: type: string - pattern: ^\d[x:]\d$ + pattern: ^\d+[x:]\d+$ example: 1080x1080 X-Plex-Client-Identifier: name: X-Plex-Client-Identifier @@ -15350,16 +15349,7 @@ components: description: | The unique identifier for the Guid. Can be prefixed with imdb://, tmdb://, tvdb:// pattern: "^(imdb|tmdb|tvdb)://.+$" - example: - imdbExample: - summary: IMDB example - value: imdb://tt13015952 - tmdbExample: - summary: TMDB example - value: tmdb://2434012 - tvdbExample: - summary: TVDB example - value: tvdb://7945991 + example: imdb://tt13015952 hero: description: When present, the URL for a hero image for the item. type: string @@ -16371,7 +16361,7 @@ components: description: List of devices your allowed to use with this account items: type: string - example: '[]' + example: [] guest: type: boolean description: If the account is a Plex Home guest user @@ -16803,7 +16793,6 @@ components: type: - string - 'null' - example: null PlexDateTime: type: - integer @@ -16858,7 +16847,6 @@ components: - 'null' items: type: string - example: null defaultSubtitleLanguage: description: The preferred subtitle language for the account type: @@ -16872,7 +16860,6 @@ components: - 'null' items: type: string - example: null autoSelectSubtitle: allOf: - type: integer @@ -16963,7 +16950,6 @@ components: - 'null' items: type: string - example: null MediaQuery: description: | A querystring-based filtering language used to select subsets of media. When provided as an object, properties are serialized as a querystring using form style with explode. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 000000000..1d4b3cec0 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2272 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@apidevtools/swagger-parser': + specifier: ^12.1.0 + version: 12.1.0(openapi-types@12.1.3) + '@stoplight/spectral-cli': + specifier: ^6.14.5 + version: 6.16.0 + prettier: + specifier: ^3.5.3 + version: 3.8.4 + +packages: + + '@apidevtools/json-schema-ref-parser@14.0.1': + resolution: {integrity: sha512-Oc96zvmxx1fqoSEdUmfmvvb59/KDOnUoJ7s2t7bISyAn0XEz57LCCw8k2Y4Pf3mwKaZLMciESALORLgfe2frCw==} + engines: {node: '>= 16'} + + '@apidevtools/openapi-schemas@2.1.0': + resolution: {integrity: sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==} + engines: {node: '>=10'} + + '@apidevtools/swagger-methods@3.0.2': + resolution: {integrity: sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==} + + '@apidevtools/swagger-parser@12.1.0': + resolution: {integrity: sha512-e5mJoswsnAX0jG+J09xHFYQXb/bUc5S3pLpMxUuRUA2H8T2kni3yEoyz2R3Dltw5f4A6j6rPNMpWTK+iVDFlng==} + peerDependencies: + openapi-types: '>=7' + + '@asyncapi/specs@6.11.1': + resolution: {integrity: sha512-A3WBLqAKGoJ2+6FWFtpjBlCQ1oFCcs4GxF7zsIGvNqp/klGUHjlA3aAcZ9XMMpLGE8zPeYDz2x9FmO6DSuKraQ==} + + '@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 + + '@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'} + + '@rollup/plugin-commonjs@22.0.2': + resolution: {integrity: sha512-//NdP6iIwPbMTcazYsiBMbJW7gfmpHom33u1beiIoHDEM0Q9clvtQB1T0efvMqHeKsGohiHo97BCPCkBXdscwg==} + engines: {node: '>= 12.0.0'} + peerDependencies: + rollup: ^2.68.0 + + '@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 + + '@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.0': + resolution: {integrity: sha512-P1acHIV/hDiO3w0YNUc3pD7/0q68SMAMyWVxAPUGzsAeq50lLpl0obN5j3QITMgJPhPByvBIjBV4ftkBd8nwMg==} + engines: {node: ^16.20 || ^18.18 || >= 20.17} + hasBin: true + + '@stoplight/spectral-core@1.23.0': + resolution: {integrity: sha512-WvdgmiiJrjiMrcw7ByxfcYtUvAXNp2MhAfcEIXP3Mn8ZOVwyAWIsFjLlsE5zRqj0LuN8+7OQM/L+BMcHj6x/BQ==} + engines: {node: ^16.20 || ^18.18 || >= 20.17} + + '@stoplight/spectral-formats@1.8.3': + resolution: {integrity: sha512-lfYzkHYS2mZQdm3k+TQ0lvXZ66vdBzJuy6awA4kXgQ0jWBbOC/FHzhBk5BaIVo2QRLUAGjMqWSd72WFryi+EvA==} + 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.3': + resolution: {integrity: sha512-AM7Gbh7pv1Mpc6fdVuR7N6C5t5KT3QKDHeBPA27Cw/GAch1VJnHkCV9R/SxDrvOgZ3tL1xrtAGFuNFwRvVdz3g==} + 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.1': + resolution: {integrity: sha512-IUEbDmmTro0oF6VoAtrUySRV/b6bvYmV7wV6lB99f0Ym5lF9M2DXcgPLo7VMbKTPjCOQcaBzWRnIMXAyLjIRMA==} + engines: {node: ^16.20 || ^18.18 || >= 20.17} + + '@stoplight/spectral-rulesets@1.22.4': + resolution: {integrity: sha512-Lwr4DVg8aEqiBcm2CMQAP1FIBmLP9Y8Z2st7jvbxzv3fXmThdafVMy6CrydWH46T4Wotm+UuBJFnqJd9H4RQZQ==} + engines: {node: ^16.20 || ^18.18 || >= 20.17} + + '@stoplight/spectral-runtime@1.1.5': + resolution: {integrity: sha512-6/HSCQBKnI4M5qonCKos2W7oggXv+U/ml+m/cAd4eJAYfIVEmaLUo03qSWIIl4cBc5ujJPmn2WnCiRrz1++P7Q==} + 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'} + + '@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@25.9.3': + resolution: {integrity: sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==} + + '@types/sarif@2.1.7': + resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} + + '@types/urijs@1.19.26': + resolution: {integrity: sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + 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==} + + 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'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + 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'} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + brace-expansion@1.1.15: + resolution: {integrity: sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + builtins@1.0.3: + resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.9: + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + call-me-maybe@1.0.2: + resolution: {integrity: sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + 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'} + + 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==} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + 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'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + dependency-graph@0.11.0: + resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} + engines: {node: '>= 0.6.0'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + es-abstract@1.24.2: + 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'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.2: + resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + 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==} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + 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-memoize@2.5.2: + resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} + + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + 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'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + 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} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.2.0: + resolution: {integrity: sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + 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'} + + get-proto@1.0.1: + 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@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'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-bigints@1.1.0: + 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==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.4: + 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'} + + immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + + 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'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.2: + resolution: {integrity: sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-document.all@1.0.0: + resolution: {integrity: sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + 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'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.1.1: + 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-reference@1.2.1: + resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + js-yaml@4.2.0: + resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} + hasBin: true + + jsep@1.4.0: + resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} + engines: {node: '>= 10.16.0'} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + 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'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + 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==} + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + 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@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + nimma@0.2.3: + resolution: {integrity: sha512-1ZOI8J+1PKKGceo/5CT5GfQOG6H8I2BencSK06YarZ2wXwH37BSSUWldqJmMJYA5JfqDqffxDXynt6f11AyKcA==} + engines: {node: ^12.20 || >=14.13} + + 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-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'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + 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'} + + prettier@3.8.4: + resolution: {integrity: sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==} + engines: {node: '>=14'} + hasBin: true + + printable-characters@1.0.42: + resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + 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'} + + rollup@2.80.0: + resolution: {integrity: sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.4: + resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} + engines: {node: '>=0.4'} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safe-stable-stringify@1.1.1: + resolution: {integrity: sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + side-channel-list@1.0.1: + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.1: + resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} + engines: {node: '>= 0.4'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + 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.trim@1.2.11: + resolution: {integrity: sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.10: + resolution: {integrity: sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + 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'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + 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==} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.8: + resolution: {integrity: sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==} + engines: {node: '>= 0.4'} + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.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==} + + 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'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.22: + resolution: {integrity: sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==} + engines: {node: '>= 0.4'} + + 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'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + +snapshots: + + '@apidevtools/json-schema-ref-parser@14.0.1': + dependencies: + '@types/json-schema': 7.0.15 + js-yaml: 4.2.0 + + '@apidevtools/openapi-schemas@2.1.0': {} + + '@apidevtools/swagger-methods@3.0.2': {} + + '@apidevtools/swagger-parser@12.1.0(openapi-types@12.1.3)': + dependencies: + '@apidevtools/json-schema-ref-parser': 14.0.1 + '@apidevtools/openapi-schemas': 2.1.0 + '@apidevtools/swagger-methods': 3.0.2 + ajv: 8.20.0 + ajv-draft-04: 1.0.0(ajv@8.20.0) + call-me-maybe: 1.0.2 + openapi-types: 12.1.3 + + '@asyncapi/specs@6.11.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@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 + + '@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.1 + + '@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/pluginutils@3.1.0(rollup@2.80.0)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.2 + rollup: 2.80.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.0': + dependencies: + '@stoplight/json': 3.21.7 + '@stoplight/path': 1.3.2 + '@stoplight/spectral-core': 1.23.0 + '@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.1 + '@stoplight/spectral-rulesets': 1.22.4 + '@stoplight/spectral-runtime': 1.1.5 + '@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.2 + transitivePeerDependencies: + - encoding + + '@stoplight/spectral-core@1.23.0': + dependencies: + '@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.5 + '@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.3': + dependencies: + '@stoplight/json': 3.21.7 + '@stoplight/spectral-core': 1.23.0 + '@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.0 + '@stoplight/spectral-runtime': 1.1.5 + '@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.3': + dependencies: + '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0) + '@stoplight/json': 3.21.7 + '@stoplight/spectral-core': 1.23.0 + '@stoplight/spectral-formats': 1.8.3 + '@stoplight/spectral-runtime': 1.1.5 + 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.5 + 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.0 + '@stoplight/spectral-formats': 1.8.3 + '@stoplight/spectral-functions': 1.10.3 + '@stoplight/spectral-parsers': 1.0.5 + '@stoplight/spectral-ref-resolver': 1.0.5 + '@stoplight/spectral-ruleset-migrator': 1.12.1 + '@stoplight/spectral-rulesets': 1.22.4 + '@stoplight/spectral-runtime': 1.1.5 + '@stoplight/types': 13.20.0 + '@types/node': 25.9.3 + 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.1': + dependencies: + '@stoplight/json': 3.21.7 + '@stoplight/ordered-object-literal': 1.0.5 + '@stoplight/path': 1.3.2 + '@stoplight/spectral-functions': 1.10.3 + '@stoplight/spectral-runtime': 1.1.5 + '@stoplight/types': 13.20.0 + '@stoplight/yaml': 4.2.3 + '@types/node': 25.9.3 + 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.4': + dependencies: + '@asyncapi/specs': 6.11.1 + '@stoplight/better-ajv-errors': 1.0.3(ajv@8.20.0) + '@stoplight/json': 3.21.7 + '@stoplight/spectral-core': 1.23.0 + '@stoplight/spectral-formats': 1.8.3 + '@stoplight/spectral-functions': 1.10.3 + '@stoplight/spectral-runtime': 1.1.5 + '@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.5': + dependencies: + '@stoplight/json': 3.21.7 + '@stoplight/path': 1.3.2 + '@stoplight/types': 13.20.0 + abort-controller: 3.0.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 + + '@types/es-aggregate-error@1.0.6': + dependencies: + '@types/node': 25.9.3 + + '@types/estree@0.0.39': {} + + '@types/estree@1.0.9': {} + + '@types/json-schema@7.0.15': {} + + '@types/markdown-escape@1.1.3': {} + + '@types/node@25.9.3': + dependencies: + undici-types: 7.24.6 + + '@types/sarif@2.1.7': {} + + '@types/urijs@1.19.26': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + 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 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + argparse@2.0.1: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + 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: {} + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + balanced-match@1.0.2: {} + + brace-expansion@1.1.15: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + builtins@1.0.3: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + call-me-maybe@1.0.2: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + 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 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + commondir@1.0.1: {} + + concat-map@0.0.1: {} + + data-uri-to-buffer@2.0.2: {} + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + dependency-graph@0.11.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + emoji-regex@8.0.0: {} + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.2.0 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.4 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.11 + string.prototype.trimend: 1.0.10 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.8 + 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: {} + + es-object-atoms@1.1.2: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + escalade@3.2.0: {} + + estree-walker@1.0.1: {} + + estree-walker@2.0.2: {} + + event-target-shim@5.0.1: {} + + 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-memoize@2.5.2: {} + + fast-uri@3.1.2: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.1 + universalify: 2.0.1 + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.2.0: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + es-define-property: 1.0.1 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + hasown: 2.0.4 + is-callable: 1.2.7 + is-document.all: 1.0.0 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.4 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + 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@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 + gopd: 1.2.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.4: + dependencies: + function-bind: 1.1.2 + + hpagent@1.2.0: {} + + immer@9.0.21: {} + + 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 + hasown: 2.0.4 + side-channel: 1.1.1 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.2: + dependencies: + hasown: 2.0.4 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-document.all@1.0.0: + dependencies: + call-bound: 1.0.4 + + 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 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-negative-zero@2.0.3: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-reference@1.2.1: + dependencies: + '@types/estree': 1.0.9 + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.4 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.22 + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + isarray@2.0.5: {} + + js-yaml@4.2.0: + dependencies: + argparse: 2.0.1 + + jsep@1.4.0: {} + + json-schema-traverse@1.0.0: {} + + 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: {} + + lodash.topath@4.5.2: {} + + lodash@4.18.1: {} + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + markdown-escape@2.0.0: {} + + math-intrinsics@1.1.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.15 + + 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-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + 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: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + openapi-types@12.1.3: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + path-is-absolute@1.0.1: {} + + path-parse@1.0.7: {} + + picomatch@2.3.2: {} + + pony-cause@1.1.1: {} + + possible-typed-array-names@1.1.0: {} + + prettier@3.8.4: {} + + printable-characters@1.0.42: {} + + queue-microtask@1.2.3: {} + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + 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 + is-core-module: 2.16.2 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + rollup@2.80.0: + optionalDependencies: + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.4: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safe-stable-stringify@1.1.1: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.2 + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + source-map@0.6.1: {} + + 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.trim@1.2.11: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.2 + has-property-descriptors: 1.0.2 + safe-regex-test: 1.1.0 + + string.prototype.trimend@1.0.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.2 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + text-table@0.2.0: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tr46@0.0.3: {} + + tslib@1.14.1: {} + + tslib@2.8.1: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.8: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + undici-types@7.24.6: {} + + universalify@2.0.1: {} + + urijs@1.19.11: {} + + utility-types@3.11.0: {} + + validate-npm-package-name@3.0.0: + dependencies: + builtins: 1.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 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.2.0 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.22 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.22: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + 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: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + 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 diff --git a/scripts/generate-reference.mjs b/scripts/generate-reference.mjs new file mode 100644 index 000000000..cc23503f1 --- /dev/null +++ b/scripts/generate-reference.mjs @@ -0,0 +1,58 @@ +#!/usr/bin/env node +import SwaggerParser from '@apidevtools/swagger-parser'; +import { writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const SCHEMA_PATH = process.argv[2] ? resolve(process.cwd(), process.argv[2]) : resolve(process.cwd(), 'plex-api-spec.yaml'); +const OUTPUT_PATH = resolve(process.cwd(), 'docs/endpoints.md'); + +function escapeTableCell(text) { + return String(text).replace(/\|/g, '\\|').replace(/\n/g, '
'); +} + +async function main() { + const api = await SwaggerParser.parse(SCHEMA_PATH); + + const lines = []; + lines.push('---'); + lines.push('title: API Endpoints'); + lines.push('---'); + lines.push(''); + lines.push('# API Endpoints'); + lines.push(''); + lines.push('This page is generated from [`plex-api-spec.yaml`](./plex-api-spec.yaml).'); + lines.push('Do not edit it by hand; run `pnpm run spec:generate-reference` to regenerate it.'); + lines.push(''); + lines.push('## Overview'); + lines.push(''); + lines.push(`| Method | Path | Summary | Operation ID |`); + lines.push(`| ------ | ---- | ------- | ------------ |`); + + const paths = Object.entries(api.paths || {}).sort(([a], [b]) => a.localeCompare(b)); + for (const [path, methods] of paths) { + for (const [method, operation] of Object.entries(methods)) { + if (typeof operation !== 'object' || !operation.summary) continue; + lines.push( + `| ${method.toUpperCase()} | \`${escapeTableCell(path)}\` | ${escapeTableCell(operation.summary)} | \`${escapeTableCell(operation.operationId || '')}\` |` + ); + } + } + + lines.push(''); + lines.push('## Authentication'); + lines.push(''); + lines.push('Most endpoints require an `X-Plex-Token` header or `X-Plex-Token` query parameter.'); + lines.push(''); + lines.push('## Response format'); + lines.push(''); + lines.push('Responses default to XML. Request JSON by sending `Accept: application/json`.'); + lines.push(''); + + writeFileSync(OUTPUT_PATH, lines.join('\n'), 'utf-8'); + console.log(`✅ Generated ${OUTPUT_PATH}`); +} + +main().catch((err) => { + console.error('❌ Reference generation failed:', err.message); + process.exit(1); +}); diff --git a/scripts/openapi-diff.mjs b/scripts/openapi-diff.mjs new file mode 100644 index 000000000..4787b3fbc --- /dev/null +++ b/scripts/openapi-diff.mjs @@ -0,0 +1,137 @@ +#!/usr/bin/env node +import SwaggerParser from "@apidevtools/swagger-parser"; +import { execSync } from "node:child_process"; +import { mkdtempSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +const SPEC_PATH = resolve(process.cwd(), "plex-api-spec.yaml"); +const BASE_REF = process.argv[2] || "origin/main"; + +function getBaseSpec(ref) { + try { + return execSync(`git show ${ref}:plex-api-spec.yaml`, { + encoding: "utf-8", + stdio: ["pipe", "pipe", "pipe"], + }); + } catch (err) { + const stderr = String(err.stderr || err); + if ( + stderr.includes("Path 'plex-api-spec.yaml' does not exist") || + stderr.includes("Invalid object name") + ) { + console.log("ℹ️ No baseline spec found in git history; skipping breaking-change check."); + process.exit(0); + } + throw err; + } +} + +function getMethods(pathItem) { + const methods = new Set(); + for (const [method, op] of Object.entries(pathItem || {})) { + if (typeof op === "object" && op !== null && op.operationId) { + methods.add(method.toLowerCase()); + } + } + return methods; +} + +function normalizeParam(param) { + return `${param.in}:${param.name}`; +} + +async function diffSpecs(basePath, headPath) { + const base = await SwaggerParser.parse(basePath); + const head = await SwaggerParser.parse(headPath); + + const basePaths = Object.keys(base.paths || {}); + const headPaths = Object.keys(head.paths || {}); + + const breaking = []; + const nonBreaking = []; + + // Removed paths are breaking + for (const path of basePaths) { + if (!headPaths.includes(path)) { + breaking.push(`Removed path: ${path}`); + continue; + } + + const baseMethods = getMethods(base.paths[path]); + const headMethods = getMethods(head.paths[path]); + + for (const method of baseMethods) { + if (!headMethods.has(method)) { + breaking.push(`Removed operation: ${method.toUpperCase()} ${path}`); + } + } + + // Added methods are non-breaking + for (const method of headMethods) { + if (!baseMethods.has(method)) { + nonBreaking.push(`Added operation: ${method.toUpperCase()} ${path}`); + } + } + + // Added required parameters are breaking + const baseParams = new Map( + (base.paths[path].parameters || []) + .filter((p) => p.required) + .map((p) => [normalizeParam(p), p]), + ); + const headParams = new Map( + (head.paths[path].parameters || []) + .filter((p) => p.required) + .map((p) => [normalizeParam(p), p]), + ); + for (const [key, param] of headParams) { + if (!baseParams.has(key)) { + breaking.push(`Added required parameter: ${key} on ${path}`); + } + } + } + + // Added paths are non-breaking + for (const path of headPaths) { + if (!basePaths.includes(path)) { + nonBreaking.push(`Added path: ${path}`); + } + } + + return { breaking, nonBreaking }; +} + +async function main() { + const baseSpec = getBaseSpec(BASE_REF); + const tmpDir = mkdtempSync(join(tmpdir(), "openapi-diff-")); + const basePath = join(tmpDir, "base.openapi.yaml"); + writeFileSync(basePath, baseSpec, "utf-8"); + + const { breaking, nonBreaking } = await diffSpecs(basePath, SPEC_PATH); + + console.log(`Breaking changes: ${breaking.length}`); + for (const item of breaking) { + console.log(` - ${item}`); + } + + console.log(`Non-breaking changes: ${nonBreaking.length}`); + for (const item of nonBreaking.slice(0, 10)) { + console.log(` - ${item}`); + } + if (nonBreaking.length > 10) { + console.log(` ... and ${nonBreaking.length - 10} more`); + } + + if (breaking.length > 0) { + console.error("❌ Breaking changes detected in OpenAPI spec."); + process.exit(1); + } + + console.log("✅ No breaking changes detected."); +} + +main().catch((err) => { + console.error("❌ OpenAPI diff failed:", err.message); + process.exit(1); +}); diff --git a/scripts/validate-spec.mjs b/scripts/validate-spec.mjs new file mode 100644 index 000000000..1ed4336da --- /dev/null +++ b/scripts/validate-spec.mjs @@ -0,0 +1,35 @@ +#!/usr/bin/env node +import SwaggerParser from '@apidevtools/swagger-parser'; +import { existsSync } from 'node:fs'; +import { resolve } from 'node:path'; + +function findSpecPath() { + const cwd = process.cwd(); + const candidates = [ + resolve(cwd, 'plex-api-spec.yaml'), + resolve(cwd, 'spec/plex-api-spec.yaml'), + ]; + for (const candidate of candidates) { + if (existsSync(candidate)) return candidate; + } + return candidates[0]; +} + +const SCHEMA_PATH = process.argv[2] ? resolve(process.cwd(), process.argv[2]) : findSpecPath(); + +async function main() { + console.log(`Validating ${SCHEMA_PATH}...`); + + await SwaggerParser.validate(SCHEMA_PATH); + console.log('✅ OpenAPI schema is valid.'); + + const api = await SwaggerParser.parse(SCHEMA_PATH); + const pathCount = Object.keys(api.paths || {}).length; + const schemaCount = Object.keys(api.components?.schemas || {}).length; + console.log(`Paths: ${pathCount}, Schemas: ${schemaCount}`); +} + +main().catch((err) => { + console.error('❌ Schema validation failed:', err.message); + process.exit(1); +});