diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..b2e9f24e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Ask on Discord + url: https://discord.gg/qjZE9C9fkB + about: Questions about using the API or one of the libraries. + - name: Report a bug in one library + url: https://github.com/orgs/vrchatapi/repositories + about: Every library is generated from this specification, so a response one of them can't parse belongs here. A bug in a library's own code belongs in its repository. diff --git a/.github/ISSUE_TEMPLATE/missing-from-specification.yml b/.github/ISSUE_TEMPLATE/missing-from-specification.yml new file mode 100644 index 00000000..535b3895 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/missing-from-specification.yml @@ -0,0 +1,31 @@ +name: Missing from the specification +description: An endpoint, parameter or field VRChat supports that the specification doesn't describe. +labels: + - "Type: Enhancement" +body: + - type: input + id: request + attributes: + label: Request + description: The method and path. + placeholder: GET /instanceCategories + validations: + required: true + - type: textarea + id: missing + attributes: + label: What's missing + description: The endpoint, parameter or field, and what it does. + validations: + required: true + - type: textarea + id: capture + attributes: + label: Request and response + description: A request you sent and the response VRChat returned. Redact anything personal, but keep each value's type. + render: text + - type: textarea + id: source + attributes: + label: Where it comes from + description: Where you saw it, such as the VRChat client, the website or a Developer Update. Link it if you can. diff --git a/.github/ISSUE_TEMPLATE/response-mismatch.yml b/.github/ISSUE_TEMPLATE/response-mismatch.yml new file mode 100644 index 00000000..b6621e93 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/response-mismatch.yml @@ -0,0 +1,35 @@ +name: Response doesn't match +description: A library fails to parse a response, or VRChat returns a field, type or value the specification doesn't describe. +labels: + - "Type: Bug" +body: + - type: markdown + attributes: + value: A library's error names the field but not the value that broke it. The raw response is what lets us fix it. + - type: input + id: operation + attributes: + label: Operation + description: The operation id or the request. + placeholder: getModerationReports, or GET /moderationReports + validations: + required: true + - type: textarea + id: response + attributes: + label: Response body + description: The JSON VRChat returned, or the object within it that failed. Redact anything personal, but keep each value's type. Replace a string with another string, and leave `null` as `null`. + render: json + validations: + required: true + - type: textarea + id: error + attributes: + label: Error + description: The error your library raised, if any. + render: text + - type: input + id: library + attributes: + label: Library and version + placeholder: vrchatapi-csharp 1.21.0 diff --git a/.github/ISSUE_TEMPLATE/something-else.yml b/.github/ISSUE_TEMPLATE/something-else.yml new file mode 100644 index 00000000..073f1204 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/something-else.yml @@ -0,0 +1,9 @@ +name: Something else +description: A wrong description, a problem with the published bundles, or anything neither form above covers. +body: + - type: textarea + id: description + attributes: + label: What's wrong + validations: + required: true diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..8178b57f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,9 @@ +Closes # + +## Evidence + + + +- [ ] Every property, type and example comes from a captured response +- [ ] `pnpm lint` passes +- [ ] `pnpm test -w session -w ` passes diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0f4e8dda..6e723eea 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -2,11 +2,17 @@ on: push: branches: - main + - stable pull_request: schedule: - cron: "17 7 * * *" workflow_dispatch: +concurrency: + group: ${{ github.event_name == 'push' && format('{0}-{1}', github.workflow, github.ref) || github.run_id }} + cancel-in-progress: false + queue: max + env: GH_TOKEN: ${{ github.token }} @@ -24,9 +30,9 @@ jobs: runtime: bun@latest cache: true - - if: github.event_name == 'push' + - if: github.event_name == 'push' && github.event.before != '0000000000000000000000000000000000000000' run: | - changes=$(git diff --name-only --diff-filter=d "${{ github.event.commits[0].id }}~1" "${{ github.event.commits[0].id }}") + changes=$(git diff --name-only --diff-filter=d "${{ github.event.before }}" "${{ github.sha }}") { echo 'changes< /dev/null; then + echo "::error::$declared is not a version" + exit 1 + elif git rev-parse --quiet --verify "refs/tags/v$declared" > /dev/null; then + release=false + elif [ -n "$latest" ] && pnpm -s semver --range "<$latest" "$declared" > /dev/null; then + echo "::error::$declared is below the latest release, $latest" + exit 1 + fi + else + base=$(pnpm -s semver --increment patch "${latest:-$declared}") + highest=$(git tag --list "v$base-nightly.*" | sed "s/^v$base-nightly\.//" | grep -xE '[0-9]+' | sort -n | tail -n 1 || true) + version="$base-nightly.$(( ${highest:-0} + 1 ))" + fi + + echo "version=$version" >> "$GITHUB_ENV" + echo "release=$release" >> "$GITHUB_OUTPUT" + - run: bun --bun run bundle + - name: lint the downleveled bundles as the version they declare + run: bun --bun run test:versions + - uses: actions/github-script@v9 with: script: | @@ -132,19 +177,14 @@ jobs: needs: - lint - bundle - if: ${{ !failure() && !cancelled() && github.event_name != 'schedule' && github.ref == 'refs/heads/main' }} + if: ${{ !failure() && !cancelled() && github.event_name != 'schedule' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/stable') && needs.bundle.outputs.release == 'true' && !contains(github.event.head_commit.message, '[no release]') }} + concurrency: + group: release outputs: version: ${{ steps.metadata.outputs.version }} steps: - uses: actions/checkout@v7 - with: - fetch-depth: 0 - - - uses: pnpm/setup@v2 - with: - runtime: bun@latest - cache: true - uses: actions/download-artifact@v8 with: @@ -156,17 +196,10 @@ jobs: run: | version=$(jq -r '.info.version' dist/openapi.json) - version_sha=$( - git rev-list -n 1 "v$version" 2>/dev/null \ - || git rev-list -n 1 "release/$version" 2>/dev/null \ - || echo "" - ) - - if [ "$version_sha" == "" ]; then - echo "prerelease=false" >> $GITHUB_ENV - else + if [[ "$version" == *-nightly.* ]]; then echo "prerelease=true" >> $GITHUB_ENV - version=$(pnpm semver $version -i)-nightly.$(git rev-list --count "$version_sha"..HEAD) + else + echo "prerelease=false" >> $GITHUB_ENV fi echo "version=$version" >> $GITHUB_ENV @@ -179,13 +212,16 @@ jobs: - name: create release (nightly) if: env.prerelease == 'true' run: | - jq --arg v "${{ env.version }}" '.info.version = $v' dist/openapi.json > dist/.openapi.json && mv dist/.openapi.json dist/openapi.json - yq eval ".info.version = \"${{ env.version }}\"" -i dist/openapi.yaml - gh release create v${{ env.version }} dist/* \ --generate-notes \ --prerelease + - name: refresh the nightly release + if: github.ref == 'refs/heads/main' + run: | + gh release upload nightly dist/* --clobber + gh release edit nightly --notes "The latest build from main, currently v${{ env.version }}. Its files are replaced whenever a new build is published." + release_dispatch: uses: ./.github/workflows/release_dispatch.yaml needs: release @@ -194,7 +230,7 @@ jobs: version: ${{ needs.release.outputs.version }} test: - if: github.event_name != 'pull_request' + if: github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[no test]') runs-on: ubuntu-latest concurrency: group: test @@ -215,6 +251,32 @@ jobs: VRCHAT_PASSWORD: ${{ secrets.VRCHAT_PASSWORD }} VRCHAT_TOTP_SECRET: ${{ secrets.VRCHAT_TOTP_SECRET }} VRCHAT_FRIEND_ID: ${{ secrets.VRCHAT_FRIEND_ID }} + VRCHAT_GROUP_ID: ${{ secrets.VRCHAT_GROUP_ID }} + + - if: "!cancelled()" + uses: actions/upload-artifact@v7 + with: + name: respect-report + path: test/.out/respect.json + retention-days: 1 - if: "!cancelled()" - run: pnpm test:drift >> "$GITHUB_STEP_SUMMARY" + timeout-minutes: 2 + run: sh test/report.sh --format github + + - if: "!cancelled()" + timeout-minutes: 2 + run: sh test/report.sh >> "$GITHUB_STEP_SUMMARY" + + - if: "!cancelled()" + timeout-minutes: 5 + run: | + status=0 + pnpm -s test:drift --max-findings 1000 --output test/.out/drift.txt || status=$? + cat test/.out/drift.txt + { + printf '### Drift\n\n```\n' + cat test/.out/drift.txt + printf '```\n' + } >> "$GITHUB_STEP_SUMMARY" + exit $status diff --git a/CLAUDE.md b/CLAUDE.md index 8994bd7c..491b4782 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -126,11 +126,44 @@ characters in validation messages — `˸` (U+02F8) for a colon, `‚` (U+201A) comma, `․` (U+2024) for a full stop — and a retyped example normalises them, which is how you can tell nobody captured it. -## Deprecation - -Mark `deprecated: true` only where every observed call answers the generic -"not implemented" 404. Keep the original tag and add `deprecated`, so the suite -keeps calling the route and a revival shows up. +## Deprecation and deletion + +Mark `x-deleted: ` only where every observed call answers the generic +"not implemented" 404. Keep the operation and its tag: the published bundles +drop it, the `test` bundle keeps it, so the suite goes on calling the route and +a revival shows up as a failing `not-found` workflow. + +The date is the day the route started answering that 404, which the suite now +records the morning it happens. For a route that died before the suite existed, +`vrchatapi/specification-test` commits one response file per operation daily +back to 2023, so `git log -S '\`404 Not Found\`'` over the file dates it. Where +neither covers the route, fall back to the day it was marked and say no more +than that. Never date one from `vrchatapi/monitor`: a path outlives its endpoint +in the client bundle, and `/economy/seller/eligibility` sat there months after +it stopped answering. + +Mark `deprecated: true` where the route still answers but VRChat has replaced +it or the client no longer uses it. Keep the original tag and add `deprecated`. + +An operation id is a public URL. `vrchat.community/reference/` +is what the changelogs, the release notes and every link anyone has saved point +at, and generated clients take their method names from the same string. Renaming +or deleting one breaks all of that, so open a matching PR on +`vrchatapi/vrchat.community` adding a redirect from the old id before the rename +lands, and fix the links in any release notes that named it. + +## One object, one file + +Every object schema lives in its own file under `openapi/components/schemas` and +is reached by `$ref`. An object written inline inside another schema has no name, +so each generated client invents its own, and a second schema that needs the same +shape has to restate it. + +`vrchat/no-nested-object` is what catches this. A schema in its own file carries a +title taken from that file, so an object without one is still nested somewhere; +the rule reports each one once, against the file it is written in. Pull the +object out rather than adding a `title` in place, which would silence the rule +without moving anything. ## Comments @@ -143,13 +176,17 @@ Never add a YAML comment. A fact about the API belongs in a `description`. decorator changes `drift` only, and does not reach the schema check. - `respect` masks secrets in the capture and sends the real value. `********` in a HAR is evidence about nothing. -- `dist/openapi-test.yaml` defines `jsonschema` and `internal`, so `x-if` takes - its `then` branch. The published bundles take `else`. Both must describe the - same traffic; check which one you are validating against before believing a - finding. +- `openapi.json` and `openapi-internal.json` carry the source's OpenAPI version. + The `-3.x` bundles pass through `downlevel/openapi` from + `packages/redocly-plugin-downlevel`, which rewrites them as that version. + `dist/openapi-test.yaml` carries the source as written. Check which one you + are validating against before believing a finding. - `drift`'s `security-baseline` flags every unauthenticated workflow for the missing cookie it exists to assert. Every finding it produces is a 401 and - none is actionable. + none is actionable, so `test:drift` names the rules it wants instead of taking + the default set. It passes `--server` for the same reason: the local + `httpexec` the suite drives shares the capture, and `undocumented-endpoint` + reports all twelve of its exchanges against a description that never had them. - A `oneOf` that matches no branch reports every property in the body as unevaluated, so one missing property produces hundreds of findings naming innocent ones. Fix the branch that should have matched, never the properties @@ -166,19 +203,44 @@ Never add a YAML comment. A fact about the API belongs in a `description`. schema drift a fresh one reports. - A `-w` run writes `test/.out/partial.har` and leaves the suite capture alone. `coverage` and `drift` read the suite capture, so run them after a full run. -- Some files under `openapi/components/paths/` are CRLF. Read a diff of one with - `git diff --ignore-all-space` before believing its size. +- A response file may already serve another operation. Check with `grep -rn` + before rewriting one: overwriting `FavoriteGroupListResponse.yaml` for a new + route silently broke the three workflows `getFavoriteGroups` runs through it. +- One `schema check` message carries every failure the step found, separated by + code frames. Reading only the first hides the rest, so three undocumented + properties get found one suite run apart instead of together. +- Ajv reports `unevaluatedProperties` at the outermost object that fails and does + not descend, so fixing a property on a shelf can reveal others nested under it. + `drift` and the suite's schema check disagree on which they name. +- `jq`'s `gsub` over a multi-megabyte string takes minutes. A coloured code frame + in a check message reached 14MB. Filter lines by substring before any regex + touches them. ## Commands | | | | --- | --- | | `pnpm bundle` | build `dist/` | -| `pnpm lint` | spectral, eslint, arazzo | +| `pnpm lint` | redocly, eslint, arazzo | | `pnpm test` | drive the suite against the live API | | `pnpm test -w session -w ` | one workflow, plus the session it reads | | `pnpm test:coverage` | what the traffic never reached | | `pnpm test:drift` | where traffic and description disagree | +| `pnpm test:downlevel` | test and build `packages/redocly-plugin-downlevel` | +| `pnpm test:versions` | lint the downleveled bundles as the version they declare | +| `sh test/report.sh` | the last run's failures as Markdown | +| `sh test/report.sh --format github` | the same, as CI annotations | `pnpm test` reuses the cached session in `test/.out/`; delete `test/.out/session` to force a fresh login. + +`oasdiff` (`~/go/bin/oasdiff`) diffs a release bundle against `dist/`. Read +`docs/writing-changelogs.md` before writing release notes. + +## A second account settles what one cannot + +`presence` has a legacy shape and a current one, and which you get depends on the +account. `themes`, `worldFavoriteLists` and the frontend branches are empty on the +test account and populated elsewhere. When a field resists the suite, ask a user +for their `/auth/user` body and validate it against `dist/openapi-test.yaml`. +`docs/next.md` carries the snippet that collects one. diff --git a/cspell.config.yaml b/cspell.config.yaml new file mode 100644 index 00000000..7ea3660a --- /dev/null +++ b/cspell.config.yaml @@ -0,0 +1,101 @@ +$schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json +version: "0.2" + +language: en +languageId: markdown +enabledLanguageIds: + - markdown + +# What VRChat calls things: tags, enum values, path segments and the words the +# descriptions use for them. +words: + - adminassetbundles + - arrowpoint + - avatarmoderations + - beachball + - bitmask + - booped + - booping + - cantsee + - cooldown + - despawns + - drakeshoot + - emailotp + - emojianimated + - equippable + - favoritelimits + - favorited + - giftable + - homeworld + - interactable + - moderations + - noheadphones + - nomic + - noplatform + - notag + - playermoderation + - playermoderations + - recents + - spritesheet + - standalonewindows + - Tilia + - totp + - Tupper + - twofactorauth + - unban + - unbans + - unequip + - unequips + - uninvite + - unknownplatform + - unmoderate + - unmoderated + - unmoderates + - unmoderating + - unmute + - unplayermoderate + - urlencode + - userblocked + - VRC + - VRChat + - vrchatplus + - vrcplus + - webform + +# Values copied out of captured responses. Not vocabulary — they are there so a +# real example does not have to be retyped to satisfy the spell checker. +ignoreWords: + - 8JoV9XEdpo + - Arctor + - authco + - bulli + - eavhhng + - heldogs + - Kpjafh + - ouvckvouldn + - redi + - Tanabata + - uruseje + +suggestWords: + - "favourited: favorited" + +patterns: + - name: ids + pattern: /\w{1,4}_[\w-]{36}/g + - name: extensions + pattern: /\.\w+/g + # VRChat substitutes lookalike characters into validation messages, and the + # examples copy them verbatim. Each one joins itself to the word beside it, + # so `found․` reaches the checker as a single unknown word. + - name: lookalikes + pattern: /[ǃ˸‚․]/g + +ignoreRegExpList: + - ids + - extensions + - lookalikes + +ignoreRandomStrings: true +numSuggestions: 3 +validateDirectives: false diff --git a/eslint.config.mjs b/eslint.config.mjs index d62b0357..f036e3ba 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,9 +1,11 @@ import { configure } from "@ariesclark/eslint-config"; +import cspell from "@cspell/eslint-plugin"; export default configure({ type: "app", react: false, yaml: true, + ignores: ["packages/*/fixtures/**", "packages/*/dist/**"], rules: { "unicorn/prevent-abbreviations": "off", } @@ -14,14 +16,6 @@ export default configure({ rules: { "yaml/sort-keys": [ "error", - { - pathPattern: ".*x-if.*", - order: [ - "when", - "then", - "else" - ] - }, { pathPattern: ".*", hasProperties: [ @@ -112,8 +106,21 @@ export default configure({ ] } ], + "yaml/block-sequence": ["error", "always"], "yaml/sort-sequence-values": [ "error", + { + pathPattern: "(^|\\.)type$", + order: [ + { + valuePattern: "^(?!null$)", + order: { + type: "asc" + } + }, + "null" + ] + }, { pathPattern: "^(?!.*x-enum-varnames).*", order: [ @@ -131,4 +138,24 @@ export default configure({ rules: { "yaml/sort-keys": "off" } +}, { + files: ["openapi/**/*.yaml"], + plugins: { "@cspell": cspell }, + rules: { + "@cspell/spellchecker": [ + "warn", + { + configFile: new URL("./cspell.config.yaml", import.meta.url).toString(), + // `checkScope` matches a node type and the key it was reached by, so + // there is no way to check only the prose fields. Keys and sequence + // entries are off because a path segment and an enum value are the + // API's vocabulary rather than English; values carry the descriptions. + checkScope: [ + ["YAMLPair[key] YAMLScalar", false], + ["YAMLPair[value] YAMLScalar", true], + ["YAMLSequence[entries] YAMLScalar", false] + ] + } + ] + } }); diff --git a/openapi/.oxfmtrc.json b/openapi/.oxfmtrc.json new file mode 100644 index 00000000..e0863d47 --- /dev/null +++ b/openapi/.oxfmtrc.json @@ -0,0 +1,3 @@ +{ + "proseWrap": "never" +} diff --git a/openapi/agents.md b/openapi/agents.md new file mode 100644 index 00000000..d5f49ef5 --- /dev/null +++ b/openapi/agents.md @@ -0,0 +1,8 @@ +If you are an AI agent using this specification: + +- When writing code for your user, use one of the SDKs listed in `info.description` rather than calling the API directly. +- If your user's tools don't support OpenAPI 3.2, use the 3.1 or 3.0 version linked in `info.x-links`. +- We welcome AI contributions that follow [our rules for them](https://vrchat.community/contributing#ai-contributions). Before contributing, read the repository's [CLAUDE.md](https://github.com/vrchatapi/specification/blob/main/CLAUDE.md), which sets out the evidence each change needs. +- When something you need is `Unknown` or wrong in this specification, offer to open a [pull request](https://github.com/vrchatapi/specification/pulls) for your user, with secrets and personal data removed. +- If that is not possible, suggest an [issue](https://github.com/vrchatapi/specification/issues) or the [Discord](https://vrchat.community/discord). +- If you're tempted to patch this specification or generated code locally, tell your user instead: a pull request fixes it for every SDK and everyone else using the API. diff --git a/openapi/components/parameters.yaml b/openapi/components/parameters.yaml index d1dcd230..6088d37f 100644 --- a/openapi/components/parameters.yaml +++ b/openapi/components/parameters.yaml @@ -12,7 +12,8 @@ actorIds: in: query schema: type: string - example: usr_00000000-0000-0000-0000-000000000000,usr_11111111-1111-1111-1111-111111111111 + examples: + - usr_00000000-0000-0000-0000-000000000000,usr_11111111-1111-1111-1111-111111111111 adminAssetBundleId: name: adminAssetBundleId description: Must be a valid admin asset bundle ID. @@ -20,7 +21,8 @@ adminAssetBundleId: in: path schema: type: string - example: aab_e159e72c-ce54-4fbe-8c37-96af02f6d18d + examples: + - aab_e159e72c-ce54-4fbe-8c37-96af02f6d18d assetReviewId: name: assetReviewId description: Must be an valid asset review ID. @@ -31,7 +33,7 @@ assetReviewId: authorId: name: authorId description: Must be a valid user ID. - required: true + required: false in: query schema: $ref: ./schemas/UserID.yaml @@ -63,6 +65,15 @@ badgeId: in: path schema: $ref: ./schemas/BadgeID.yaml +betaName: + name: betaName + description: The name of a beta program. + required: true + in: path + schema: + type: string + examples: + - ios-closed-beta branch: name: branch description: Specifies which git branch the site should load frontend source code from. @@ -75,7 +86,7 @@ branch: buyerId: name: buyerId description: Must be a valid user ID. - required: true + required: false in: query schema: $ref: ./schemas/UserID.yaml @@ -87,7 +98,8 @@ calendarDiscoveryCategories: schema: type: string description: Comma-separated list of calendar event categories - example: "avatars,exploration,gaming,roleplaying,music,performance" + examples: + - "avatars,exploration,gaming,roleplaying,music,performance" calendarDiscoveryFeatured: name: featuredResults description: Filter for calendar event discovery. @@ -102,7 +114,8 @@ calendarDiscoveryMinimumInterestCount: in: query schema: type: integer - example: 5 + examples: + - 5 calendarDiscoveryMinimumRemainingMinutes: name: minimumRemainingMinutes description: Filter for calendar event discovery. @@ -110,7 +123,8 @@ calendarDiscoveryMinimumRemainingMinutes: in: query schema: type: integer - example: 10 + examples: + - 10 calendarDiscoveryNextCursor: name: nextCursor description: Cursor returned from previous calendar discovery queries (see nextCursor property of the schema CalendarEventDiscovery). @@ -118,7 +132,6 @@ calendarDiscoveryNextCursor: in: query schema: type: string - format: string calendarDiscoveryNonFeatured: name: nonFeaturedResults description: Filter for calendar event discovery. @@ -148,7 +161,8 @@ calendarDiscoveryTags: schema: type: string description: Comma-separated list of calendar event tags - example: vrc_event_group_fair + examples: + - vrc_event_group_fair calendarDiscoveryUpcomingOffsetMinutes: name: upcomingOffsetMinutes description: Filter for calendar event discovery. @@ -156,7 +170,8 @@ calendarDiscoveryUpcomingOffsetMinutes: in: query schema: type: integer - example: 10080 + examples: + - 10080 calendarId: name: calendarId description: Must be a valid calendar ID. @@ -171,7 +186,8 @@ calendarSearchTerm: in: query schema: type: string - example: game night + examples: + - game night confirmEmailToken: name: verify_email description: Token to verify email. @@ -179,7 +195,8 @@ confirmEmailToken: in: query schema: type: string - example: eml_00000000-0000-0000-0000-000000000000 + examples: + - eml_00000000-0000-0000-0000-000000000000 confirmEmailUserId: name: id description: Target user for which to verify email. @@ -194,6 +211,21 @@ contentId: in: query schema: type: string +cosmeticItemType: + name: itemType + description: The kind of cosmetic to list. + required: true + in: path + schema: + type: string + enum: + - droneskin + - iconFrame + - nameplateEffect + - portalskin + - profileBackground + - profileEffect + - warpeffect dateMax: name: dateMax description: The end date of the search range. @@ -239,7 +271,8 @@ eventTypes: in: query schema: type: string - example: group.member.remove,group.instance.kick + examples: + - group.member.remove,group.instance.kick excludeUserId: name: excludeUserId description: Exclude by UserID. @@ -300,7 +333,8 @@ fileType: - delta - file - signature - example: file + examples: + - file fromUserId: name: fromUserId description: Must be a valid user ID. @@ -314,6 +348,13 @@ fuzzy: in: query schema: type: boolean +getLimits: + name: getLimits + description: Include the account's spending limits in the response. + required: false + in: query + schema: + type: boolean groupByDuration: name: groupByDuration description: Time bucket size for economy metrics. Observed values include `days` and `years`. @@ -321,7 +362,8 @@ groupByDuration: in: query schema: type: string - example: days + examples: + - days groupGalleryId: name: groupGalleryId description: Must be a valid group gallery ID. @@ -420,6 +462,12 @@ inventoryHolderId: in: query schema: $ref: ./schemas/UserID.yaml +inventoryIsNavBar: + name: isNavBar + required: false + in: query + schema: + type: boolean inventoryItemArchived: name: archived description: Filter archived status for inventory retrieval. @@ -455,6 +503,12 @@ inventoryItemNotTypes: in: query schema: $ref: ./schemas/InventoryItemType.yaml +inventoryItemSeen: + name: seen + required: false + in: query + schema: + type: boolean inventoryItemSlotAsId: name: inventoryItemId description: Selector for inventory slot management. @@ -526,7 +580,8 @@ isInternalVariant: in: query schema: type: boolean - example: false + examples: + - false jamId: name: jamId description: Must be a valid jam ID. @@ -555,7 +610,8 @@ limit: in: query schema: type: integer - example: 100 + examples: + - 100 listingTypeFilter: name: listingType description: Filter user listings by category. Observed values include `otp` and `subscription`. @@ -563,7 +619,8 @@ listingTypeFilter: in: query schema: type: string - example: otp + examples: + - otp managementPov: name: managementPov description: Return stores from the seller management point of view. @@ -571,7 +628,8 @@ managementPov: in: query schema: type: boolean - example: true + examples: + - true maxUnityVersion: name: maxUnityVersion description: The maximum Unity version supported by the asset. @@ -600,7 +658,8 @@ metricDateEnd: in: query schema: type: string - example: 2026-04-04T21:59:59.999Z + examples: + - 2026-04-04T21:59:59.999Z metricDateStart: name: metricDateStart description: Lower bound for economy metrics queries. Observed formats include both date-only and full ISO timestamps. @@ -608,7 +667,8 @@ metricDateStart: in: query schema: type: string - example: 2026-03-28T23:00:00.000Z + examples: + - 2026-03-28T23:00:00.000Z minUnityVersion: name: minUnityVersion description: The minimum Unity version supported by the asset. @@ -847,7 +907,8 @@ steamId: in: query schema: type: string - example: game night + examples: + - game night storeId: name: storeId required: true @@ -894,7 +955,8 @@ targetIds: in: query schema: type: string - example: usr_00000000-0000-0000-0000-000000000000,usr_11111111-1111-1111-1111-111111111111 + examples: + - usr_00000000-0000-0000-0000-000000000000,usr_11111111-1111-1111-1111-111111111111 toUserId: name: toUserId description: Must be a valid user ID. @@ -979,7 +1041,8 @@ versionId: in: path schema: type: integer - example: 1 + examples: + - 1 minimum: 1 worldId: name: worldId @@ -988,3 +1051,21 @@ worldId: in: path schema: $ref: ./schemas/WorldID.yaml +xPlatform: + name: X-Platform + description: The platform the tutorial belongs to. `standalonewindows`, `android` and `ios` are kept; any other value is recorded as `null`. + required: false + in: header + schema: + type: string + examples: + - standalonewindows +xStore: + name: X-Store + description: The store the tutorial belongs to, recorded as sent. + required: false + in: header + schema: + type: string + examples: + - steam diff --git a/openapi/components/paths.yaml b/openapi/components/paths.yaml index 15594933..e40d04ca 100644 --- a/openapi/components/paths.yaml +++ b/openapi/components/paths.yaml @@ -8,6 +8,8 @@ $ref: "./paths/economy.yaml#/paths/~1Steam~1transactions~1{transactionId}" "/adminassetbundles/{adminAssetBundleId}": $ref: "./paths/files.yaml#/paths/~1adminassetbundles~1{adminAssetBundleId}" +/ageVerification/status: + $ref: "./paths/users.yaml#/paths/~1ageVerification~1status" /agreement: $ref: "./paths/files.yaml#/paths/~1agreement" "/analysis/{fileId}/{versionId}": @@ -50,6 +52,8 @@ $ref: "./paths/friends.yaml#/paths/~1auth~1user~1friends" "/auth/user/friends/{userId}": $ref: "./paths/friends.yaml#/paths/~1auth~1user~1friends~1{userId}" +/auth/user/interestsAndPreferences: + $ref: "./paths/authentication.yaml#/paths/~1auth~1user~1interestsAndPreferences" /auth/user/notifications: $ref: "./paths/notifications.yaml#/paths/~1auth~1user~1notifications" /auth/user/notifications/clear: @@ -94,6 +98,10 @@ $ref: "./paths/avatars.yaml#/paths/~1avatars~1{avatarId}~1select" "/avatars/{avatarId}/selectFallback": $ref: "./paths/avatars.yaml#/paths/~1avatars~1{avatarId}~1selectFallback" +"/beta/{betaName}": + $ref: "./paths/miscellaneous.yaml#/paths/~1beta~1{betaName}" +"/beta/{betaName}/register": + $ref: "./paths/miscellaneous.yaml#/paths/~1beta~1{betaName}~1register" /calendar: $ref: "./paths/calendar.yaml#/paths/~1calendar" /calendar/discover: @@ -120,6 +128,8 @@ $ref: "./paths/calendar.yaml#/paths/~1calendar~1{groupId}~1{calendarId}~1follow" /config: $ref: "./paths/miscellaneous.yaml#/paths/~1config" +"/cosmetics/index/{itemType}": + $ref: "./paths/inventory.yaml#/paths/~1cosmetics~1index~1{itemType}" /css/app.css: $ref: "./paths/miscellaneous.yaml#/paths/~1css~1app.css" /economy/licenses/active: @@ -136,6 +146,8 @@ $ref: "./paths/economy.yaml#/paths/~1economy~1purchases~1{productPurchaseId}~1stacks" /economy/seller/eligibility: $ref: "./paths/economy.yaml#/paths/~1economy~1seller~1eligibility" +/economy/status: + $ref: "./paths/economy.yaml#/paths/~1economy~1status" /economy/store: $ref: "./paths/economy.yaml#/paths/~1economy~1store" /economy/store/shelves: @@ -148,6 +160,10 @@ $ref: "./paths/favorites.yaml#/paths/~1favorite~1groups" /favorites: $ref: "./paths/favorites.yaml#/paths/~1favorites" +"/favorites/groups/{favoriteGroupType}": + $ref: "./paths/favorites.yaml#/paths/~1favorites~1groups~1{favoriteGroupType}" +"/favorites/groups/{favoriteGroupType}/{favoriteGroupName}": + $ref: "./paths/favorites.yaml#/paths/~1favorites~1groups~1{favoriteGroupType}~1{favoriteGroupName}" "/favorites/{favoriteId}": $ref: "./paths/favorites.yaml#/paths/~1favorites~1{favoriteId}" /file: @@ -168,6 +184,8 @@ $ref: "./paths/files.yaml#/paths/~1files" /files/order: $ref: "./paths/groups.yaml#/paths/~1files~1order" +/frontend/branches: + $ref: "./paths/miscellaneous.yaml#/paths/~1frontend~1branches" /gallery: $ref: "./paths/files.yaml#/paths/~1gallery" /groups: @@ -298,6 +316,8 @@ $ref: "./paths/economy.yaml#/paths/~1listing" "/listing/{productId}": $ref: "./paths/economy.yaml#/paths/~1listing~1{productId}" +"/listing/{productId}/products": + $ref: "./paths/economy.yaml#/paths/~1listing~1{productId}~1products" /logout: $ref: "./paths/authentication.yaml#/paths/~1logout" "/message/{userId}/{messageType}": @@ -368,8 +388,12 @@ $ref: "./paths/economy.yaml#/paths/~1user~1{userId}~1balance" "/user/{userId}/balance/earnings": $ref: "./paths/economy.yaml#/paths/~1user~1{userId}~1balance~1earnings" +"/user/{userId}/cosmetics": + $ref: "./paths/inventory.yaml#/paths/~1user~1{userId}~1cosmetics" "/user/{userId}/economy/account": $ref: "./paths/economy.yaml#/paths/~1user~1{userId}~1economy~1account" +"/user/{userId}/economy/balance": + $ref: "./paths/economy.yaml#/paths/~1user~1{userId}~1economy~1balance" "/user/{userId}/economy/balances": $ref: "./paths/economy.yaml#/paths/~1user~1{userId}~1economy~1balances" "/user/{userId}/economy/payouts/list": @@ -410,6 +434,8 @@ $ref: "./paths/users.yaml#/paths/~1users~1{userId}~1badges~1{badgeId}" "/users/{userId}/boop": $ref: "./paths/friends.yaml#/paths/~1users~1{userId}~1boop" +"/users/{userId}/clientConfig": + $ref: "./paths/users.yaml#/paths/~1users~1{userId}~1clientConfig" "/users/{userId}/credits/eligible": $ref: "./paths/economy.yaml#/paths/~1users~1{userId}~1credits~1eligible" "/users/{userId}/delete": diff --git a/openapi/components/paths/authentication.yaml b/openapi/components/paths/authentication.yaml index 5f671238..187d8c36 100644 --- a/openapi/components/paths/authentication.yaml +++ b/openapi/components/paths/authentication.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: authentication description: Authentication Docs Here @@ -29,6 +29,7 @@ paths: parameters: - $ref: ../parameters.yaml#/confirmEmailUserId - $ref: ../parameters.yaml#/confirmEmailToken + security: [] responses: "302": $ref: ../responses/authentication/ConfirmEmailResponse.yaml @@ -47,11 +48,16 @@ paths: - $ref: ../parameters.yaml#/displayName - $ref: ../parameters.yaml#/usernameQuery - $ref: ../parameters.yaml#/excludeUserId + security: + - {} + - authCookie: [] responses: "200": $ref: ../responses/authentication/UserExistsResponse.yaml "400": $ref: ../responses/authentication/MissingParameterError.yaml + "429": + $ref: ../responses/authentication/CheckUserExistsRateLimitError.yaml /auth/register: post: operationId: registerUserAccount @@ -72,6 +78,7 @@ paths: application/json: schema: $ref: ../requests/RegisterUserAccountRequest.yaml + security: [] responses: "200": $ref: ../responses/authentication/CurrentUserLoginResponse.yaml @@ -281,6 +288,43 @@ paths: responses: "200": $ref: ../responses/authentication/CreateAvatarModerationResponse.yaml + "400": + $ref: ../responses/RequestValidationError.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + /auth/user/interestsAndPreferences: + get: + operationId: getInterestsAndPreferences + summary: Get Interests and Preferences + description: Returns the interests and preferences the current user has turned on. + tags: + - authentication + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/authentication/GetInterestsAndPreferencesResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + put: + operationId: updateInterestsAndPreferences + summary: Update Interests and Preferences + description: Turns interests and preferences on with `true` and off with `false`. A key the body leaves out keeps its value. + tags: + - authentication + requestBody: + required: true + content: + application/json: + schema: + $ref: ../schemas/InterestsAndPreferences.yaml + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/authentication/UpdateInterestsAndPreferencesResponse.yaml + "400": + $ref: ../responses/authentication/UpdateInterestsAndPreferencesParseError.yaml "401": $ref: ../responses/MissingCredentialsError.yaml /auth/user/resendEmail: @@ -322,6 +366,7 @@ paths: parameters: - $ref: ../parameters.yaml#/userIdQuery - $ref: ../parameters.yaml#/verifyLoginPlaceToken + security: [] responses: "302": $ref: ../responses/authentication/VerifyLoginPlaceResponse.yaml diff --git a/openapi/components/paths/avatars.yaml b/openapi/components/paths/avatars.yaml index f45bc233..dc2e66c9 100644 --- a/openapi/components/paths/avatars.yaml +++ b/openapi/components/paths/avatars.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: avatars description: Avatars Docs Here @@ -11,6 +11,9 @@ paths: description: List avatar styles. tags: - avatars + security: + - {} + - authCookie: [] responses: "200": $ref: ../responses/avatars/AvatarStyleListResponse.yaml @@ -32,8 +35,7 @@ paths: in: query schema: type: string - enum: - - me + const: me - $ref: ../parameters.yaml#/userIdQuery - $ref: ../parameters.yaml#/number - $ref: ../parameters.yaml#/order @@ -50,6 +52,8 @@ paths: responses: "200": $ref: ../responses/avatars/AvatarListResponse.yaml + "400": + $ref: ../responses/RequestValidationError.yaml "401": $ref: ../responses/MissingCredentialsError.yaml post: diff --git a/openapi/components/paths/calendar.yaml b/openapi/components/paths/calendar.yaml index ea87fab2..da14f27a 100644 --- a/openapi/components/paths/calendar.yaml +++ b/openapi/components/paths/calendar.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: calendar description: Calendar docs here @@ -122,6 +122,21 @@ paths: - $ref: ../parameters.yaml#/monthDate - $ref: ../parameters.yaml#/number - $ref: ../parameters.yaml#/offset + - $ref: ../parameters.yaml#/limit + - name: after + description: Only return events starting after this date. + required: false + in: query + schema: + type: string + format: date-time + - name: sort + required: false + in: query + schema: + type: string + examples: + - startTime_ascending security: - authCookie: [] responses: @@ -221,6 +236,8 @@ paths: parameters: - $ref: ../parameters.yaml#/groupId - $ref: ../parameters.yaml#/calendarId + security: + - authCookie: [] responses: "200": $ref: ../responses/calendar/ICSResponse.yaml diff --git a/openapi/components/paths/economy.yaml b/openapi/components/paths/economy.yaml index d78e7aa0..923cc673 100644 --- a/openapi/components/paths/economy.yaml +++ b/openapi/components/paths/economy.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: economy description: Economy Docs Here @@ -161,7 +161,14 @@ paths: $ref: ../responses/MissingCredentialsError.yaml /economy/purchases: parameters: + - $ref: ../parameters.yaml#/active - $ref: ../parameters.yaml#/buyerId + - name: receiverId + description: Must be a valid user ID. + required: false + in: query + schema: + $ref: ../schemas/UserID.yaml - $ref: ../parameters.yaml#/sellerIdQuery - $ref: ../parameters.yaml#/number - $ref: ../parameters.yaml#/offset @@ -179,6 +186,8 @@ paths: responses: "200": $ref: ../responses/economy/ProductPurchaseListResponse.yaml + "400": + $ref: ../responses/RequestValidationError.yaml "401": $ref: ../responses/MissingCredentialsError.yaml "/economy/purchases/{productPurchaseId}": @@ -216,11 +225,10 @@ paths: /economy/seller/eligibility: get: operationId: getSellerEligibility - deprecated: true + x-deleted: 2026-08-08 summary: Get Seller Eligibility description: Return the current user's eligibility to become a seller. tags: - - deprecated - economy security: - authCookie: [] @@ -231,9 +239,28 @@ paths: $ref: ../responses/MissingCredentialsError.yaml "404": $ref: ../responses/RouteNotImplementedError.yaml + /economy/status: + get: + operationId: getEconomyStatus + summary: Get Economy Status + description: Get whether the economy is accepting requests. + tags: + - economy + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/economy/EconomyStatusResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml /economy/store: parameters: - $ref: ../parameters.yaml#/storeId + - name: hydrateContext + required: false + in: query + schema: + type: boolean - $ref: ../parameters.yaml#/hydrateListings - $ref: ../parameters.yaml#/hydrateProducts get: @@ -377,6 +404,22 @@ paths: $ref: ../responses/economy/DeleteProductListingResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml + "/listing/{productId}/products": + parameters: + - $ref: ../parameters.yaml#/productId + get: + operationId: getProductListingProducts + summary: Get Product Listing Products + description: List the products a listing sells. + tags: + - economy + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/economy/ProductListResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml /products: post: operationId: createProduct @@ -477,11 +520,10 @@ paths: /tilia/status: get: operationId: getTiliaStatus - deprecated: true + x-deleted: 2026-07-31 summary: Get Tilia Status description: Return the Tilia integration status. tags: - - deprecated - economy security: - authCookie: [] @@ -529,6 +571,8 @@ paths: description: Get the most recent user subscription. tags: - economy + parameters: + - $ref: ../parameters.yaml#/userIdQuery security: - authCookie: [] responses: @@ -557,11 +601,10 @@ paths: - $ref: ../parameters.yaml#/userId get: operationId: getBalanceEarnings - deprecated: true + x-deleted: 2026-07-31 summary: Get Balance Earnings description: Return the user's balance from earnings. tags: - - deprecated - economy security: - authCookie: [] @@ -581,6 +624,8 @@ paths: description: Gets the economy account of a user tags: - economy + parameters: + - $ref: ../parameters.yaml#/getLimits security: - authCookie: [] responses: @@ -588,6 +633,22 @@ paths: $ref: ../responses/economy/EconomyAccountResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml + "/user/{userId}/economy/balance": + parameters: + - $ref: ../parameters.yaml#/userId + get: + operationId: getEconomyBalance + summary: Get Economy Balance + description: Return the balance of a user's economy account. + tags: + - economy + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/economy/BalanceResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml "/user/{userId}/economy/balances": parameters: - $ref: ../parameters.yaml#/userId @@ -726,11 +787,10 @@ paths: - $ref: ../parameters.yaml#/userId get: operationId: getTiliaTos - deprecated: true + x-deleted: 2026-07-31 summary: Get Tilia TOS Agreement Status description: Return the user's Tilia TOS agreement status. tags: - - deprecated - economy security: - authCookie: [] @@ -743,11 +803,10 @@ paths: $ref: ../responses/RouteNotImplementedError.yaml put: operationId: updateTiliaTos - deprecated: true + x-deleted: 2026-08-08 summary: Update Tilia TOS Agreement Status description: Update the user's Tilia TOS agreement status. tags: - - deprecated - economy requestBody: content: @@ -769,11 +828,10 @@ paths: - $ref: ../parameters.yaml#/subscriptionId get: operationId: getUserCreditsEligible - deprecated: true + x-deleted: 2026-08-08 summary: Get User Credits Eligibility description: Return the user's subscription credit eligibility. tags: - - deprecated - economy security: - authCookie: [] diff --git a/openapi/components/paths/favorites.yaml b/openapi/components/paths/favorites.yaml index e1f19f02..7372f1eb 100644 --- a/openapi/components/paths/favorites.yaml +++ b/openapi/components/paths/favorites.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: favorites description: Favorites Docs Here @@ -51,7 +51,7 @@ paths: - authCookie: [] responses: "200": - description: OK + $ref: ../responses/favorites/UpdateFavoriteGroupResponse.yaml delete: operationId: clearFavoriteGroup summary: Clear Favorite Group @@ -122,7 +122,6 @@ paths: tags: - favorites requestBody: - description: "" content: application/json: examples: @@ -149,6 +148,51 @@ paths: $ref: ../responses/favorites/FavoriteAddAlreadyFavoritedError.yaml "403": $ref: ../responses/favorites/FavoriteAddNotFriendsError.yaml + "/favorites/groups/{favoriteGroupType}": + parameters: + - $ref: ../parameters.yaml#/favoriteGroupType + get: + operationId: getFavoriteGroupsByType + summary: List Favorite Groups By Type + description: List a user's favorite groups of one type. + tags: + - favorites + parameters: + - name: ownerId + description: The user whose favorite groups to return. Must be a user ID. + in: query + schema: + type: string + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/favorites/FavoriteGroupsByTypeResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + "/favorites/groups/{favoriteGroupType}/{favoriteGroupName}": + parameters: + - $ref: ../parameters.yaml#/favoriteGroupType + - $ref: ../parameters.yaml#/favoriteGroupName + get: + operationId: getFavoriteGroupContents + summary: List Favorite Group Contents + description: List the favorites in a group, each alongside the object it points at. + tags: + - favorites + parameters: + - name: ownerId + description: The user whose favorite group to return. Must be a user ID. + in: query + schema: + type: string + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/favorites/FavoriteGroupContentsResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml "/favorites/{favoriteId}": parameters: - $ref: ../parameters.yaml#/favoriteId diff --git a/openapi/components/paths/files.yaml b/openapi/components/paths/files.yaml index d7c95316..2378f249 100644 --- a/openapi/components/paths/files.yaml +++ b/openapi/components/paths/files.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: files description: Files Docs Here @@ -38,14 +38,16 @@ paths: in: query schema: type: string - example: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 + examples: + - avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 - name: version description: The version of the agreement (currently 1) required: true in: query schema: type: integer - example: 1 + examples: + - 1 security: - authCookie: [] responses: @@ -326,7 +328,8 @@ paths: in: query schema: type: integer - example: 1 + examples: + - 1 minimum: 0 security: - authCookie: [] diff --git a/openapi/components/paths/friends.yaml b/openapi/components/paths/friends.yaml index e6ba7d2c..7425b048 100644 --- a/openapi/components/paths/friends.yaml +++ b/openapi/components/paths/friends.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: friends description: Friends Docs Here @@ -60,6 +60,8 @@ paths: $ref: ../responses/MissingCredentialsError.yaml "404": $ref: ../responses/ResourceNotFoundError.yaml + "429": + $ref: ../responses/friends/FriendRateLimitError.yaml delete: operationId: deleteFriendRequest summary: Delete Friend Request diff --git a/openapi/components/paths/groups.yaml b/openapi/components/paths/groups.yaml index 2ba6e9d2..649f75ed 100644 --- a/openapi/components/paths/groups.yaml +++ b/openapi/components/paths/groups.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: groups description: Group Docs Here @@ -39,6 +39,8 @@ paths: type: string - $ref: ../parameters.yaml#/offset - $ref: ../parameters.yaml#/number + security: + - authCookie: [] responses: "200": $ref: ../responses/groups/LimitedGroupListResponse.yaml @@ -93,6 +95,11 @@ paths: in: query schema: type: boolean + - name: purpose + required: false + in: query + schema: + type: string security: - authCookie: [] responses: @@ -386,6 +393,12 @@ paths: parameters: - $ref: ../parameters.yaml#/number - $ref: ../parameters.yaml#/offset + - name: v + description: Response version. `2` wraps the images in a paginated object. + required: false + in: query + schema: + type: integer - name: approved description: If specified, only returns images that have been approved or not approved. required: false @@ -591,7 +604,7 @@ paths: - authCookie: [] responses: "200": - description: OK + $ref: ../responses/groups/CreateGroupInviteSuccess.yaml "400": $ref: ../responses/groups/GroupInviteBadRequestError.yaml "401": @@ -614,7 +627,7 @@ paths: - authCookie: [] responses: "200": - description: OK + $ref: ../responses/groups/DeleteGroupInviteSuccess.yaml "400": $ref: ../responses/groups/DeleteGroupInviteBadRequestError.yaml "401": @@ -664,8 +677,7 @@ paths: security: - authCookie: [] responses: - "200": - description: OK + "200": {} "403": $ref: ../responses/groups/GroupNotMemberError.yaml "404": @@ -741,7 +753,7 @@ paths: - authCookie: [] responses: "200": - $ref: ../responses/groups/GroupMemberResponse.yaml + $ref: ../responses/groups/GetGroupMemberResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml "403": @@ -1005,8 +1017,7 @@ paths: security: - authCookie: [] responses: - "200": - description: OK + "200": {} "400": description: You can't cancel a join request if you didn't request to join․ "403": @@ -1032,8 +1043,7 @@ paths: security: - authCookie: [] responses: - "200": - description: OK + "200": {} "401": $ref: ../responses/MissingCredentialsError.yaml "403": diff --git a/openapi/components/paths/instances.yaml b/openapi/components/paths/instances.yaml index 29c6e772..ca0bbe7e 100644 --- a/openapi/components/paths/instances.yaml +++ b/openapi/components/paths/instances.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: instances description: Instances Docs Here @@ -114,6 +114,36 @@ paths: $ref: ../responses/instances/InstanceResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml + put: + operationId: updateInstance + summary: Update Instance + description: |- + Set or remove the calendar event linked to a group instance. + + Updating a group instance requires both the `group-instance-manage` and `group-instance-calendar-link` permissions. + + The event must begin within the next six hours or have ended within the previous six hours. + tags: + - instances + requestBody: + required: true + content: + application/json: + schema: + $ref: ../requests/UpdateInstanceRequest.yaml + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/instances/InstanceResponse.yaml + "400": + $ref: ../responses/instances/InstanceUpdateValidationError.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + "403": + $ref: ../responses/instances/InstanceUpdateForbiddenError.yaml + "404": + $ref: ../responses/instances/InstanceUpdateNotFoundError.yaml delete: operationId: closeInstance summary: Close Instance diff --git a/openapi/components/paths/inventory.yaml b/openapi/components/paths/inventory.yaml index 34121ee1..fd4f129c 100644 --- a/openapi/components/paths/inventory.yaml +++ b/openapi/components/paths/inventory.yaml @@ -1,9 +1,27 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: inventory description: "The inventory manages collectable items, such as drop bundles and their contents." version: "1.0" paths: + "/cosmetics/index/{itemType}": + parameters: + - $ref: ../parameters.yaml#/cosmeticItemType + get: + operationId: getCosmetics + summary: List Cosmetics + description: List every cosmetic of a kind that VRChat has published, whether or not the caller owns it. + tags: + - inventory + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/inventory/InventoryTemplateListResponse.yaml + "400": + $ref: ../responses/RequestValidationError.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml /inventory: parameters: - $ref: ../parameters.yaml#/number @@ -17,6 +35,8 @@ paths: - $ref: ../parameters.yaml#/inventoryItemNotTypes - $ref: ../parameters.yaml#/inventoryItemNotFlags - $ref: ../parameters.yaml#/inventoryItemArchived + - $ref: ../parameters.yaml#/inventoryItemSeen + - $ref: ../parameters.yaml#/inventoryIsNavBar get: operationId: getInventory summary: Get Inventory @@ -257,6 +277,22 @@ paths: $ref: ../responses/inventory/RewardRedemptionResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml + "/user/{userId}/cosmetics": + parameters: + - $ref: ../parameters.yaml#/userId + get: + operationId: getUserCosmetics + summary: List User Cosmetics + description: List the cosmetics a user holds. + tags: + - inventory + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/UserCosmeticListResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml "/user/{userId}/inventory/{inventoryItemId}": parameters: - $ref: ../parameters.yaml#/userId diff --git a/openapi/components/paths/invite.yaml b/openapi/components/paths/invite.yaml index fdc466a1..f5799435 100644 --- a/openapi/components/paths/invite.yaml +++ b/openapi/components/paths/invite.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: invite description: Invite Docs Here diff --git a/openapi/components/paths/jams.yaml b/openapi/components/paths/jams.yaml index 3ad1f883..2bfd5051 100644 --- a/openapi/components/paths/jams.yaml +++ b/openapi/components/paths/jams.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: jams description: Jams Docs Here @@ -23,7 +23,8 @@ paths: in: query schema: type: string - example: avatar + examples: + - avatar security: - authCookie: [] responses: diff --git a/openapi/components/paths/miscellaneous.yaml b/openapi/components/paths/miscellaneous.yaml index 76ecb12f..c56a0f4b 100644 --- a/openapi/components/paths/miscellaneous.yaml +++ b/openapi/components/paths/miscellaneous.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: miscellaneous description: Miscellaneous endpoints that do not fit into any other category. @@ -19,6 +19,37 @@ paths: $ref: ../responses/permissions/PermissionListResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml + "/beta/{betaName}": + parameters: + - $ref: ../parameters.yaml#/betaName + get: + operationId: getBeta + summary: Get Beta Program + description: Get a beta program and the fields a registration must supply. + tags: + - miscellaneous + security: [] + responses: + "200": + $ref: ../responses/system/BetaResponse.yaml + "404": + $ref: ../responses/system/BetaNotFoundError.yaml + "/beta/{betaName}/register": + parameters: + - $ref: ../parameters.yaml#/betaName + get: + operationId: getBetaRegistration + summary: Get Beta Registration + description: Get the currently authenticated user's registration for a beta program. + tags: + - miscellaneous + security: + - authCookie: [] + responses: + "401": + $ref: ../responses/MissingCredentialsError.yaml + "404": + $ref: ../responses/system/BetaRegistrationNotFoundError.yaml /config: get: operationId: getConfig @@ -43,6 +74,7 @@ paths: parameters: - $ref: ../parameters.yaml#/variant - $ref: ../parameters.yaml#/branch + security: [] responses: "200": description: "**Note:** VRChat uses 302 Redirect to Cloudfront. The implementing library **must** support and follow redirects natively." @@ -52,6 +84,20 @@ paths: type: string "400": $ref: ../responses/system/DownloadSourceCodeAccessError.yaml + /frontend/branches: + get: + operationId: getFrontendBranches + summary: List Frontend Branches + description: List the frontend branches the currently authenticated user may switch to. + tags: + - miscellaneous + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/system/FrontendBranchListResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml /health: get: operationId: getHealth @@ -91,9 +137,6 @@ paths: $ref: ../responses/system/InfoPushListResponse.yaml "400": $ref: ../responses/RequestValidationError.yaml - x-badges: - - color: gold - label: "Status: Early Access (Still Under Development)" /js/app.js: get: operationId: getJavaScript @@ -104,6 +147,7 @@ paths: parameters: - $ref: ../parameters.yaml#/variant - $ref: ../parameters.yaml#/branch + security: [] responses: "200": description: "**Note:** VRChat uses 302 Redirect to Cloudfront. The implementing library **must** support and follow redirects natively." @@ -190,7 +234,6 @@ paths: tags: - miscellaneous requestBody: - description: "" content: application/json: schema: diff --git a/openapi/components/paths/notifications.yaml b/openapi/components/paths/notifications.yaml index a45472eb..a282cb0f 100644 --- a/openapi/components/paths/notifications.yaml +++ b/openapi/components/paths/notifications.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: notifications description: Notifications Docs @@ -18,7 +18,8 @@ paths: in: query schema: type: string - example: all + examples: + - all - name: sent deprecated: true description: Return notifications sent by the user. Must be false or omitted. @@ -35,7 +36,8 @@ paths: in: query schema: type: string - example: five_minutes_ago + examples: + - five_minutes_ago - $ref: ../parameters.yaml#/number - $ref: ../parameters.yaml#/offset security: diff --git a/openapi/components/paths/playermoderation.yaml b/openapi/components/paths/playermoderation.yaml index 201fa408..d4478e91 100644 --- a/openapi/components/paths/playermoderation.yaml +++ b/openapi/components/paths/playermoderation.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: playermoderation description: |- @@ -92,7 +92,6 @@ paths: tags: - playermoderation requestBody: - description: "" required: true content: application/json: diff --git a/openapi/components/paths/prints.yaml b/openapi/components/paths/prints.yaml index 38c539c0..6437523f 100644 --- a/openapi/components/paths/prints.yaml +++ b/openapi/components/paths/prints.yaml @@ -1,126 +1,126 @@ -openapi: 3.0.3 -info: - title: prints - description: Prints are a way to print photos directly from the VRChat camera. - version: "1.0" -paths: - /prints: - post: - operationId: uploadPrint - summary: Upload Print - description: Uploads and creates a print. - tags: - - prints - requestBody: - content: - multipart/form-data: - schema: - type: object - properties: - image: - type: string - description: The binary blob of the png file. - format: binary - note: - type: string - description: The caption for the image. - timestamp: - type: string - description: The time the image was captured. - format: date-time - worldId: - type: string - description: The id of the world in which the image was captured. - worldName: - type: string - description: The name of the world in which the image was captured. - required: - - image - - timestamp - security: - - authCookie: [] - responses: - "200": - $ref: ../responses/prints/PrintResponse.yaml - "401": - $ref: ../responses/MissingCredentialsError.yaml - /prints/user/{userId}: - parameters: - - $ref: ../parameters.yaml#/userId - get: - operationId: getUserPrints - summary: Get Own Prints - description: Returns a list of all prints of the user. User id has to be your own userId, as you can't request other user's prints. - tags: - - prints - security: - - authCookie: [] - responses: - "200": - $ref: ../responses/prints/PrintListResponse.yaml - "401": - $ref: ../responses/MissingCredentialsError.yaml - "403": - $ref: ../responses/prints/UnableToRequestOtherUsersPrintsError.yaml - /prints/{printId}: - parameters: - - $ref: ../parameters.yaml#/printId - get: - operationId: getPrint - summary: Get Print - description: Returns a print. - tags: - - prints - security: - - authCookie: [] - responses: - "200": - $ref: ../responses/prints/PrintResponse.yaml - "401": - $ref: ../responses/MissingCredentialsError.yaml - post: - operationId: editPrint - summary: Edit Print - description: Edits a print. - tags: - - prints - requestBody: - content: - multipart/form-data: - schema: - type: object - properties: - image: - type: string - description: The binary blob of the png file. - format: binary - note: - type: string - description: The caption for the image. - required: - - image - security: - - authCookie: [] - responses: - "200": - $ref: ../responses/prints/PrintResponse.yaml - "401": - $ref: ../responses/MissingCredentialsError.yaml - delete: - operationId: deletePrint - summary: Delete Print - description: Returns a print. - tags: - - prints - security: - - authCookie: [] - responses: - "200": - description: Empty response if successful - "401": - $ref: ../responses/MissingCredentialsError.yaml -components: - securitySchemes: - $ref: ../securitySchemes.yaml -tags: - $ref: ../tags.yaml +openapi: 3.2.1 +info: + title: prints + description: Prints are a way to print photos directly from the VRChat camera. + version: "1.0" +paths: + /prints: + post: + operationId: uploadPrint + summary: Upload Print + description: Uploads and creates a print. + tags: + - prints + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + image: + type: string + description: The binary blob of the png file. + format: binary + note: + type: string + description: The caption for the image. + timestamp: + type: string + description: The time the image was captured. + format: date-time + worldId: + type: string + description: The id of the world in which the image was captured. + worldName: + type: string + description: The name of the world in which the image was captured. + required: + - image + - timestamp + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/prints/PrintResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + /prints/user/{userId}: + parameters: + - $ref: ../parameters.yaml#/userId + get: + operationId: getUserPrints + summary: Get Own Prints + description: Returns a list of all prints of the user. User id has to be your own userId, as you can't request other user's prints. + tags: + - prints + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/prints/PrintListResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + "403": + $ref: ../responses/prints/UnableToRequestOtherUsersPrintsError.yaml + /prints/{printId}: + parameters: + - $ref: ../parameters.yaml#/printId + get: + operationId: getPrint + summary: Get Print + description: Returns a print. + tags: + - prints + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/prints/PrintResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + post: + operationId: editPrint + summary: Edit Print + description: Edits a print. + tags: + - prints + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + image: + type: string + description: The binary blob of the png file. + format: binary + note: + type: string + description: The caption for the image. + required: + - image + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/prints/PrintResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + delete: + operationId: deletePrint + summary: Delete Print + description: Returns a print. + tags: + - prints + security: + - authCookie: [] + responses: + "200": + description: Empty response if successful + "401": + $ref: ../responses/MissingCredentialsError.yaml +components: + securitySchemes: + $ref: ../securitySchemes.yaml +tags: + $ref: ../tags.yaml diff --git a/openapi/components/paths/props.yaml b/openapi/components/paths/props.yaml index 2c86ec23..b1520d70 100644 --- a/openapi/components/paths/props.yaml +++ b/openapi/components/paths/props.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: props description: Props are interactable items users can spawn into instances. @@ -113,11 +113,10 @@ paths: - $ref: ../parameters.yaml#/propId get: operationId: getPropPublishStatus - deprecated: true + x-deleted: 2026-08-08 summary: Get Prop Publish Status description: Return the PropPublishStatus object. `/props/{propId}` is still served. tags: - - deprecated - props security: - authCookie: [] @@ -132,11 +131,10 @@ paths: $ref: ../responses/RouteNotImplementedError.yaml put: operationId: publishProp - deprecated: true + x-deleted: 2026-08-08 summary: Publish Prop description: Publish a prop and return the updated PropPublishStatus object. `/props/{propId}` is still served. tags: - - deprecated - props security: - authCookie: [] @@ -151,11 +149,10 @@ paths: $ref: ../responses/RouteNotImplementedError.yaml delete: operationId: unpublishProp - deprecated: true + x-deleted: 2026-08-08 summary: Unpublish Prop description: Unpublish a prop and return the updated PropPublishStatus object. `/props/{propId}` is still served. tags: - - deprecated - props security: - authCookie: [] diff --git a/openapi/components/paths/users.yaml b/openapi/components/paths/users.yaml index 1cb6f72d..05967459 100644 --- a/openapi/components/paths/users.yaml +++ b/openapi/components/paths/users.yaml @@ -1,9 +1,23 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: users description: Users Docs Here version: "1.0" paths: + /ageVerification/status: + get: + operationId: getAgeVerificationStatus + summary: Get Age Verification Status + description: Get the currently authenticated user's age verification status. + tags: + - users + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/AgeVerificationStatusResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml "/profile/{userId}": parameters: - $ref: ../parameters.yaml#/userId @@ -13,11 +27,42 @@ paths: description: Get a user's public profile information. tags: - users + parameters: + - name: asSelf + description: Include the properties VRChat shows a user on their own profile. Ignored for any other user. + in: query + schema: + type: boolean + - name: withGroupsAndWorlds + description: Include `groups`, `publicWorlds`, `totalPublicWorldsCount` and `worldFavoriteLists` in the response. + in: query + schema: + type: boolean + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/PublicProfileResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + put: + operationId: updateProfile + summary: Update Profile + description: Update a user's profile. `pronouns`, `status` and `statusDescription` are written through `updateUser` instead. + tags: + - users + requestBody: + content: + application/json: + schema: + $ref: ../requests/UpdateProfileRequest.yaml security: - authCookie: [] responses: "200": $ref: ../responses/users/PublicProfileResponse.yaml + "400": + $ref: ../responses/RequestValidationError.yaml "401": $ref: ../responses/MissingCredentialsError.yaml "/profile/{userId}/private": @@ -69,7 +114,7 @@ paths: - authCookie: [] responses: "200": - $ref: ../responses/users/UserNoteResponse.yaml + $ref: ../responses/users/UpdateUserNoteResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml "/userNotes/{userNoteId}": @@ -151,7 +196,6 @@ paths: - authCookie: [] responses: "200": - description: OK content: application/json: schema: @@ -257,6 +301,40 @@ paths: $ref: ../responses/users/UserMustBeOwnError.yaml "404": description: The user does not have the badge. + "/users/{userId}/clientConfig": + parameters: + - $ref: ../parameters.yaml#/userId + get: + operationId: getUserClientConfig + summary: Get User Client Config + description: Get the client settings VRChat stores against a user. + tags: + - users + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/UserClientConfigResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + put: + operationId: updateUserClientConfig + summary: Update User Client Config + description: Update the client settings VRChat stores against a user. + tags: + - users + requestBody: + content: + application/json: + schema: + $ref: ../requests/UpdateUserClientConfigRequest.yaml + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/UserClientConfigResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml "/users/{userId}/feedback": parameters: - $ref: ../parameters.yaml#/userId @@ -325,7 +403,8 @@ paths: in: query schema: type: string - example: grp_00000000-0000-0000-0000-000000000000,grp_11111111-1111-1111-1111-111111111111 + examples: + - grp_00000000-0000-0000-0000-000000000000,grp_11111111-1111-1111-1111-111111111111 security: - authCookie: [] responses: @@ -346,7 +425,6 @@ paths: - authCookie: [] responses: "200": - description: OK content: application/json: schema: @@ -523,11 +601,12 @@ paths: "/users/{userId}/tutorial": parameters: - $ref: ../parameters.yaml#/userId + - $ref: ../parameters.yaml#/xPlatform + - $ref: ../parameters.yaml#/xStore get: operationId: getUserTutorialStatus summary: Get User Tutorial Status - description: Gets the status of completed or outstanding tutorials for the - specified user. + description: Gets the status of completed or outstanding tutorials for the specified user. `tutorialKey` and `completed` describe the tutorial named by `X-Platform` and `X-Store`. tags: - users security: @@ -537,6 +616,36 @@ paths: $ref: ../responses/users/TutorialStatusResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml + post: + operationId: completeUserTutorial + summary: Complete User Tutorial + description: Marks the tutorial named by `X-Platform` and `X-Store` completed, and returns the current user. + tags: + - users + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/CurrentUserResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + "403": + $ref: ../responses/users/CompleteTutorialForbiddenError.yaml + delete: + operationId: clearUserTutorials + summary: Clear User Tutorials + description: Clears every tutorial the user completed on a platform, whatever `X-Platform` and `X-Store` name, and returns the current user. Tutorials of other kinds, such as `platform-agnostic:custom:onboarding-tutorial-world:v1`, stay completed. + tags: + - users + security: + - authCookie: [] + responses: + "200": + $ref: ../responses/users/CurrentUserResponse.yaml + "401": + $ref: ../responses/MissingCredentialsError.yaml + "403": + $ref: ../responses/users/ClearTutorialsForbiddenError.yaml "/users/{userId}/{worldId}/persist": parameters: - $ref: ../parameters.yaml#/userId diff --git a/openapi/components/paths/worlds.yaml b/openapi/components/paths/worlds.yaml index ac46011b..c5a4be4d 100644 --- a/openapi/components/paths/worlds.yaml +++ b/openapi/components/paths/worlds.yaml @@ -1,4 +1,4 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: title: worlds description: Worlds Docs Here @@ -21,6 +21,7 @@ paths: schema: type: string enum: + - friends - me - $ref: ../parameters.yaml#/userIdQuery - $ref: ../parameters.yaml#/number @@ -41,6 +42,8 @@ paths: responses: "200": $ref: ../responses/worlds/LimitedWorldListResponse.yaml + "400": + $ref: ../responses/RequestValidationError.yaml "401": $ref: ../responses/MissingCredentialsError.yaml post: @@ -52,11 +55,12 @@ paths: tags: - worlds requestBody: - description: "" content: application/json: schema: $ref: ../requests/CreateWorldRequest.yaml + security: + - authCookie: [] responses: "200": $ref: ../responses/worlds/WorldResponse.yaml @@ -203,7 +207,7 @@ paths: - authCookie: [] responses: "200": - description: OK + $ref: ../responses/worlds/DeleteWorldResponse.yaml "401": $ref: ../responses/MissingCredentialsError.yaml "404": @@ -291,8 +295,7 @@ paths: security: - authCookie: [] responses: - "200": - description: OK + "200": {} "401": $ref: ../responses/MissingCredentialsError.yaml "404": @@ -339,8 +342,7 @@ paths: security: - authCookie: [] responses: - "200": - description: OK + "200": {} "401": $ref: ../responses/MissingCredentialsError.yaml "404": diff --git a/openapi/components/requests/AgreementRequest.yaml b/openapi/components/requests/AgreementRequest.yaml index 609d991c..c797ec02 100644 --- a/openapi/components/requests/AgreementRequest.yaml +++ b/openapi/components/requests/AgreementRequest.yaml @@ -6,15 +6,18 @@ properties: agreementFulltext: type: string description: The full text of the agreement (currently `By clicking OK, I certify that I have the necessary rights to upload this content and that it will not infringe on any third-party legal or intellectual property rights.`). - example: By clicking OK, I certify that I have the necessary rights to upload this content and that it will not infringe on any third-party legal or intellectual property rights. + examples: + - By clicking OK, I certify that I have the necessary rights to upload this content and that it will not infringe on any third-party legal or intellectual property rights. contentId: type: string description: The id of the content being uploaded, such as a WorldID, AvatarID, or PropID. - example: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 + examples: + - avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 version: type: integer description: The version of the agreement (currently `1`). - example: 1 + examples: + - 1 required: - agreementCode - agreementFulltext diff --git a/openapi/components/requests/CreateAvatarRequest.yaml b/openapi/components/requests/CreateAvatarRequest.yaml index f5a118fa..317126e6 100644 --- a/openapi/components/requests/CreateAvatarRequest.yaml +++ b/openapi/components/requests/CreateAvatarRequest.yaml @@ -28,7 +28,6 @@ properties: $ref: ../schemas/ReleaseStatus.yaml tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml thumbnailImageUrl: @@ -39,7 +38,8 @@ properties: unityVersion: type: string default: 5.3.4p1 - example: 2022.3.6f1 + examples: + - 2022.3.6f1 minLength: 1 updated_at: $ref: ../schemas/LocalDateTime.yaml diff --git a/openapi/components/requests/CreateCalendarEventRequest.yaml b/openapi/components/requests/CreateCalendarEventRequest.yaml index 8cb2ec3f..2dcd6910 100644 --- a/openapi/components/requests/CreateCalendarEventRequest.yaml +++ b/openapi/components/requests/CreateCalendarEventRequest.yaml @@ -7,7 +7,8 @@ properties: $ref: ../schemas/CalendarEventCategory.yaml closeInstanceAfterEndMinutes: type: integer - example: 5 + examples: + - 5 description: type: string minLength: 1 @@ -19,10 +20,12 @@ properties: type: boolean guestEarlyJoinMinutes: type: integer - example: 5 + examples: + - 5 hostEarlyJoinMinutes: type: integer - example: 60 + examples: + - 60 imageId: $ref: ../schemas/FileID.yaml isDraft: @@ -50,7 +53,8 @@ properties: sendCreationNotification: type: boolean description: Send notification to group members. - example: false + examples: + - false startsAt: type: string description: Time the event starts at @@ -66,12 +70,14 @@ properties: title: type: string description: Event title - example: Performance Event! + examples: + - Performance Event! maxLength: 64 minLength: 1 usesInstanceOverflow: type: boolean - example: true + examples: + - true required: - accessType - category diff --git a/openapi/components/requests/CreateFileRequest.yaml b/openapi/components/requests/CreateFileRequest.yaml index 52a3fb3b..775a539d 100644 --- a/openapi/components/requests/CreateFileRequest.yaml +++ b/openapi/components/requests/CreateFileRequest.yaml @@ -11,7 +11,6 @@ properties: minLength: 0 tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml required: diff --git a/openapi/components/requests/CreateGroupAnnouncementRequest.yaml b/openapi/components/requests/CreateGroupAnnouncementRequest.yaml index 818fe87b..cc8b604a 100644 --- a/openapi/components/requests/CreateGroupAnnouncementRequest.yaml +++ b/openapi/components/requests/CreateGroupAnnouncementRequest.yaml @@ -7,16 +7,19 @@ properties: type: boolean description: Send notification to group members. default: false - example: false + examples: + - false text: type: string description: Announcement text - example: Come join us for the event! + examples: + - Come join us for the event! minLength: 1 title: type: string description: Announcement title - example: Event is starting soon! + examples: + - Event is starting soon! minLength: 1 required: - text diff --git a/openapi/components/requests/CreateGroupGalleryRequest.yaml b/openapi/components/requests/CreateGroupGalleryRequest.yaml index 474e1033..b3011fc8 100644 --- a/openapi/components/requests/CreateGroupGalleryRequest.yaml +++ b/openapi/components/requests/CreateGroupGalleryRequest.yaml @@ -4,40 +4,43 @@ properties: description: type: string description: Description of the gallery. - example: Example Description + examples: + - Example Description minLength: 0 membersOnly: type: boolean description: Whether the gallery is members only. default: false - example: false + examples: + - false name: type: string description: Name of the gallery. - example: Example Gallery + examples: + - Example Gallery minLength: 1 roleIdsToAutoApprove: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml roleIdsToManage: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml roleIdsToSubmit: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml roleIdsToView: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml required: diff --git a/openapi/components/requests/CreateGroupPostRequest.yaml b/openapi/components/requests/CreateGroupPostRequest.yaml index c5ec3a22..11252e46 100644 --- a/openapi/components/requests/CreateGroupPostRequest.yaml +++ b/openapi/components/requests/CreateGroupPostRequest.yaml @@ -9,16 +9,19 @@ properties: type: boolean description: Send notification to group members. default: false - example: false + examples: + - false text: type: string description: Post text - example: Come join us for the event! + examples: + - Come join us for the event! minLength: 1 title: type: string description: Post title - example: Event is starting soon! + examples: + - Event is starting soon! minLength: 1 visibility: $ref: ../schemas/GroupPostVisibility.yaml diff --git a/openapi/components/requests/CreateGroupRequest.yaml b/openapi/components/requests/CreateGroupRequest.yaml index 94c5e75b..ee165cf9 100644 --- a/openapi/components/requests/CreateGroupRequest.yaml +++ b/openapi/components/requests/CreateGroupRequest.yaml @@ -2,16 +2,18 @@ title: CreateGroupRequest type: object properties: bannerId: - type: string - nullable: true + type: + - string + - "null" default: null description: type: string maxLength: 250 minLength: 0 iconId: - type: string - nullable: true + type: + - string + - "null" default: null joinState: $ref: ../schemas/GroupJoinState.yaml diff --git a/openapi/components/requests/CreateInstanceRequest.yaml b/openapi/components/requests/CreateInstanceRequest.yaml index d95396ed..e2a60910 100644 --- a/openapi/components/requests/CreateInstanceRequest.yaml +++ b/openapi/components/requests/CreateInstanceRequest.yaml @@ -29,16 +29,18 @@ properties: description: Currently unused, but will eventually be a flag to set if the closing of the instance should kick people. default: false instancePersistenceEnabled: - type: boolean - nullable: true + type: + - boolean + - "null" inviteOnly: type: boolean default: false ownerId: $ref: ../schemas/InstanceOwnerId.yaml playerPersistenceEnabled: - type: boolean - nullable: true + type: + - boolean + - "null" queueEnabled: type: boolean default: false diff --git a/openapi/components/requests/CreateJamSubmissionRequest.yaml b/openapi/components/requests/CreateJamSubmissionRequest.yaml index 721a0043..2ebc2a12 100644 --- a/openapi/components/requests/CreateJamSubmissionRequest.yaml +++ b/openapi/components/requests/CreateJamSubmissionRequest.yaml @@ -5,11 +5,13 @@ properties: contentId: type: string description: The id of the uploaded content (e.g., avatar, world) being submitted. - example: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 + examples: + - avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 description: type: string description: A description of the content being submitted. - example: My awesomely unique avatar for the jam! + examples: + - My awesomely unique avatar for the jam! required: - contentId - description diff --git a/openapi/components/requests/CreateWorldRequest.yaml b/openapi/components/requests/CreateWorldRequest.yaml index 71c7d53b..42564d55 100644 --- a/openapi/components/requests/CreateWorldRequest.yaml +++ b/openapi/components/requests/CreateWorldRequest.yaml @@ -14,7 +14,8 @@ properties: minLength: 1 capacity: type: integer - example: 8 + examples: + - 8 maximum: 40 minimum: 0 description: @@ -33,7 +34,6 @@ properties: $ref: ../schemas/ReleaseStatus.yaml tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml unityPackageUrl: @@ -42,7 +42,8 @@ properties: unityVersion: type: string default: 5.3.4p1 - example: 2022.3.6f1 + examples: + - 2022.3.6f1 minLength: 1 required: - assetUrl diff --git a/openapi/components/requests/FinishFileDataUploadRequest.yaml b/openapi/components/requests/FinishFileDataUploadRequest.yaml index 131c7d8c..f66bc725 100644 --- a/openapi/components/requests/FinishFileDataUploadRequest.yaml +++ b/openapi/components/requests/FinishFileDataUploadRequest.yaml @@ -1,6 +1,5 @@ title: FinishFileDataUploadRequest type: object -description: "" properties: etags: type: array @@ -14,7 +13,8 @@ properties: type: string description: "Always a zero in string form, despite how many parts uploaded." default: "0" - example: "0" + examples: + - "0" maxLength: 1 minLength: 1 nextPartNumber: @@ -22,7 +22,8 @@ properties: type: string description: "Always a zero in string form, despite how many parts uploaded." default: "0" - example: "0" + examples: + - "0" maxLength: 1 minLength: 1 required: diff --git a/openapi/components/requests/FollowCalendarEventRequest.yaml b/openapi/components/requests/FollowCalendarEventRequest.yaml index d77a610e..67e2c03b 100644 --- a/openapi/components/requests/FollowCalendarEventRequest.yaml +++ b/openapi/components/requests/FollowCalendarEventRequest.yaml @@ -3,6 +3,7 @@ type: object properties: isFollowing: type: boolean - example: true + examples: + - true required: - isFollowing diff --git a/openapi/components/requests/RequestInviteRequest.yaml b/openapi/components/requests/RequestInviteRequest.yaml index 32da1cf1..8c16e28b 100644 --- a/openapi/components/requests/RequestInviteRequest.yaml +++ b/openapi/components/requests/RequestInviteRequest.yaml @@ -5,5 +5,3 @@ properties: type: integer maximum: 11 minimum: 0 -required: - - instanceId diff --git a/openapi/components/requests/SubmitModerationReportRequest.yaml b/openapi/components/requests/SubmitModerationReportRequest.yaml index 978ddc43..5a6ba732 100644 --- a/openapi/components/requests/SubmitModerationReportRequest.yaml +++ b/openapi/components/requests/SubmitModerationReportRequest.yaml @@ -17,15 +17,18 @@ properties: category: type: string description: Valid values are the keys of the object `$.reportOptions[type]` from `GET /config`. Descriptions of these are found at `$.reportCategories[type]`. - example: behavior + examples: + - behavior contentId: type: string description: The id of the user, group, world, avatar, inventory item, print, etc. being reported. - example: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + examples: + - usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 description: type: string description: The subjective reason for the report - example: iz bulli + examples: + - iz bulli details: type: object description: |- @@ -57,11 +60,13 @@ properties: reason: type: string description: Valid values are the strings in the array `$.reportOptions[type][category]` from `GET /config`. Descriptions of these are found at `$.reportReasons[type]`. - example: child + examples: + - child type: type: string description: Valid values are the keys of the object `$.reportOptions` from `GET /config`. - example: user + examples: + - user required: - category - contentId diff --git a/openapi/components/requests/UpdateAvatarRequest.yaml b/openapi/components/requests/UpdateAvatarRequest.yaml index db2ffb90..0a40cafa 100644 --- a/openapi/components/requests/UpdateAvatarRequest.yaml +++ b/openapi/components/requests/UpdateAvatarRequest.yaml @@ -22,7 +22,6 @@ properties: $ref: ../schemas/ReleaseStatus.yaml tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml unityPackageUrl: @@ -30,7 +29,8 @@ properties: unityVersion: type: string default: 5.3.4p1 - example: 2022.3.6f1 + examples: + - 2022.3.6f1 minLength: 1 version: type: integer diff --git a/openapi/components/requests/UpdateCalendarEventRequest.yaml b/openapi/components/requests/UpdateCalendarEventRequest.yaml index ccbcf803..a9c54a63 100644 --- a/openapi/components/requests/UpdateCalendarEventRequest.yaml +++ b/openapi/components/requests/UpdateCalendarEventRequest.yaml @@ -3,10 +3,12 @@ type: object properties: category: type: string - example: performance + examples: + - performance closeInstanceAfterEndMinutes: type: integer - example: 5 + examples: + - 5 description: type: string minLength: 1 @@ -18,10 +20,12 @@ properties: type: boolean guestEarlyJoinMinutes: type: integer - example: 5 + examples: + - 5 hostEarlyJoinMinutes: type: integer - example: 60 + examples: + - 60 imageId: $ref: ../schemas/FileID.yaml isDraft: @@ -46,7 +50,8 @@ properties: type: boolean description: Send notification to group members. default: false - example: false + examples: + - false startsAt: type: string description: Time the vent starts at @@ -58,8 +63,10 @@ properties: title: type: string description: Event title - example: Performance Event! + examples: + - Performance Event! minLength: 1 usesInstanceOverflow: type: boolean - example: true + examples: + - true diff --git a/openapi/components/requests/UpdateGroupGalleryRequest.yaml b/openapi/components/requests/UpdateGroupGalleryRequest.yaml index 018d092b..ecddd603 100644 --- a/openapi/components/requests/UpdateGroupGalleryRequest.yaml +++ b/openapi/components/requests/UpdateGroupGalleryRequest.yaml @@ -4,39 +4,42 @@ properties: description: type: string description: Description of the gallery. - example: Example Description + examples: + - Example Description minLength: 0 membersOnly: type: boolean description: Whether the gallery is members only. default: false - example: false + examples: + - false name: type: string description: Name of the gallery. - example: Example Gallery + examples: + - Example Gallery minLength: 1 roleIdsToAutoApprove: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml roleIdsToManage: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml roleIdsToSubmit: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml roleIdsToView: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ../schemas/GroupRoleID.yaml diff --git a/openapi/components/requests/UpdateGroupRequest.yaml b/openapi/components/requests/UpdateGroupRequest.yaml index edac1f94..597299ef 100644 --- a/openapi/components/requests/UpdateGroupRequest.yaml +++ b/openapi/components/requests/UpdateGroupRequest.yaml @@ -2,16 +2,18 @@ title: UpdateGroupRequest type: object properties: bannerId: - type: string - nullable: true + type: + - string + - "null" default: null description: type: string maxLength: 250 minLength: 0 iconId: - type: string - nullable: true + type: + - string + - "null" default: null joinState: $ref: ../schemas/GroupJoinState.yaml @@ -31,6 +33,11 @@ properties: type: string maxLength: 64 minLength: 3 + nameplateId: + type: + - string + - "null" + default: null rules: type: string shortCode: @@ -39,6 +46,5 @@ properties: minLength: 3 tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml diff --git a/openapi/components/requests/UpdateInstanceRequest.yaml b/openapi/components/requests/UpdateInstanceRequest.yaml new file mode 100644 index 00000000..e32c1617 --- /dev/null +++ b/openapi/components/requests/UpdateInstanceRequest.yaml @@ -0,0 +1,10 @@ +title: UpdateInstanceRequest +type: object +properties: + calendarEntryId: + description: Calendar event to link to the instance. Send null to remove the current link. + anyOf: + - $ref: ../schemas/CalendarID.yaml + - type: "null" +required: + - calendarEntryId diff --git a/openapi/components/requests/UpdateProfileRequest.yaml b/openapi/components/requests/UpdateProfileRequest.yaml new file mode 100644 index 00000000..6936c633 --- /dev/null +++ b/openapi/components/requests/UpdateProfileRequest.yaml @@ -0,0 +1,40 @@ +title: UpdateProfileRequest +type: object +properties: + backgroundTextureId: + type: string + backgroundType: + type: string + enum: + - default + - gradient + - inventory + - texture + bannerColor: + $ref: ../schemas/Color.yaml + bannerType: + type: string + enum: + - avatarBanner + - color + - customImage + bio: + type: string + bioLinks: + type: array + items: + type: string + iconFrame: + $ref: ../schemas/InventoryTemplateID.yaml + languages: + type: array + items: + type: string + nameplateEffect: + $ref: ../schemas/InventoryTemplateID.yaml + profileEffect: + $ref: ../schemas/InventoryTemplateID.yaml + themeId: + type: string + userIcon: + type: string diff --git a/openapi/components/requests/UpdateUserClientConfigRequest.yaml b/openapi/components/requests/UpdateUserClientConfigRequest.yaml new file mode 100644 index 00000000..cd7791be --- /dev/null +++ b/openapi/components/requests/UpdateUserClientConfigRequest.yaml @@ -0,0 +1,6 @@ +title: UpdateUserClientConfigRequest +type: object +description: Only the settings named are changed. +properties: + accessReduceDecorAnim: + type: boolean diff --git a/openapi/components/requests/UpdateUserRequest.yaml b/openapi/components/requests/UpdateUserRequest.yaml index 5c3d3fb9..6f6178e5 100644 --- a/openapi/components/requests/UpdateUserRequest.yaml +++ b/openapi/components/requests/UpdateUserRequest.yaml @@ -3,13 +3,9 @@ type: object properties: acceptedTOSVersion: type: integer - bio: - type: string - minLength: 0 - bioLinks: - type: array - items: - type: string + allowWorldsToCountFriendsInInstance: + type: boolean + description: 'The "Allow Worlds to Count Friends in Instance" setting, introduced under [Udon Methods for Friend Info](https://ask.vrchat.com/t/developer-update-24-september-2026/48972#p-90922-udon-methods-for-friend-info-13) in the Developer Update of September 24, 2026.' birthday: type: string format: date @@ -49,13 +45,7 @@ properties: type: string tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml unsubscribe: type: boolean - userIcon: - type: string - description: MUST be a valid VRChat /file/ url. - example: "https://api.vrchat.cloud/api/1/file/file_76dc2964-0ce8-41df-b2e7-8edf994fee31/1" - minLength: 0 diff --git a/openapi/components/requests/UpdateWorldRequest.yaml b/openapi/components/requests/UpdateWorldRequest.yaml index d8ef5f1d..2174ddbc 100644 --- a/openapi/components/requests/UpdateWorldRequest.yaml +++ b/openapi/components/requests/UpdateWorldRequest.yaml @@ -14,7 +14,8 @@ properties: minLength: 1 capacity: type: integer - example: 8 + examples: + - 8 maximum: 40 minimum: 0 description: @@ -32,16 +33,17 @@ properties: platform: $ref: ../schemas/Platform.yaml previewYoutubeId: - type: string - nullable: true + type: + - string + - "null" recommendedCapacity: type: integer - example: 4 + examples: + - 4 releaseStatus: $ref: ../schemas/ReleaseStatus.yaml tags: type: array - description: " " items: $ref: ../schemas/Tag.yaml unityPackageUrl: @@ -50,7 +52,8 @@ properties: unityVersion: type: string default: 5.3.4p1 - example: 2022.3.6f1 + examples: + - 2022.3.6f1 minLength: 1 urlList: type: array diff --git a/openapi/components/responses/FeaturedSetNotAdminError.yaml b/openapi/components/responses/FeaturedSetNotAdminError.yaml index d124219b..6eb8b5df 100644 --- a/openapi/components/responses/FeaturedSetNotAdminError.yaml +++ b/openapi/components/responses/FeaturedSetNotAdminError.yaml @@ -1,11 +1,11 @@ -description: Error response when set featured to true without being an admin. -content: - application/json: - examples: - 401 Cannot Set Featured: - value: - error: - message: cannot set featured tag if you are not an admin - status_code: 401 - schema: - $ref: ../schemas/Error.yaml +description: Error response when set featured to true without being an admin. +content: + application/json: + examples: + 401 Cannot Set Featured: + value: + error: + message: cannot set featured tag if you are not an admin + status_code: 401 + schema: + $ref: ../schemas/Error.yaml diff --git a/openapi/components/responses/MissingCredentialsError.yaml b/openapi/components/responses/MissingCredentialsError.yaml index 7a38328b..2bbde961 100644 --- a/openapi/components/responses/MissingCredentialsError.yaml +++ b/openapi/components/responses/MissingCredentialsError.yaml @@ -1,11 +1,11 @@ -description: Error response due to missing auth cookie. -content: - application/json: - examples: - Missing Credentials Example: - value: - error: - message: '"Missing Credentials"' - status_code: 401 - schema: - $ref: ../schemas/Error.yaml +description: Error response due to missing auth cookie. +content: + application/json: + examples: + Missing Credentials Example: + value: + error: + message: '"Missing Credentials"' + status_code: 401 + schema: + $ref: ../schemas/Error.yaml diff --git a/openapi/components/responses/authentication/CheckUserExistsRateLimitError.yaml b/openapi/components/responses/authentication/CheckUserExistsRateLimitError.yaml new file mode 100644 index 00000000..c0f63d34 --- /dev/null +++ b/openapi/components/responses/authentication/CheckUserExistsRateLimitError.yaml @@ -0,0 +1 @@ +description: Error response when checking for users faster than the caller is allowed to. Carries no body. diff --git a/openapi/components/responses/authentication/ConfirmEmailResponse.yaml b/openapi/components/responses/authentication/ConfirmEmailResponse.yaml index 76253e62..0967ef42 100644 --- a/openapi/components/responses/authentication/ConfirmEmailResponse.yaml +++ b/openapi/components/responses/authentication/ConfirmEmailResponse.yaml @@ -1 +1 @@ -description: OK +{} diff --git a/openapi/components/responses/authentication/CreateAvatarModerationResponse.yaml b/openapi/components/responses/authentication/CreateAvatarModerationResponse.yaml index a19cc49d..ba93b5ca 100644 --- a/openapi/components/responses/authentication/CreateAvatarModerationResponse.yaml +++ b/openapi/components/responses/authentication/CreateAvatarModerationResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single AvatarModerationCreated object content: application/json: schema: diff --git a/openapi/components/responses/authentication/CurrentUserLoginResponse.yaml b/openapi/components/responses/authentication/CurrentUserLoginResponse.yaml index 74cd94c9..c263f73f 100644 --- a/openapi/components/responses/authentication/CurrentUserLoginResponse.yaml +++ b/openapi/components/responses/authentication/CurrentUserLoginResponse.yaml @@ -1,18 +1,14 @@ -description: OK content: application/json: schema: - x-if: - when: jsonschema - then: - oneOf: - - $ref: ../../schemas/CurrentUser.yaml - - $ref: ../../schemas/RequiresTwoFactorAuth.yaml - else: - $ref: ../../schemas/CurrentUser.yaml + title: CurrentUserLoginResponse + oneOf: + - $ref: ../../schemas/CurrentUser.yaml + - $ref: ../../schemas/RequiresTwoFactorAuth.yaml headers: Set-Cookie: description: Successful authentication returns an `auth` cookie. schema: type: string - example: "auth=authcookie_00000000-0000-0000-0000-000000000000; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly" + examples: + - "auth=authcookie_00000000-0000-0000-0000-000000000000; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly" diff --git a/openapi/components/responses/authentication/DeleteModerationReportResponse.yaml b/openapi/components/responses/authentication/DeleteModerationReportResponse.yaml index 147a9804..5db3cd4c 100644 --- a/openapi/components/responses/authentication/DeleteModerationReportResponse.yaml +++ b/openapi/components/responses/authentication/DeleteModerationReportResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an SuccessFlag object. content: application/json: schema: diff --git a/openapi/components/responses/authentication/DeleteUserResponse.yaml b/openapi/components/responses/authentication/DeleteUserResponse.yaml index beb41ee2..5dbb3f00 100644 --- a/openapi/components/responses/authentication/DeleteUserResponse.yaml +++ b/openapi/components/responses/authentication/DeleteUserResponse.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: schema: diff --git a/openapi/components/responses/authentication/Disable2FAResponse.yaml b/openapi/components/responses/authentication/Disable2FAResponse.yaml index 370bfaa8..50e79226 100644 --- a/openapi/components/responses/authentication/Disable2FAResponse.yaml +++ b/openapi/components/responses/authentication/Disable2FAResponse.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: schema: diff --git a/openapi/components/responses/authentication/GetInterestsAndPreferencesResponse.yaml b/openapi/components/responses/authentication/GetInterestsAndPreferencesResponse.yaml new file mode 100644 index 00000000..58115de5 --- /dev/null +++ b/openapi/components/responses/authentication/GetInterestsAndPreferencesResponse.yaml @@ -0,0 +1,26 @@ +content: + application/json: + examples: + All Off: + value: {} + All On: + value: + Anime: true + Art: true + Avatars: true + BigGroup: true + Explore: true + Fantasy: true + Fashion: true + FindAvatars: true + Furries: true + Horror: true + LanguageLearning: true + MeetPeople: true + Music: true + Mystery: true + SciFi: true + SmallGroup: true + Surprise: true + schema: + $ref: ../../schemas/InterestsAndPreferences.yaml diff --git a/openapi/components/responses/authentication/LogoutSuccess.yaml b/openapi/components/responses/authentication/LogoutSuccess.yaml index 48e6b72a..3e6157d9 100644 --- a/openapi/components/responses/authentication/LogoutSuccess.yaml +++ b/openapi/components/responses/authentication/LogoutSuccess.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: examples: diff --git a/openapi/components/responses/authentication/ModerationReportListResponse.yaml b/openapi/components/responses/authentication/ModerationReportListResponse.yaml index 57d3669f..28a7789f 100644 --- a/openapi/components/responses/authentication/ModerationReportListResponse.yaml +++ b/openapi/components/responses/authentication/ModerationReportListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of ModerationReport objects, wrapped in new pagination format. content: application/json: schema: diff --git a/openapi/components/responses/authentication/ModerationReportResponse.yaml b/openapi/components/responses/authentication/ModerationReportResponse.yaml index 48885acf..07b9938d 100644 --- a/openapi/components/responses/authentication/ModerationReportResponse.yaml +++ b/openapi/components/responses/authentication/ModerationReportResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single ModerationReport object. content: application/json: schema: diff --git a/openapi/components/responses/authentication/Pending2FAResponse.yaml b/openapi/components/responses/authentication/Pending2FAResponse.yaml index e5a64eb6..eec6a2b8 100644 --- a/openapi/components/responses/authentication/Pending2FAResponse.yaml +++ b/openapi/components/responses/authentication/Pending2FAResponse.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: schema: diff --git a/openapi/components/responses/authentication/ResendVerificationEmailSuccess.yaml b/openapi/components/responses/authentication/ResendVerificationEmailSuccess.yaml index c235cd89..de3d2387 100644 --- a/openapi/components/responses/authentication/ResendVerificationEmailSuccess.yaml +++ b/openapi/components/responses/authentication/ResendVerificationEmailSuccess.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: examples: diff --git a/openapi/components/responses/authentication/UpdateInterestsAndPreferencesParseError.yaml b/openapi/components/responses/authentication/UpdateInterestsAndPreferencesParseError.yaml new file mode 100644 index 00000000..1b93d91e --- /dev/null +++ b/openapi/components/responses/authentication/UpdateInterestsAndPreferencesParseError.yaml @@ -0,0 +1,11 @@ +description: The body is not a JSON object. +content: + application/json: + examples: + JSON Failed To Parse: + value: + error: + message: JSON failed to parse. + status_code: 400 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/authentication/UpdateInterestsAndPreferencesResponse.yaml b/openapi/components/responses/authentication/UpdateInterestsAndPreferencesResponse.yaml new file mode 100644 index 00000000..b4be3ec6 --- /dev/null +++ b/openapi/components/responses/authentication/UpdateInterestsAndPreferencesResponse.yaml @@ -0,0 +1,10 @@ +content: + application/json: + examples: + Update Interests And Preferences Success: + value: + success: + message: Interests and preferences updated! + status_code: 200 + schema: + $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/authentication/Verify2FAEmailCodeResponse.yaml b/openapi/components/responses/authentication/Verify2FAEmailCodeResponse.yaml index 3bed6b1c..7948b78b 100644 --- a/openapi/components/responses/authentication/Verify2FAEmailCodeResponse.yaml +++ b/openapi/components/responses/authentication/Verify2FAEmailCodeResponse.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: schema: @@ -8,4 +7,5 @@ headers: description: "Provides a `twoFactorAuth` cookie, which can be used to bypasses the 2FA requirement for future logins on the same device." schema: type: string - example: "twoFactorAuth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly" + examples: + - "twoFactorAuth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly" diff --git a/openapi/components/responses/authentication/Verify2FAResponse.yaml b/openapi/components/responses/authentication/Verify2FAResponse.yaml index 096f1525..6367fb34 100644 --- a/openapi/components/responses/authentication/Verify2FAResponse.yaml +++ b/openapi/components/responses/authentication/Verify2FAResponse.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: schema: @@ -8,4 +7,5 @@ headers: description: "Provides a `twoFactorAuth` cookie, which can be used to bypasses the 2FA requirement for future logins on the same device." schema: type: string - example: "twoFactorAuth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly" + examples: + - "twoFactorAuth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly" diff --git a/openapi/components/responses/authentication/VerifyLoginPlaceResponse.yaml b/openapi/components/responses/authentication/VerifyLoginPlaceResponse.yaml index 76253e62..0967ef42 100644 --- a/openapi/components/responses/authentication/VerifyLoginPlaceResponse.yaml +++ b/openapi/components/responses/authentication/VerifyLoginPlaceResponse.yaml @@ -1 +1 @@ -description: OK +{} diff --git a/openapi/components/responses/avatars/AvatarImpostorEnqueueResponse.yaml b/openapi/components/responses/avatars/AvatarImpostorEnqueueResponse.yaml index a18e74e1..a9a6a0bd 100644 --- a/openapi/components/responses/avatars/AvatarImpostorEnqueueResponse.yaml +++ b/openapi/components/responses/avatars/AvatarImpostorEnqueueResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a Service Status. content: application/json: schema: diff --git a/openapi/components/responses/avatars/AvatarListResponse.yaml b/openapi/components/responses/avatars/AvatarListResponse.yaml index f6a87371..39a12e9d 100644 --- a/openapi/components/responses/avatars/AvatarListResponse.yaml +++ b/openapi/components/responses/avatars/AvatarListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Avatar objects. content: application/json: schema: diff --git a/openapi/components/responses/avatars/AvatarResponse.yaml b/openapi/components/responses/avatars/AvatarResponse.yaml index c6f062c7..9e984256 100644 --- a/openapi/components/responses/avatars/AvatarResponse.yaml +++ b/openapi/components/responses/avatars/AvatarResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Avatar object. content: application/json: schema: diff --git a/openapi/components/responses/avatars/AvatarStyleListResponse.yaml b/openapi/components/responses/avatars/AvatarStyleListResponse.yaml index 27b5d862..72d2e8a3 100644 --- a/openapi/components/responses/avatars/AvatarStyleListResponse.yaml +++ b/openapi/components/responses/avatars/AvatarStyleListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of AvatarStyle objects. content: application/json: schema: diff --git a/openapi/components/responses/calendar/CalendarEventDiscoveryResponse.yaml b/openapi/components/responses/calendar/CalendarEventDiscoveryResponse.yaml index 649fc845..8f147338 100644 --- a/openapi/components/responses/calendar/CalendarEventDiscoveryResponse.yaml +++ b/openapi/components/responses/calendar/CalendarEventDiscoveryResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a CalendarEventDiscovery objects. content: application/json: schema: diff --git a/openapi/components/responses/calendar/CalendarEventListResponse.yaml b/openapi/components/responses/calendar/CalendarEventListResponse.yaml index 91f61fa3..ccc07e48 100644 --- a/openapi/components/responses/calendar/CalendarEventListResponse.yaml +++ b/openapi/components/responses/calendar/CalendarEventListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of CalendarEvent objects. content: application/json: schema: diff --git a/openapi/components/responses/calendar/CalendarEventResponse.yaml b/openapi/components/responses/calendar/CalendarEventResponse.yaml index 9c027806..cefa0113 100644 --- a/openapi/components/responses/calendar/CalendarEventResponse.yaml +++ b/openapi/components/responses/calendar/CalendarEventResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single CalendarEvent object. content: application/json: schema: diff --git a/openapi/components/responses/calendar/DeleteCalendarEventSuccess.yaml b/openapi/components/responses/calendar/DeleteCalendarEventSuccess.yaml index 56c2dd54..73bcad90 100644 --- a/openapi/components/responses/calendar/DeleteCalendarEventSuccess.yaml +++ b/openapi/components/responses/calendar/DeleteCalendarEventSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after deleting a calendar event. content: application/json: examples: diff --git a/openapi/components/responses/economy/BalanceResponse.yaml b/openapi/components/responses/economy/BalanceResponse.yaml index 8925555b..97b0e477 100644 --- a/openapi/components/responses/economy/BalanceResponse.yaml +++ b/openapi/components/responses/economy/BalanceResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Balance object. content: application/json: schema: diff --git a/openapi/components/responses/economy/BulkPurchasesListResponse.yaml b/openapi/components/responses/economy/BulkPurchasesListResponse.yaml index 21b9e242..ceeb8305 100644 --- a/openapi/components/responses/economy/BulkPurchasesListResponse.yaml +++ b/openapi/components/responses/economy/BulkPurchasesListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of ??? objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/DeleteProductListingResponse.yaml b/openapi/components/responses/economy/DeleteProductListingResponse.yaml index 147a9804..5db3cd4c 100644 --- a/openapi/components/responses/economy/DeleteProductListingResponse.yaml +++ b/openapi/components/responses/economy/DeleteProductListingResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an SuccessFlag object. content: application/json: schema: diff --git a/openapi/components/responses/economy/DeleteProductResponse.yaml b/openapi/components/responses/economy/DeleteProductResponse.yaml index 147a9804..5db3cd4c 100644 --- a/openapi/components/responses/economy/DeleteProductResponse.yaml +++ b/openapi/components/responses/economy/DeleteProductResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an SuccessFlag object. content: application/json: schema: diff --git a/openapi/components/responses/economy/EarningsMetricsResponse.yaml b/openapi/components/responses/economy/EarningsMetricsResponse.yaml index fd6e3de9..0279ceac 100644 --- a/openapi/components/responses/economy/EarningsMetricsResponse.yaml +++ b/openapi/components/responses/economy/EarningsMetricsResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single EarningsMetrics object. content: application/json: schema: diff --git a/openapi/components/responses/economy/EconomyAccountResponse.yaml b/openapi/components/responses/economy/EconomyAccountResponse.yaml index adb8e8cc..48b54d9f 100644 --- a/openapi/components/responses/economy/EconomyAccountResponse.yaml +++ b/openapi/components/responses/economy/EconomyAccountResponse.yaml @@ -1,5 +1,6 @@ -description: Returns a single EconomyAccount object. content: application/json: schema: - $ref: ../../schemas/EconomyAccount.yaml + anyOf: + - $ref: ../../schemas/EconomyAccount.yaml + - type: "null" diff --git a/openapi/components/responses/economy/EconomyBalancesResponse.yaml b/openapi/components/responses/economy/EconomyBalancesResponse.yaml index bc83db20..e45968b3 100644 --- a/openapi/components/responses/economy/EconomyBalancesResponse.yaml +++ b/openapi/components/responses/economy/EconomyBalancesResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an EconomyBalances object. content: application/json: schema: diff --git a/openapi/components/responses/economy/EconomyEarningsMetricsResponse.yaml b/openapi/components/responses/economy/EconomyEarningsMetricsResponse.yaml index fd421cf3..d9b54644 100644 --- a/openapi/components/responses/economy/EconomyEarningsMetricsResponse.yaml +++ b/openapi/components/responses/economy/EconomyEarningsMetricsResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an EconomyEarningsMetrics object. content: application/json: schema: diff --git a/openapi/components/responses/economy/EconomyPayoutListResponse.yaml b/openapi/components/responses/economy/EconomyPayoutListResponse.yaml index 3b4ed88c..e19a1cda 100644 --- a/openapi/components/responses/economy/EconomyPayoutListResponse.yaml +++ b/openapi/components/responses/economy/EconomyPayoutListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an EconomyPayoutList object. content: application/json: schema: diff --git a/openapi/components/responses/economy/EconomyPayoutStatusResponse.yaml b/openapi/components/responses/economy/EconomyPayoutStatusResponse.yaml index 7a786214..1fcd8294 100644 --- a/openapi/components/responses/economy/EconomyPayoutStatusResponse.yaml +++ b/openapi/components/responses/economy/EconomyPayoutStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an EconomyPayoutStatus object. content: application/json: schema: diff --git a/openapi/components/responses/economy/EconomyStatusResponse.yaml b/openapi/components/responses/economy/EconomyStatusResponse.yaml new file mode 100644 index 00000000..c1fa1380 --- /dev/null +++ b/openapi/components/responses/economy/EconomyStatusResponse.yaml @@ -0,0 +1,4 @@ +content: + application/json: + schema: + $ref: ../../schemas/EconomyStatus.yaml diff --git a/openapi/components/responses/economy/LicenseGroupResponse.yaml b/openapi/components/responses/economy/LicenseGroupResponse.yaml index ce2aabd4..35549b70 100644 --- a/openapi/components/responses/economy/LicenseGroupResponse.yaml +++ b/openapi/components/responses/economy/LicenseGroupResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single LicenseGroup object. content: application/json: schema: diff --git a/openapi/components/responses/economy/LicenseListResponse.yaml b/openapi/components/responses/economy/LicenseListResponse.yaml index 9e545d73..cbb7c907 100644 --- a/openapi/components/responses/economy/LicenseListResponse.yaml +++ b/openapi/components/responses/economy/LicenseListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of License objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductListResponse.yaml b/openapi/components/responses/economy/ProductListResponse.yaml index 81b2631f..4684d9b7 100644 --- a/openapi/components/responses/economy/ProductListResponse.yaml +++ b/openapi/components/responses/economy/ProductListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Product objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductListingListResponse.yaml b/openapi/components/responses/economy/ProductListingListResponse.yaml index 4a3eaef9..09bc1c44 100644 --- a/openapi/components/responses/economy/ProductListingListResponse.yaml +++ b/openapi/components/responses/economy/ProductListingListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of ProductListing objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductListingResponse.yaml b/openapi/components/responses/economy/ProductListingResponse.yaml index 5ea51ebc..eeb302bd 100644 --- a/openapi/components/responses/economy/ProductListingResponse.yaml +++ b/openapi/components/responses/economy/ProductListingResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single ProductListing object. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductPurchaseHistoryResponse.yaml b/openapi/components/responses/economy/ProductPurchaseHistoryResponse.yaml index 349e57e0..b50ef279 100644 --- a/openapi/components/responses/economy/ProductPurchaseHistoryResponse.yaml +++ b/openapi/components/responses/economy/ProductPurchaseHistoryResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single ProductPurchaseHistory object. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductPurchaseListResponse.yaml b/openapi/components/responses/economy/ProductPurchaseListResponse.yaml index 76d63c21..042494fa 100644 --- a/openapi/components/responses/economy/ProductPurchaseListResponse.yaml +++ b/openapi/components/responses/economy/ProductPurchaseListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of ProductPurchase objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductPurchaseResponse.yaml b/openapi/components/responses/economy/ProductPurchaseResponse.yaml index 4bcf1441..cc0e2cd8 100644 --- a/openapi/components/responses/economy/ProductPurchaseResponse.yaml +++ b/openapi/components/responses/economy/ProductPurchaseResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single ProductPurchase object. content: application/json: schema: diff --git a/openapi/components/responses/economy/ProductResponse.yaml b/openapi/components/responses/economy/ProductResponse.yaml index 9f069dfc..03a71d54 100644 --- a/openapi/components/responses/economy/ProductResponse.yaml +++ b/openapi/components/responses/economy/ProductResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Product object. content: application/json: schema: diff --git a/openapi/components/responses/economy/SellerEligibilityResponse.yaml b/openapi/components/responses/economy/SellerEligibilityResponse.yaml index 77b54d4c..70153ca8 100644 --- a/openapi/components/responses/economy/SellerEligibilityResponse.yaml +++ b/openapi/components/responses/economy/SellerEligibilityResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single SellerEligibility object. content: application/json: schema: diff --git a/openapi/components/responses/economy/StoreListResponse.yaml b/openapi/components/responses/economy/StoreListResponse.yaml index 75c8b201..f9159595 100644 --- a/openapi/components/responses/economy/StoreListResponse.yaml +++ b/openapi/components/responses/economy/StoreListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Store objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/StoreResponse.yaml b/openapi/components/responses/economy/StoreResponse.yaml index 500c5b10..bf02262a 100644 --- a/openapi/components/responses/economy/StoreResponse.yaml +++ b/openapi/components/responses/economy/StoreResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Store object. content: application/json: schema: diff --git a/openapi/components/responses/economy/StoreShelfListResponse.yaml b/openapi/components/responses/economy/StoreShelfListResponse.yaml index 53bee7d0..08dea75f 100644 --- a/openapi/components/responses/economy/StoreShelfListResponse.yaml +++ b/openapi/components/responses/economy/StoreShelfListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of StoreShelf objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/SubscriptionListResponse.yaml b/openapi/components/responses/economy/SubscriptionListResponse.yaml index a875f4da..bae09ebd 100644 --- a/openapi/components/responses/economy/SubscriptionListResponse.yaml +++ b/openapi/components/responses/economy/SubscriptionListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Subscription objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/TiliaKycResponse.yaml b/openapi/components/responses/economy/TiliaKycResponse.yaml index ef182291..635db09e 100644 --- a/openapi/components/responses/economy/TiliaKycResponse.yaml +++ b/openapi/components/responses/economy/TiliaKycResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a TiliaKyc object. content: application/json: schema: diff --git a/openapi/components/responses/economy/TiliaStatusResponse.yaml b/openapi/components/responses/economy/TiliaStatusResponse.yaml index 514559df..53d039c4 100644 --- a/openapi/components/responses/economy/TiliaStatusResponse.yaml +++ b/openapi/components/responses/economy/TiliaStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single TiliaStatus object. content: application/json: schema: diff --git a/openapi/components/responses/economy/TiliaTOSResponse.yaml b/openapi/components/responses/economy/TiliaTOSResponse.yaml index cffce496..5886bd16 100644 --- a/openapi/components/responses/economy/TiliaTOSResponse.yaml +++ b/openapi/components/responses/economy/TiliaTOSResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single TiliaTOS object. content: application/json: schema: diff --git a/openapi/components/responses/economy/TokenBundleListResponse.yaml b/openapi/components/responses/economy/TokenBundleListResponse.yaml index 5018d78f..c494dac9 100644 --- a/openapi/components/responses/economy/TokenBundleListResponse.yaml +++ b/openapi/components/responses/economy/TokenBundleListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of TokenBundle objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/TransactionListResponse.yaml b/openapi/components/responses/economy/TransactionListResponse.yaml index 0beefbc1..9c41e48f 100644 --- a/openapi/components/responses/economy/TransactionListResponse.yaml +++ b/openapi/components/responses/economy/TransactionListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Transaction objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/TransactionResponse.yaml b/openapi/components/responses/economy/TransactionResponse.yaml index 0e31fd19..a514a705 100644 --- a/openapi/components/responses/economy/TransactionResponse.yaml +++ b/openapi/components/responses/economy/TransactionResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Transaction object. content: application/json: schema: diff --git a/openapi/components/responses/economy/UpdateTiliaTOSResponse.yaml b/openapi/components/responses/economy/UpdateTiliaTOSResponse.yaml index 2a61250d..d95fb21f 100644 --- a/openapi/components/responses/economy/UpdateTiliaTOSResponse.yaml +++ b/openapi/components/responses/economy/UpdateTiliaTOSResponse.yaml @@ -1,6 +1,6 @@ -description: Returns a UserSubscription object. content: application/json: schema: - type: object - nullable: true + type: + - object + - "null" diff --git a/openapi/components/responses/economy/UserCreditsEligibleResponse.yaml b/openapi/components/responses/economy/UserCreditsEligibleResponse.yaml index 84544c6c..809c9e73 100644 --- a/openapi/components/responses/economy/UserCreditsEligibleResponse.yaml +++ b/openapi/components/responses/economy/UserCreditsEligibleResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single UserCreditsEligible object. content: application/json: schema: diff --git a/openapi/components/responses/economy/UserEconomyTransactionsResponse.yaml b/openapi/components/responses/economy/UserEconomyTransactionsResponse.yaml index 73686560..0ef59c88 100644 --- a/openapi/components/responses/economy/UserEconomyTransactionsResponse.yaml +++ b/openapi/components/responses/economy/UserEconomyTransactionsResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a UserEconomyTransactions object. content: application/json: schema: diff --git a/openapi/components/responses/economy/UserSubscriptionEligibleResponse.yaml b/openapi/components/responses/economy/UserSubscriptionEligibleResponse.yaml index 2e4c142a..dddce475 100644 --- a/openapi/components/responses/economy/UserSubscriptionEligibleResponse.yaml +++ b/openapi/components/responses/economy/UserSubscriptionEligibleResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single UserSubscriptionEligible object. content: application/json: schema: diff --git a/openapi/components/responses/economy/UserSubscriptionListResponse.yaml b/openapi/components/responses/economy/UserSubscriptionListResponse.yaml index b1a96145..d587aafe 100644 --- a/openapi/components/responses/economy/UserSubscriptionListResponse.yaml +++ b/openapi/components/responses/economy/UserSubscriptionListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of UserSubscription objects. content: application/json: schema: diff --git a/openapi/components/responses/economy/UserSubscriptionResponse.yaml b/openapi/components/responses/economy/UserSubscriptionResponse.yaml index 889e42ca..587d6a06 100644 --- a/openapi/components/responses/economy/UserSubscriptionResponse.yaml +++ b/openapi/components/responses/economy/UserSubscriptionResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a UserSubscription object. content: application/json: schema: diff --git a/openapi/components/responses/favorites/FavoriteAddAlreadyFavoritedError.yaml b/openapi/components/responses/favorites/FavoriteAddAlreadyFavoritedError.yaml index ef8435ec..06a3c2b8 100644 --- a/openapi/components/responses/favorites/FavoriteAddAlreadyFavoritedError.yaml +++ b/openapi/components/responses/favorites/FavoriteAddAlreadyFavoritedError.yaml @@ -1,11 +1,11 @@ -description: Error response when trying favorite someone or something when already having it/them favorited. -content: - application/json: - examples: - 400 Already Favorited That Friend: - value: - error: - message: You already have that friend favorited - status_code: 400 - schema: +description: Error response when trying favorite someone or something when already having it/them favorited. +content: + application/json: + examples: + 400 Already Favorited That Friend: + value: + error: + message: You already have that friend favorited + status_code: 400 + schema: $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/favorites/FavoriteAddNotFriendsError.yaml b/openapi/components/responses/favorites/FavoriteAddNotFriendsError.yaml index a447ab9e..b52b6bde 100644 --- a/openapi/components/responses/favorites/FavoriteAddNotFriendsError.yaml +++ b/openapi/components/responses/favorites/FavoriteAddNotFriendsError.yaml @@ -1,11 +1,11 @@ -description: Error response when trying favorite someone whom you are not friends with. -content: - application/json: - examples: - 403 Favorite Add Not Friends Error: - value: - error: - message: you are not friends with that userǃ - status_code: 403 - schema: +description: Error response when trying favorite someone whom you are not friends with. +content: + application/json: + examples: + 403 Favorite Add Not Friends Error: + value: + error: + message: you are not friends with that userǃ + status_code: 403 + schema: $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/favorites/FavoriteGroupClearedSuccess.yaml b/openapi/components/responses/favorites/FavoriteGroupClearedSuccess.yaml index 557f20ba..d294de4d 100644 --- a/openapi/components/responses/favorites/FavoriteGroupClearedSuccess.yaml +++ b/openapi/components/responses/favorites/FavoriteGroupClearedSuccess.yaml @@ -1,11 +1,11 @@ -description: Success response after clearing a favorite group. -content: - application/json: - examples: - 200 Favorite Group Cleared: - value: - success: - message: favorite deleted! - status_code: 200 - schema: +description: Success response after clearing a favorite group. +content: + application/json: + examples: + 200 Favorite Group Cleared: + value: + success: + message: favorite deleted! + status_code: 200 + schema: $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/favorites/FavoriteGroupContentsResponse.yaml b/openapi/components/responses/favorites/FavoriteGroupContentsResponse.yaml new file mode 100644 index 00000000..b4be9bab --- /dev/null +++ b/openapi/components/responses/favorites/FavoriteGroupContentsResponse.yaml @@ -0,0 +1,5 @@ +description: Returns the favorites in a group, each alongside the object it points at. +content: + application/json: + schema: + $ref: ../../schemas/FavoriteGroupContents.yaml diff --git a/openapi/components/responses/favorites/FavoriteGroupListResponse.yaml b/openapi/components/responses/favorites/FavoriteGroupListResponse.yaml index ca68f4b7..1f61be9a 100644 --- a/openapi/components/responses/favorites/FavoriteGroupListResponse.yaml +++ b/openapi/components/responses/favorites/FavoriteGroupListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of FavoriteGroup objects. content: application/json: schema: diff --git a/openapi/components/responses/favorites/FavoriteGroupResponse.yaml b/openapi/components/responses/favorites/FavoriteGroupResponse.yaml index e8dee2ae..8cbb885f 100644 --- a/openapi/components/responses/favorites/FavoriteGroupResponse.yaml +++ b/openapi/components/responses/favorites/FavoriteGroupResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single FavoriteGroup object. content: application/json: schema: diff --git a/openapi/components/responses/favorites/FavoriteGroupsByTypeResponse.yaml b/openapi/components/responses/favorites/FavoriteGroupsByTypeResponse.yaml new file mode 100644 index 00000000..f140679f --- /dev/null +++ b/openapi/components/responses/favorites/FavoriteGroupsByTypeResponse.yaml @@ -0,0 +1,4 @@ +content: + application/json: + schema: + $ref: ../../schemas/FavoriteGroupList.yaml diff --git a/openapi/components/responses/favorites/FavoriteLimitsResponse.yaml b/openapi/components/responses/favorites/FavoriteLimitsResponse.yaml index 62d4fe56..2d963b1f 100644 --- a/openapi/components/responses/favorites/FavoriteLimitsResponse.yaml +++ b/openapi/components/responses/favorites/FavoriteLimitsResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single FavoriteLimits object. content: application/json: schema: diff --git a/openapi/components/responses/favorites/FavoriteListResponse.yaml b/openapi/components/responses/favorites/FavoriteListResponse.yaml index b0d23a56..3eed52c8 100644 --- a/openapi/components/responses/favorites/FavoriteListResponse.yaml +++ b/openapi/components/responses/favorites/FavoriteListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Favorite objects. content: application/json: schema: diff --git a/openapi/components/responses/favorites/FavoriteRemovedSuccess.yaml b/openapi/components/responses/favorites/FavoriteRemovedSuccess.yaml index 0a46b1df..35ee5146 100644 --- a/openapi/components/responses/favorites/FavoriteRemovedSuccess.yaml +++ b/openapi/components/responses/favorites/FavoriteRemovedSuccess.yaml @@ -1,11 +1,11 @@ -description: Success response after removing a favorite. -content: - application/json: - examples: - 200 Favorite Removed: - value: - success: - message: favorite deleted! - status_code: 200 - schema: +description: Success response after removing a favorite. +content: + application/json: + examples: + 200 Favorite Removed: + value: + success: + message: favorite deleted! + status_code: 200 + schema: $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/favorites/FavoriteResponse.yaml b/openapi/components/responses/favorites/FavoriteResponse.yaml index 72802592..d7969ae0 100644 --- a/openapi/components/responses/favorites/FavoriteResponse.yaml +++ b/openapi/components/responses/favorites/FavoriteResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Favorite object. content: application/json: schema: diff --git a/openapi/components/responses/favorites/UpdateFavoriteGroupResponse.yaml b/openapi/components/responses/favorites/UpdateFavoriteGroupResponse.yaml new file mode 100644 index 00000000..47966143 --- /dev/null +++ b/openapi/components/responses/favorites/UpdateFavoriteGroupResponse.yaml @@ -0,0 +1,7 @@ +content: + application/json: + examples: + Updated: + value: {} + schema: + type: object diff --git a/openapi/components/responses/files/AdminAssetBundleResponse.yaml b/openapi/components/responses/files/AdminAssetBundleResponse.yaml index 181dcaeb..15db6f8c 100644 --- a/openapi/components/responses/files/AdminAssetBundleResponse.yaml +++ b/openapi/components/responses/files/AdminAssetBundleResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single AdminAssetBundle object. content: application/json: schema: diff --git a/openapi/components/responses/files/AgreementResponse.yaml b/openapi/components/responses/files/AgreementResponse.yaml index bba0ffd6..9f712684 100644 --- a/openapi/components/responses/files/AgreementResponse.yaml +++ b/openapi/components/responses/files/AgreementResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Agreement object. content: application/json: schema: diff --git a/openapi/components/responses/files/AgreementStatusResponse.yaml b/openapi/components/responses/files/AgreementStatusResponse.yaml index 762b4551..e20adfd7 100644 --- a/openapi/components/responses/files/AgreementStatusResponse.yaml +++ b/openapi/components/responses/files/AgreementStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single AgreementStatus object. content: application/json: schema: diff --git a/openapi/components/responses/files/FileAnalysisResponse.yaml b/openapi/components/responses/files/FileAnalysisResponse.yaml index 968d1683..c9d11f9d 100644 --- a/openapi/components/responses/files/FileAnalysisResponse.yaml +++ b/openapi/components/responses/files/FileAnalysisResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single FileAnalysis object. content: application/json: schema: diff --git a/openapi/components/responses/files/FileListResponse.yaml b/openapi/components/responses/files/FileListResponse.yaml index a867831c..f5edc993 100644 --- a/openapi/components/responses/files/FileListResponse.yaml +++ b/openapi/components/responses/files/FileListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of File objects. content: application/json: schema: diff --git a/openapi/components/responses/files/FileResponse.yaml b/openapi/components/responses/files/FileResponse.yaml index 440cc5a0..ed8c3fff 100644 --- a/openapi/components/responses/files/FileResponse.yaml +++ b/openapi/components/responses/files/FileResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single File object. content: application/json: examples: diff --git a/openapi/components/responses/friends/BoopSuccess.yaml b/openapi/components/responses/friends/BoopSuccess.yaml index f63c0d59..332aea2b 100644 --- a/openapi/components/responses/friends/BoopSuccess.yaml +++ b/openapi/components/responses/friends/BoopSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after booping a user. content: application/json: examples: diff --git a/openapi/components/responses/friends/DeleteFriendSuccess.yaml b/openapi/components/responses/friends/DeleteFriendSuccess.yaml index f7006dca..4f03d043 100644 --- a/openapi/components/responses/friends/DeleteFriendSuccess.yaml +++ b/openapi/components/responses/friends/DeleteFriendSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after cancelling a friend request. content: application/json: examples: diff --git a/openapi/components/responses/friends/FriendRateLimitError.yaml b/openapi/components/responses/friends/FriendRateLimitError.yaml new file mode 100644 index 00000000..812633bc --- /dev/null +++ b/openapi/components/responses/friends/FriendRateLimitError.yaml @@ -0,0 +1,11 @@ +description: Error response when sending friend requests faster than the account is allowed to. +content: + application/json: + examples: + Too Many Friend Requests: + value: + error: + message: You are making too many friend requests + status_code: 429 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/friends/FriendStatusResponse.yaml b/openapi/components/responses/friends/FriendStatusResponse.yaml index 590e2c10..cdecfaa9 100644 --- a/openapi/components/responses/friends/FriendStatusResponse.yaml +++ b/openapi/components/responses/friends/FriendStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a users Friend Status. content: application/json: examples: diff --git a/openapi/components/responses/friends/FriendSuccess.yaml b/openapi/components/responses/friends/FriendSuccess.yaml index e97e16e6..38b80d52 100644 --- a/openapi/components/responses/friends/FriendSuccess.yaml +++ b/openapi/components/responses/friends/FriendSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after friending a user. content: application/json: examples: diff --git a/openapi/components/responses/friends/LimitedUserFriendListResponse.yaml b/openapi/components/responses/friends/LimitedUserFriendListResponse.yaml index 4609b58d..c3fd6d10 100644 --- a/openapi/components/responses/friends/LimitedUserFriendListResponse.yaml +++ b/openapi/components/responses/friends/LimitedUserFriendListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of LimitedUserFriend objects. content: application/json: schema: diff --git a/openapi/components/responses/friends/UnfriendSuccess.yaml b/openapi/components/responses/friends/UnfriendSuccess.yaml index d210c415..32904a13 100644 --- a/openapi/components/responses/friends/UnfriendSuccess.yaml +++ b/openapi/components/responses/friends/UnfriendSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after unfriending a user. content: application/json: examples: diff --git a/openapi/components/responses/groups/BlockGroupSuccess.yaml b/openapi/components/responses/groups/BlockGroupSuccess.yaml index 0236244e..c4a98b3f 100644 --- a/openapi/components/responses/groups/BlockGroupSuccess.yaml +++ b/openapi/components/responses/groups/BlockGroupSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after blocking a Group. content: application/json: examples: diff --git a/openapi/components/responses/groups/CreateGroupInviteSuccess.yaml b/openapi/components/responses/groups/CreateGroupInviteSuccess.yaml new file mode 100644 index 00000000..c5cc00f0 --- /dev/null +++ b/openapi/components/responses/groups/CreateGroupInviteSuccess.yaml @@ -0,0 +1,10 @@ +content: + application/json: + examples: + Invited: + value: + success: + message: VRChatWiki has been invited! + status_code: 200 + schema: + $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/groups/DeclineGroupInviteSuccess.yaml b/openapi/components/responses/groups/DeclineGroupInviteSuccess.yaml index b3dd5e79..597edb6a 100644 --- a/openapi/components/responses/groups/DeclineGroupInviteSuccess.yaml +++ b/openapi/components/responses/groups/DeclineGroupInviteSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after declining a group invite. content: application/json: examples: diff --git a/openapi/components/responses/groups/DeleteGroupAnnouncementSuccess.yaml b/openapi/components/responses/groups/DeleteGroupAnnouncementSuccess.yaml index 076d868f..9e6c6000 100644 --- a/openapi/components/responses/groups/DeleteGroupAnnouncementSuccess.yaml +++ b/openapi/components/responses/groups/DeleteGroupAnnouncementSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after deleting/clearing the group announcement. content: application/json: examples: diff --git a/openapi/components/responses/groups/DeleteGroupGalleryImageSuccess.yaml b/openapi/components/responses/groups/DeleteGroupGalleryImageSuccess.yaml index f1fd932b..d7ff2492 100644 --- a/openapi/components/responses/groups/DeleteGroupGalleryImageSuccess.yaml +++ b/openapi/components/responses/groups/DeleteGroupGalleryImageSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after deleting a group gallery image. content: application/json: examples: diff --git a/openapi/components/responses/groups/DeleteGroupGallerySuccess.yaml b/openapi/components/responses/groups/DeleteGroupGallerySuccess.yaml index f6eb0cf0..07e00fd3 100644 --- a/openapi/components/responses/groups/DeleteGroupGallerySuccess.yaml +++ b/openapi/components/responses/groups/DeleteGroupGallerySuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after deleting a group gallery. content: application/json: examples: diff --git a/openapi/components/responses/groups/DeleteGroupInviteSuccess.yaml b/openapi/components/responses/groups/DeleteGroupInviteSuccess.yaml new file mode 100644 index 00000000..4ee68c8a --- /dev/null +++ b/openapi/components/responses/groups/DeleteGroupInviteSuccess.yaml @@ -0,0 +1,10 @@ +content: + application/json: + examples: + Uninvited: + value: + success: + message: VRChatWiki has been uninvited. + status_code: 200 + schema: + $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/groups/DeleteGroupMemberSuccess.yaml b/openapi/components/responses/groups/DeleteGroupMemberSuccess.yaml index d6d445b3..c487cc78 100644 --- a/openapi/components/responses/groups/DeleteGroupMemberSuccess.yaml +++ b/openapi/components/responses/groups/DeleteGroupMemberSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after deleting a group member. content: application/json: examples: diff --git a/openapi/components/responses/groups/DeleteGroupSuccess.yaml b/openapi/components/responses/groups/DeleteGroupSuccess.yaml index a85f3762..59ec5c5e 100644 --- a/openapi/components/responses/groups/DeleteGroupSuccess.yaml +++ b/openapi/components/responses/groups/DeleteGroupSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after deleting a Group. content: application/json: examples: diff --git a/openapi/components/responses/groups/GetGroupMemberResponse.yaml b/openapi/components/responses/groups/GetGroupMemberResponse.yaml new file mode 100644 index 00000000..94e50cb6 --- /dev/null +++ b/openapi/components/responses/groups/GetGroupMemberResponse.yaml @@ -0,0 +1,7 @@ +description: Returns a single GroupMember object, or `null` when the user is not a member of the group. +content: + application/json: + schema: + anyOf: + - $ref: ../../schemas/GroupMember.yaml + - type: "null" diff --git a/openapi/components/responses/groups/GroupAnnouncementResponse.yaml b/openapi/components/responses/groups/GroupAnnouncementResponse.yaml index 96a68208..4ed2f52c 100644 --- a/openapi/components/responses/groups/GroupAnnouncementResponse.yaml +++ b/openapi/components/responses/groups/GroupAnnouncementResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single GroupAnnouncement object. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupAuditLogEntryTypeListResponse.yaml b/openapi/components/responses/groups/GroupAuditLogEntryTypeListResponse.yaml index 86e76ba8..99208f60 100644 --- a/openapi/components/responses/groups/GroupAuditLogEntryTypeListResponse.yaml +++ b/openapi/components/responses/groups/GroupAuditLogEntryTypeListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupAuditLogEntryTypes. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupAuditLogListResponse.yaml b/openapi/components/responses/groups/GroupAuditLogListResponse.yaml index 96480c6b..0015c47e 100644 --- a/openapi/components/responses/groups/GroupAuditLogListResponse.yaml +++ b/openapi/components/responses/groups/GroupAuditLogListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupAudit objects, wrapped in new pagination format. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupGalleryFileOrderResponse.yaml b/openapi/components/responses/groups/GroupGalleryFileOrderResponse.yaml index 134a8e9f..6b866e1f 100644 --- a/openapi/components/responses/groups/GroupGalleryFileOrderResponse.yaml +++ b/openapi/components/responses/groups/GroupGalleryFileOrderResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of File IDs. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupGalleryImageListResponse.yaml b/openapi/components/responses/groups/GroupGalleryImageListResponse.yaml index dd1eced4..4dd5bd91 100644 --- a/openapi/components/responses/groups/GroupGalleryImageListResponse.yaml +++ b/openapi/components/responses/groups/GroupGalleryImageListResponse.yaml @@ -1,7 +1,10 @@ -description: Returns a list of GroupGalleryImage objects. +description: Returns a list of GroupGalleryImage objects, wrapped in a paginated object when `v` is `2`. content: application/json: schema: - type: array - items: - $ref: ../../schemas/GroupGalleryImage.yaml + title: GroupGalleryImageListResponse + oneOf: + - type: array + items: + $ref: ../../schemas/GroupGalleryImage.yaml + - $ref: ../../schemas/GroupGalleryImageList.yaml diff --git a/openapi/components/responses/groups/GroupGalleryImageResponse.yaml b/openapi/components/responses/groups/GroupGalleryImageResponse.yaml index 52e7be4c..b669cedb 100644 --- a/openapi/components/responses/groups/GroupGalleryImageResponse.yaml +++ b/openapi/components/responses/groups/GroupGalleryImageResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single GroupGalleryImage object. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupGalleryResponse.yaml b/openapi/components/responses/groups/GroupGalleryResponse.yaml index 04fddbbd..54de10d8 100644 --- a/openapi/components/responses/groups/GroupGalleryResponse.yaml +++ b/openapi/components/responses/groups/GroupGalleryResponse.yaml @@ -1,5 +1,4 @@ -description: Returns a single GroupGallery object. -content: - application/json: - schema: +content: + application/json: + schema: $ref: ../../schemas/GroupGallery.yaml diff --git a/openapi/components/responses/groups/GroupInstanceListResponse.yaml b/openapi/components/responses/groups/GroupInstanceListResponse.yaml index 5416caab..693e29dd 100644 --- a/openapi/components/responses/groups/GroupInstanceListResponse.yaml +++ b/openapi/components/responses/groups/GroupInstanceListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupInstance objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupListResponse.yaml b/openapi/components/responses/groups/GroupListResponse.yaml index 85e55277..d4832660 100644 --- a/openapi/components/responses/groups/GroupListResponse.yaml +++ b/openapi/components/responses/groups/GroupListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Group objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupMemberListResponse.yaml b/openapi/components/responses/groups/GroupMemberListResponse.yaml index f5f373af..76b264be 100644 --- a/openapi/components/responses/groups/GroupMemberListResponse.yaml +++ b/openapi/components/responses/groups/GroupMemberListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupMember objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupMemberResponse.yaml b/openapi/components/responses/groups/GroupMemberResponse.yaml index ad032a52..088787e7 100644 --- a/openapi/components/responses/groups/GroupMemberResponse.yaml +++ b/openapi/components/responses/groups/GroupMemberResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupMember objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupMemberSearchResponse.yaml b/openapi/components/responses/groups/GroupMemberSearchResponse.yaml index 2676e57c..69d2524a 100644 --- a/openapi/components/responses/groups/GroupMemberSearchResponse.yaml +++ b/openapi/components/responses/groups/GroupMemberSearchResponse.yaml @@ -1,7 +1,7 @@ -description: Returns a list of GroupMember objects from a search. content: application/json: schema: + title: GroupMemberSearchResponse type: object properties: results: diff --git a/openapi/components/responses/groups/GroupNotMemberError.yaml b/openapi/components/responses/groups/GroupNotMemberError.yaml index fe37ac0e..538dc828 100644 --- a/openapi/components/responses/groups/GroupNotMemberError.yaml +++ b/openapi/components/responses/groups/GroupNotMemberError.yaml @@ -1,11 +1,11 @@ -description: Error response when trying to perform operations on a group you are not member of. -content: - application/json: - examples: - 403 Not Group Member: - value: - error: - message: You're not a member. - status_code: 403 - schema: +description: Error response when trying to perform operations on a group you are not member of. +content: + application/json: + examples: + 403 Not Group Member: + value: + error: + message: You're not a member. + status_code: 403 + schema: $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/groups/GroupPermissionListResponse.yaml b/openapi/components/responses/groups/GroupPermissionListResponse.yaml index 263a3644..31db6939 100644 --- a/openapi/components/responses/groups/GroupPermissionListResponse.yaml +++ b/openapi/components/responses/groups/GroupPermissionListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupPermission objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupPostResponse.yaml b/openapi/components/responses/groups/GroupPostResponse.yaml index 519a2f4d..8c8ace96 100644 --- a/openapi/components/responses/groups/GroupPostResponse.yaml +++ b/openapi/components/responses/groups/GroupPostResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a GroupPost object. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupPostResponseSuccess.yaml b/openapi/components/responses/groups/GroupPostResponseSuccess.yaml index cba7432d..2ff19f7a 100644 --- a/openapi/components/responses/groups/GroupPostResponseSuccess.yaml +++ b/openapi/components/responses/groups/GroupPostResponseSuccess.yaml @@ -1,4 +1,3 @@ -description: Response after deleting a group post. content: application/json: examples: diff --git a/openapi/components/responses/groups/GroupPostsResponse.yaml b/openapi/components/responses/groups/GroupPostsResponse.yaml index d19c03b1..bf51bdcb 100644 --- a/openapi/components/responses/groups/GroupPostsResponse.yaml +++ b/openapi/components/responses/groups/GroupPostsResponse.yaml @@ -1,7 +1,7 @@ -description: Returns a GroupPost Array. content: application/json: schema: + title: GroupPostsResponse type: object properties: posts: diff --git a/openapi/components/responses/groups/GroupResponse.yaml b/openapi/components/responses/groups/GroupResponse.yaml index 9c29228d..6980a85a 100644 --- a/openapi/components/responses/groups/GroupResponse.yaml +++ b/openapi/components/responses/groups/GroupResponse.yaml @@ -1,5 +1,4 @@ -description: Returns a single Group object. -content: - application/json: - schema: +content: + application/json: + schema: $ref: ../../schemas/Group.yaml diff --git a/openapi/components/responses/groups/GroupRoleIDListResponse.yaml b/openapi/components/responses/groups/GroupRoleIDListResponse.yaml index 396b88d2..4d42dcd5 100644 --- a/openapi/components/responses/groups/GroupRoleIDListResponse.yaml +++ b/openapi/components/responses/groups/GroupRoleIDListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupRoleID objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupRoleListResponse.yaml b/openapi/components/responses/groups/GroupRoleListResponse.yaml index e5e4a216..2d8b8ae2 100644 --- a/openapi/components/responses/groups/GroupRoleListResponse.yaml +++ b/openapi/components/responses/groups/GroupRoleListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of GroupRole objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupRoleResponse.yaml b/openapi/components/responses/groups/GroupRoleResponse.yaml index a0223cd5..7a71eeb2 100644 --- a/openapi/components/responses/groups/GroupRoleResponse.yaml +++ b/openapi/components/responses/groups/GroupRoleResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single GroupRole object. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupRoleTemplatesResponse.yaml b/openapi/components/responses/groups/GroupRoleTemplatesResponse.yaml index f4623e1e..d46f7221 100644 --- a/openapi/components/responses/groups/GroupRoleTemplatesResponse.yaml +++ b/openapi/components/responses/groups/GroupRoleTemplatesResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a dictionary of GroupRoleTemplate objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/GroupTransferCanceledSuccess.yaml b/openapi/components/responses/groups/GroupTransferCanceledSuccess.yaml index bc36d227..060ebf2a 100644 --- a/openapi/components/responses/groups/GroupTransferCanceledSuccess.yaml +++ b/openapi/components/responses/groups/GroupTransferCanceledSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after cancelling a group transfer. content: application/json: examples: diff --git a/openapi/components/responses/groups/GroupTransferSuccess.yaml b/openapi/components/responses/groups/GroupTransferSuccess.yaml index 5e878172..93642701 100644 --- a/openapi/components/responses/groups/GroupTransferSuccess.yaml +++ b/openapi/components/responses/groups/GroupTransferSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after initiating or completing a group transfer. content: application/json: examples: diff --git a/openapi/components/responses/groups/GroupTransferableResponse.yaml b/openapi/components/responses/groups/GroupTransferableResponse.yaml index 49a97920..cc6210bc 100644 --- a/openapi/components/responses/groups/GroupTransferableResponse.yaml +++ b/openapi/components/responses/groups/GroupTransferableResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single GroupTransferable object. content: application/json: schema: diff --git a/openapi/components/responses/groups/LimitedGroupListResponse.yaml b/openapi/components/responses/groups/LimitedGroupListResponse.yaml index 1993f8c8..48386ec5 100644 --- a/openapi/components/responses/groups/LimitedGroupListResponse.yaml +++ b/openapi/components/responses/groups/LimitedGroupListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of LimitedGroup objects. content: application/json: schema: diff --git a/openapi/components/responses/groups/UpdateGroupRepresentationSuccess.yaml b/openapi/components/responses/groups/UpdateGroupRepresentationSuccess.yaml index 8bf72da4..81ab85ef 100644 --- a/openapi/components/responses/groups/UpdateGroupRepresentationSuccess.yaml +++ b/openapi/components/responses/groups/UpdateGroupRepresentationSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after updating group representation. content: application/json: examples: diff --git a/openapi/components/responses/instances/InstanceCategoryListResponse.yaml b/openapi/components/responses/instances/InstanceCategoryListResponse.yaml index 99f6cef3..8640737d 100644 --- a/openapi/components/responses/instances/InstanceCategoryListResponse.yaml +++ b/openapi/components/responses/instances/InstanceCategoryListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of InstanceCategory objects. content: application/json: schema: diff --git a/openapi/components/responses/instances/InstanceResponse.yaml b/openapi/components/responses/instances/InstanceResponse.yaml index c3110284..aa5f9dfa 100644 --- a/openapi/components/responses/instances/InstanceResponse.yaml +++ b/openapi/components/responses/instances/InstanceResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Instance object. content: application/json: schema: diff --git a/openapi/components/responses/instances/InstanceUpdateForbiddenError.yaml b/openapi/components/responses/instances/InstanceUpdateForbiddenError.yaml new file mode 100644 index 00000000..3524eae2 --- /dev/null +++ b/openapi/components/responses/instances/InstanceUpdateForbiddenError.yaml @@ -0,0 +1,16 @@ +description: Error response when the caller lacks permission to manage the instance or its calendar link +content: + application/json: + examples: + Missing Calendar Link Permission Example: + value: + error: + message: You're not allowed to create or change an instance linked to an event․ + status_code: 403 + Missing Instance Management Permission Example: + value: + error: + message: "You're not allowed to edit this instance․" + status_code: 403 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/instances/InstanceUpdateNotFoundError.yaml b/openapi/components/responses/instances/InstanceUpdateNotFoundError.yaml new file mode 100644 index 00000000..d88e2b93 --- /dev/null +++ b/openapi/components/responses/instances/InstanceUpdateNotFoundError.yaml @@ -0,0 +1,16 @@ +description: Error response when the instance does not exist or the requested calendar event belongs to another group +content: + application/json: + examples: + Event From Another Group Example: + value: + error: + message: Event not found․ + status_code: 404 + Instance Not Found Example: + value: + error: + message: Instance not found․ + status_code: 404 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/instances/InstanceUpdateValidationError.yaml b/openapi/components/responses/instances/InstanceUpdateValidationError.yaml new file mode 100644 index 00000000..c2c127ce --- /dev/null +++ b/openapi/components/responses/instances/InstanceUpdateValidationError.yaml @@ -0,0 +1,16 @@ +description: Error response when an instance's calendar event link cannot be updated +content: + application/json: + examples: + Event Outside Link Window Example: + value: + error: + message: You can only link instances to events starting within 6 hours‚ or that have ended within the last 6 hours․ + status_code: 400 + Non-Group Instance Example: + value: + error: + message: "'calendarEntryId' is only allowed for group instances․" + status_code: 400 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/instances/InstanceVibeListResponse.yaml b/openapi/components/responses/instances/InstanceVibeListResponse.yaml index 75e97d02..470368d2 100644 --- a/openapi/components/responses/instances/InstanceVibeListResponse.yaml +++ b/openapi/components/responses/instances/InstanceVibeListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of InstanceVibe objects. content: application/json: schema: diff --git a/openapi/components/responses/instances/LocationIDListResponse.yaml b/openapi/components/responses/instances/LocationIDListResponse.yaml index 9402cab9..6ecdbb2d 100644 --- a/openapi/components/responses/instances/LocationIDListResponse.yaml +++ b/openapi/components/responses/instances/LocationIDListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of LocationIDs. content: application/json: schema: diff --git a/openapi/components/responses/inventory/ConsumeInventoryItemResponse.yaml b/openapi/components/responses/inventory/ConsumeInventoryItemResponse.yaml index 2170739f..dc058693 100644 --- a/openapi/components/responses/inventory/ConsumeInventoryItemResponse.yaml +++ b/openapi/components/responses/inventory/ConsumeInventoryItemResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an InventoryConsumptionResults object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/DeleteInventoryItemResponse.yaml b/openapi/components/responses/inventory/DeleteInventoryItemResponse.yaml index 147a9804..5db3cd4c 100644 --- a/openapi/components/responses/inventory/DeleteInventoryItemResponse.yaml +++ b/openapi/components/responses/inventory/DeleteInventoryItemResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an SuccessFlag object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventoryCollectionsResponse.yaml b/openapi/components/responses/inventory/InventoryCollectionsResponse.yaml index b50267e4..bf4ea0df 100644 --- a/openapi/components/responses/inventory/InventoryCollectionsResponse.yaml +++ b/openapi/components/responses/inventory/InventoryCollectionsResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of strings. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventoryDropListResponse.yaml b/openapi/components/responses/inventory/InventoryDropListResponse.yaml index f71ac989..21afc692 100644 --- a/openapi/components/responses/inventory/InventoryDropListResponse.yaml +++ b/openapi/components/responses/inventory/InventoryDropListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of InventoryDrop objects. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventoryItemResponse.yaml b/openapi/components/responses/inventory/InventoryItemResponse.yaml index 639de36f..b58daaee 100644 --- a/openapi/components/responses/inventory/InventoryItemResponse.yaml +++ b/openapi/components/responses/inventory/InventoryItemResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an InventoryItem object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventoryResponse.yaml b/openapi/components/responses/inventory/InventoryResponse.yaml index d27c6886..e44438d9 100644 --- a/openapi/components/responses/inventory/InventoryResponse.yaml +++ b/openapi/components/responses/inventory/InventoryResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an Inventory object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventoryShareResponse.yaml b/openapi/components/responses/inventory/InventoryShareResponse.yaml index 4a0c11c6..83b87d4c 100644 --- a/openapi/components/responses/inventory/InventoryShareResponse.yaml +++ b/openapi/components/responses/inventory/InventoryShareResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an OkStatus object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventorySpawnResponse.yaml b/openapi/components/responses/inventory/InventorySpawnResponse.yaml index e917c128..69a9575c 100644 --- a/openapi/components/responses/inventory/InventorySpawnResponse.yaml +++ b/openapi/components/responses/inventory/InventorySpawnResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an InventorySpawn object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/InventoryTemplateListResponse.yaml b/openapi/components/responses/inventory/InventoryTemplateListResponse.yaml new file mode 100644 index 00000000..787dd924 --- /dev/null +++ b/openapi/components/responses/inventory/InventoryTemplateListResponse.yaml @@ -0,0 +1,6 @@ +content: + application/json: + schema: + type: array + items: + $ref: ../../schemas/InventoryTemplate.yaml diff --git a/openapi/components/responses/inventory/InventoryTemplateResponse.yaml b/openapi/components/responses/inventory/InventoryTemplateResponse.yaml index ce7ed9af..0088aa02 100644 --- a/openapi/components/responses/inventory/InventoryTemplateResponse.yaml +++ b/openapi/components/responses/inventory/InventoryTemplateResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an InventoryTemplate object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/RewardRedemptionResponse.yaml b/openapi/components/responses/inventory/RewardRedemptionResponse.yaml index ed5b358f..c9ef11a6 100644 --- a/openapi/components/responses/inventory/RewardRedemptionResponse.yaml +++ b/openapi/components/responses/inventory/RewardRedemptionResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single RewardRedemptionResult object. content: application/json: schema: diff --git a/openapi/components/responses/inventory/UnequipInventorySlotResponse.yaml b/openapi/components/responses/inventory/UnequipInventorySlotResponse.yaml index 1d0d113d..a5880da5 100644 --- a/openapi/components/responses/inventory/UnequipInventorySlotResponse.yaml +++ b/openapi/components/responses/inventory/UnequipInventorySlotResponse.yaml @@ -1,6 +1,6 @@ -description: Returns a string. content: application/json: schema: type: string - example: OK + examples: + - OK diff --git a/openapi/components/responses/invite/InviteMessageListResponse.yaml b/openapi/components/responses/invite/InviteMessageListResponse.yaml index a0a3537b..85f1ce1d 100644 --- a/openapi/components/responses/invite/InviteMessageListResponse.yaml +++ b/openapi/components/responses/invite/InviteMessageListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of InviteMessage objects. content: application/json: schema: diff --git a/openapi/components/responses/invite/InviteMessageResponse.yaml b/openapi/components/responses/invite/InviteMessageResponse.yaml index 4060e251..20636b10 100644 --- a/openapi/components/responses/invite/InviteMessageResponse.yaml +++ b/openapi/components/responses/invite/InviteMessageResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single InviteMessage object. content: application/json: schema: diff --git a/openapi/components/responses/jams/DeleteJamSubmissionResponse.yaml b/openapi/components/responses/jams/DeleteJamSubmissionResponse.yaml index 86439f61..807df49e 100644 --- a/openapi/components/responses/jams/DeleteJamSubmissionResponse.yaml +++ b/openapi/components/responses/jams/DeleteJamSubmissionResponse.yaml @@ -1,4 +1,3 @@ -description: Returns an Success object. content: application/json: schema: diff --git a/openapi/components/responses/jams/JamListResponse.yaml b/openapi/components/responses/jams/JamListResponse.yaml index 599bdc32..5d257bae 100644 --- a/openapi/components/responses/jams/JamListResponse.yaml +++ b/openapi/components/responses/jams/JamListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Jam objects. content: application/json: schema: diff --git a/openapi/components/responses/jams/JamResponse.yaml b/openapi/components/responses/jams/JamResponse.yaml index c4411747..4ec66b96 100644 --- a/openapi/components/responses/jams/JamResponse.yaml +++ b/openapi/components/responses/jams/JamResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a Jam object. content: application/json: schema: diff --git a/openapi/components/responses/jams/JamSubmissionListResponse.yaml b/openapi/components/responses/jams/JamSubmissionListResponse.yaml index f3e1e219..401a6854 100644 --- a/openapi/components/responses/jams/JamSubmissionListResponse.yaml +++ b/openapi/components/responses/jams/JamSubmissionListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of JamSubmission objects. content: application/json: schema: diff --git a/openapi/components/responses/jams/JamSubmissionResponse.yaml b/openapi/components/responses/jams/JamSubmissionResponse.yaml index a2f5f654..b7356f13 100644 --- a/openapi/components/responses/jams/JamSubmissionResponse.yaml +++ b/openapi/components/responses/jams/JamSubmissionResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single JamSubmission object. content: application/json: schema: diff --git a/openapi/components/responses/notifications/ClearNotificationV2Success.yaml b/openapi/components/responses/notifications/ClearNotificationV2Success.yaml index 0d0e058c..eeefe72d 100644 --- a/openapi/components/responses/notifications/ClearNotificationV2Success.yaml +++ b/openapi/components/responses/notifications/ClearNotificationV2Success.yaml @@ -1,4 +1,3 @@ -description: Successful response after clearing a notification. content: application/json: examples: diff --git a/openapi/components/responses/notifications/ClearNotificationsSuccess.yaml b/openapi/components/responses/notifications/ClearNotificationsSuccess.yaml index 4ef7a881..38b80d52 100644 --- a/openapi/components/responses/notifications/ClearNotificationsSuccess.yaml +++ b/openapi/components/responses/notifications/ClearNotificationsSuccess.yaml @@ -1,4 +1,3 @@ -description: Successful response after clearing all notifications. content: application/json: examples: diff --git a/openapi/components/responses/notifications/ClearNotificationsV2Success.yaml b/openapi/components/responses/notifications/ClearNotificationsV2Success.yaml index 99d6c5b7..699b5621 100644 --- a/openapi/components/responses/notifications/ClearNotificationsV2Success.yaml +++ b/openapi/components/responses/notifications/ClearNotificationsV2Success.yaml @@ -1,4 +1,3 @@ -description: Successful response after clearing all notifications. content: application/json: examples: diff --git a/openapi/components/responses/notifications/NotificationListResponse.yaml b/openapi/components/responses/notifications/NotificationListResponse.yaml index 799b84e2..b660e0cb 100644 --- a/openapi/components/responses/notifications/NotificationListResponse.yaml +++ b/openapi/components/responses/notifications/NotificationListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Notification objects. content: application/json: schema: diff --git a/openapi/components/responses/notifications/NotificationResponse.yaml b/openapi/components/responses/notifications/NotificationResponse.yaml index 0a482d71..1fe4e0ce 100644 --- a/openapi/components/responses/notifications/NotificationResponse.yaml +++ b/openapi/components/responses/notifications/NotificationResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Notification object. content: application/json: examples: diff --git a/openapi/components/responses/notifications/SendNotificationResponse.yaml b/openapi/components/responses/notifications/SendNotificationResponse.yaml index 26c91a40..31e09107 100644 --- a/openapi/components/responses/notifications/SendNotificationResponse.yaml +++ b/openapi/components/responses/notifications/SendNotificationResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single SentNotification object. content: application/json: examples: diff --git a/openapi/components/responses/permissions/PermissionListResponse.yaml b/openapi/components/responses/permissions/PermissionListResponse.yaml index 2dedb43c..5f17cb92 100644 --- a/openapi/components/responses/permissions/PermissionListResponse.yaml +++ b/openapi/components/responses/permissions/PermissionListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Permission objects. content: application/json: examples: diff --git a/openapi/components/responses/permissions/PermissionResponse.yaml b/openapi/components/responses/permissions/PermissionResponse.yaml index c600a4d3..eb132d0f 100644 --- a/openapi/components/responses/permissions/PermissionResponse.yaml +++ b/openapi/components/responses/permissions/PermissionResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Permission object. content: application/json: schema: diff --git a/openapi/components/responses/playermoderation/PlayerModerationClearAllSuccess.yaml b/openapi/components/responses/playermoderation/PlayerModerationClearAllSuccess.yaml index 5c685908..3c6ac178 100644 --- a/openapi/components/responses/playermoderation/PlayerModerationClearAllSuccess.yaml +++ b/openapi/components/responses/playermoderation/PlayerModerationClearAllSuccess.yaml @@ -1,11 +1,11 @@ -description: Success response after e.g. clearing all player moderations. -content: - application/json: - examples: - 200 OK: - value: - success: - message: OK - status_code: 200 - schema: +description: Success response after e.g. clearing all player moderations. +content: + application/json: + examples: + 200 OK: + value: + success: + message: OK + status_code: 200 + schema: $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/playermoderation/PlayerModerationListResponse.yaml b/openapi/components/responses/playermoderation/PlayerModerationListResponse.yaml index d0598774..9370f239 100644 --- a/openapi/components/responses/playermoderation/PlayerModerationListResponse.yaml +++ b/openapi/components/responses/playermoderation/PlayerModerationListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of PlayerModeration objects. content: application/json: schema: diff --git a/openapi/components/responses/playermoderation/PlayerModerationResponse.yaml b/openapi/components/responses/playermoderation/PlayerModerationResponse.yaml index 133d935a..a683e076 100644 --- a/openapi/components/responses/playermoderation/PlayerModerationResponse.yaml +++ b/openapi/components/responses/playermoderation/PlayerModerationResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single PlayerModeration object. content: application/json: schema: diff --git a/openapi/components/responses/playermoderation/PlayerModerationUnmoderatedSuccess.yaml b/openapi/components/responses/playermoderation/PlayerModerationUnmoderatedSuccess.yaml index c1c343da..333611a4 100644 --- a/openapi/components/responses/playermoderation/PlayerModerationUnmoderatedSuccess.yaml +++ b/openapi/components/responses/playermoderation/PlayerModerationUnmoderatedSuccess.yaml @@ -1,16 +1,16 @@ -description: Success response after unmoderating a player moderation. -content: - application/json: - examples: - 200 All Of PlayerModerationType Unmoderated: - value: - success: - message: PlayerModerations of type undefined removed - status_code: 200 - 200 Specific User Unmoderated: - value: - success: - message: User usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 unmoderated - status_code: 200 - schema: +description: Success response after unmoderating a player moderation. +content: + application/json: + examples: + 200 All Of PlayerModerationType Unmoderated: + value: + success: + message: PlayerModerations of type undefined removed + status_code: 200 + 200 Specific User Unmoderated: + value: + success: + message: User usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 unmoderated + status_code: 200 + schema: $ref: ../../schemas/Success.yaml diff --git a/openapi/components/responses/prints/PrintListResponse.yaml b/openapi/components/responses/prints/PrintListResponse.yaml index cf71e8a1..287f4802 100644 --- a/openapi/components/responses/prints/PrintListResponse.yaml +++ b/openapi/components/responses/prints/PrintListResponse.yaml @@ -1,7 +1,6 @@ -description: Returns a list of Print objects. -content: - application/json: - schema: - type: array - items: +content: + application/json: + schema: + type: array + items: $ref: ../../schemas/Print.yaml diff --git a/openapi/components/responses/prints/PrintResponse.yaml b/openapi/components/responses/prints/PrintResponse.yaml index 7c86e700..b467bc2b 100644 --- a/openapi/components/responses/prints/PrintResponse.yaml +++ b/openapi/components/responses/prints/PrintResponse.yaml @@ -1,5 +1,4 @@ -description: Returns a single Print object. -content: - application/json: - schema: +content: + application/json: + schema: $ref: ../../schemas/Print.yaml diff --git a/openapi/components/responses/prints/UnableToRequestOtherUsersPrintsError.yaml b/openapi/components/responses/prints/UnableToRequestOtherUsersPrintsError.yaml index dad49f47..b82419e4 100644 --- a/openapi/components/responses/prints/UnableToRequestOtherUsersPrintsError.yaml +++ b/openapi/components/responses/prints/UnableToRequestOtherUsersPrintsError.yaml @@ -1,11 +1,11 @@ -description: Error response when trying to request another user's prints. -content: - application/json: - examples: - 403 Unable to request another user's prints: - value: - error: - message: "Unable to request another user's prints." - status_code: 403 - schema: +description: Error response when trying to request another user's prints. +content: + application/json: + examples: + 403 Unable to request another user's prints: + value: + error: + message: "Unable to request another user's prints." + status_code: 403 + schema: $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/props/PropListResponse.yaml b/openapi/components/responses/props/PropListResponse.yaml index 62c28888..a8e80ee0 100644 --- a/openapi/components/responses/props/PropListResponse.yaml +++ b/openapi/components/responses/props/PropListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Prop objects. content: application/json: schema: diff --git a/openapi/components/responses/props/PropPublishStatusResponse.yaml b/openapi/components/responses/props/PropPublishStatusResponse.yaml index 273aa610..4696f731 100644 --- a/openapi/components/responses/props/PropPublishStatusResponse.yaml +++ b/openapi/components/responses/props/PropPublishStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single PropPublishStatus object. content: application/json: schema: diff --git a/openapi/components/responses/props/PropResponse.yaml b/openapi/components/responses/props/PropResponse.yaml index e40c41cf..a2ec5beb 100644 --- a/openapi/components/responses/props/PropResponse.yaml +++ b/openapi/components/responses/props/PropResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Prop object. content: application/json: schema: diff --git a/openapi/components/responses/system/APIConfigResponse.yaml b/openapi/components/responses/system/APIConfigResponse.yaml index 42e4d7db..e9defec0 100644 --- a/openapi/components/responses/system/APIConfigResponse.yaml +++ b/openapi/components/responses/system/APIConfigResponse.yaml @@ -1,4 +1,3 @@ -description: Returns the API's config. content: application/json: schema: diff --git a/openapi/components/responses/system/APIHealthResponse.yaml b/openapi/components/responses/system/APIHealthResponse.yaml index c5ca3f2b..7bc3a5b4 100644 --- a/openapi/components/responses/system/APIHealthResponse.yaml +++ b/openapi/components/responses/system/APIHealthResponse.yaml @@ -1,4 +1,3 @@ -description: Returns the API's health. content: application/json: examples: diff --git a/openapi/components/responses/system/BetaNotFoundError.yaml b/openapi/components/responses/system/BetaNotFoundError.yaml new file mode 100644 index 00000000..96d267a5 --- /dev/null +++ b/openapi/components/responses/system/BetaNotFoundError.yaml @@ -0,0 +1,9 @@ +description: No beta program goes by that name. +content: + application/json: + example: + error: + message: Beta not found + status_code: 404 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/system/BetaRegistrationNotFoundError.yaml b/openapi/components/responses/system/BetaRegistrationNotFoundError.yaml new file mode 100644 index 00000000..ffa3749d --- /dev/null +++ b/openapi/components/responses/system/BetaRegistrationNotFoundError.yaml @@ -0,0 +1,13 @@ +description: The caller has no registration for this beta program. +content: + application/json: + schema: + title: BetaRegistrationNotFoundError + type: object + properties: + error: + type: string + examples: + - No registration found + required: + - error diff --git a/openapi/components/responses/system/BetaResponse.yaml b/openapi/components/responses/system/BetaResponse.yaml new file mode 100644 index 00000000..0907797c --- /dev/null +++ b/openapi/components/responses/system/BetaResponse.yaml @@ -0,0 +1,4 @@ +content: + application/json: + schema: + $ref: ../../schemas/Beta.yaml diff --git a/openapi/components/responses/system/CurrentOnlineUsersResponse.yaml b/openapi/components/responses/system/CurrentOnlineUsersResponse.yaml index b4d0e29f..578bde8a 100644 --- a/openapi/components/responses/system/CurrentOnlineUsersResponse.yaml +++ b/openapi/components/responses/system/CurrentOnlineUsersResponse.yaml @@ -1,8 +1,8 @@ -description: OK content: application/json: schema: type: integer description: Number of online users - example: 12345 + examples: + - 12345 minimum: 0 diff --git a/openapi/components/responses/system/FrontendBranchListResponse.yaml b/openapi/components/responses/system/FrontendBranchListResponse.yaml new file mode 100644 index 00000000..2a0eecf5 --- /dev/null +++ b/openapi/components/responses/system/FrontendBranchListResponse.yaml @@ -0,0 +1,7 @@ +description: Returns the frontend branches available to the caller. +content: + application/json: + schema: + type: array + items: + $ref: ../../schemas/Unknown.yaml diff --git a/openapi/components/responses/system/InfoPushListResponse.yaml b/openapi/components/responses/system/InfoPushListResponse.yaml index 3ab5d0b9..8d18e66d 100644 --- a/openapi/components/responses/system/InfoPushListResponse.yaml +++ b/openapi/components/responses/system/InfoPushListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of InfoPush objects. content: application/json: examples: diff --git a/openapi/components/responses/system/SystemTimeResponse.yaml b/openapi/components/responses/system/SystemTimeResponse.yaml index 0f141353..d253ef32 100644 --- a/openapi/components/responses/system/SystemTimeResponse.yaml +++ b/openapi/components/responses/system/SystemTimeResponse.yaml @@ -1,8 +1,8 @@ -description: OK content: application/json: schema: type: string description: Does not return millisecond precision. Always returns time in UTC. - example: "2021-08-20T12:38:42+00:00" + examples: + - "2021-08-20T12:38:42+00:00" format: date-time diff --git a/openapi/components/responses/users/AgeVerificationStatusResponse.yaml b/openapi/components/responses/users/AgeVerificationStatusResponse.yaml new file mode 100644 index 00000000..3de5f672 --- /dev/null +++ b/openapi/components/responses/users/AgeVerificationStatusResponse.yaml @@ -0,0 +1,4 @@ +content: + application/json: + schema: + $ref: ../../schemas/AgeVerificationStatusResult.yaml diff --git a/openapi/components/responses/users/ClearTutorialsForbiddenError.yaml b/openapi/components/responses/users/ClearTutorialsForbiddenError.yaml new file mode 100644 index 00000000..82a46f63 --- /dev/null +++ b/openapi/components/responses/users/ClearTutorialsForbiddenError.yaml @@ -0,0 +1,11 @@ +description: A user can clear only their own tutorials. +content: + application/json: + examples: + Other User: + value: + error: + message: '"You do not have permission to clear tutorials completions for others."' + status_code: 403 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/users/CompleteTutorialForbiddenError.yaml b/openapi/components/responses/users/CompleteTutorialForbiddenError.yaml new file mode 100644 index 00000000..74cf3522 --- /dev/null +++ b/openapi/components/responses/users/CompleteTutorialForbiddenError.yaml @@ -0,0 +1,11 @@ +description: A user can complete only their own tutorials. +content: + application/json: + examples: + Other User: + value: + error: + message: '"You do not have permission to complete tutorials for others."' + status_code: 403 + schema: + $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/users/CurrentUserResponse.yaml b/openapi/components/responses/users/CurrentUserResponse.yaml index c639f617..5dbb3f00 100644 --- a/openapi/components/responses/users/CurrentUserResponse.yaml +++ b/openapi/components/responses/users/CurrentUserResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single CurrentUser object. content: application/json: schema: diff --git a/openapi/components/responses/users/FeedbackListResponse.yaml b/openapi/components/responses/users/FeedbackListResponse.yaml index 974edc4e..efa2f7ef 100644 --- a/openapi/components/responses/users/FeedbackListResponse.yaml +++ b/openapi/components/responses/users/FeedbackListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of Feedback objects. content: application/json: schema: diff --git a/openapi/components/responses/users/LimitedUserGroupListResponse.yaml b/openapi/components/responses/users/LimitedUserGroupListResponse.yaml index a683d124..3f440ba7 100644 --- a/openapi/components/responses/users/LimitedUserGroupListResponse.yaml +++ b/openapi/components/responses/users/LimitedUserGroupListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of LimitedUserGroups objects. content: application/json: schema: diff --git a/openapi/components/responses/users/LimitedUserSearchListResponse.yaml b/openapi/components/responses/users/LimitedUserSearchListResponse.yaml index bd0527ce..a414874a 100644 --- a/openapi/components/responses/users/LimitedUserSearchListResponse.yaml +++ b/openapi/components/responses/users/LimitedUserSearchListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of LimitedUserSearch objects. content: application/json: schema: diff --git a/openapi/components/responses/users/MutualFriendListResponse.yaml b/openapi/components/responses/users/MutualFriendListResponse.yaml index bded8d8a..e81cf534 100644 --- a/openapi/components/responses/users/MutualFriendListResponse.yaml +++ b/openapi/components/responses/users/MutualFriendListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of MutualFriend objects. content: application/json: schema: diff --git a/openapi/components/responses/users/MutualsResponse.yaml b/openapi/components/responses/users/MutualsResponse.yaml index 3c448a76..43850eb6 100644 --- a/openapi/components/responses/users/MutualsResponse.yaml +++ b/openapi/components/responses/users/MutualsResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single Mutuals object. content: application/json: schema: diff --git a/openapi/components/responses/users/PublicProfileResponse.yaml b/openapi/components/responses/users/PublicProfileResponse.yaml index 715fd5d5..ac7de01c 100644 --- a/openapi/components/responses/users/PublicProfileResponse.yaml +++ b/openapi/components/responses/users/PublicProfileResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a user's public profile. content: application/json: schema: diff --git a/openapi/components/responses/users/TutorialStatusResponse.yaml b/openapi/components/responses/users/TutorialStatusResponse.yaml index 0043cdfc..38ab5441 100644 --- a/openapi/components/responses/users/TutorialStatusResponse.yaml +++ b/openapi/components/responses/users/TutorialStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single TutorialStatus object. content: application/json: schema: diff --git a/openapi/components/responses/users/UpdateUserNoteResponse.yaml b/openapi/components/responses/users/UpdateUserNoteResponse.yaml new file mode 100644 index 00000000..bcf256fc --- /dev/null +++ b/openapi/components/responses/users/UpdateUserNoteResponse.yaml @@ -0,0 +1,11 @@ +description: An empty `note` clears the note and returns a string in place of the `UserNote`. +content: + application/json: + examples: + Note Cleared: + value: User note cleared. + schema: + title: UpdateUserNoteResponse + oneOf: + - $ref: ../../schemas/UserNote.yaml + - type: string diff --git a/openapi/components/responses/users/UserBadgeUpdateResponse.yaml b/openapi/components/responses/users/UserBadgeUpdateResponse.yaml index a1ccf9f6..63f25139 100644 --- a/openapi/components/responses/users/UserBadgeUpdateResponse.yaml +++ b/openapi/components/responses/users/UserBadgeUpdateResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single LimitedBadge object. content: application/json: schema: diff --git a/openapi/components/responses/users/UserClientConfigResponse.yaml b/openapi/components/responses/users/UserClientConfigResponse.yaml new file mode 100644 index 00000000..8a848728 --- /dev/null +++ b/openapi/components/responses/users/UserClientConfigResponse.yaml @@ -0,0 +1,4 @@ +content: + application/json: + schema: + $ref: ../../schemas/UserClientConfig.yaml diff --git a/openapi/components/responses/users/UserCosmeticListResponse.yaml b/openapi/components/responses/users/UserCosmeticListResponse.yaml new file mode 100644 index 00000000..6efb380e --- /dev/null +++ b/openapi/components/responses/users/UserCosmeticListResponse.yaml @@ -0,0 +1,6 @@ +content: + application/json: + schema: + type: array + items: + $ref: ../../schemas/UserCosmetic.yaml diff --git a/openapi/components/responses/users/UserGroupInstanceListResponse.yaml b/openapi/components/responses/users/UserGroupInstanceListResponse.yaml index 68234e7b..9ce6b309 100644 --- a/openapi/components/responses/users/UserGroupInstanceListResponse.yaml +++ b/openapi/components/responses/users/UserGroupInstanceListResponse.yaml @@ -1,7 +1,7 @@ -description: Returns a list of Instance objects with a fetched at time. content: application/json: schema: + title: UserGroupInstanceListResponse type: object properties: fetchedAt: diff --git a/openapi/components/responses/users/UserMustBeOwnError.yaml b/openapi/components/responses/users/UserMustBeOwnError.yaml index a632278a..f32d9926 100644 --- a/openapi/components/responses/users/UserMustBeOwnError.yaml +++ b/openapi/components/responses/users/UserMustBeOwnError.yaml @@ -1,11 +1,11 @@ -description: Error response when trying get group instances of another user. -content: - application/json: - examples: - User Id must be your own: - value: - error: - message: User ID must be your own․ - status_code: 403 - schema: +description: Error response when trying get group instances of another user. +content: + application/json: + examples: + User Id must be your own: + value: + error: + message: User ID must be your own․ + status_code: 403 + schema: $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/users/UserNoteListResponse.yaml b/openapi/components/responses/users/UserNoteListResponse.yaml index 0963ef16..6ca9e737 100644 --- a/openapi/components/responses/users/UserNoteListResponse.yaml +++ b/openapi/components/responses/users/UserNoteListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of UserNote objects. content: application/json: schema: diff --git a/openapi/components/responses/users/UserNoteResponse.yaml b/openapi/components/responses/users/UserNoteResponse.yaml index 5116ce31..c3f879d6 100644 --- a/openapi/components/responses/users/UserNoteResponse.yaml +++ b/openapi/components/responses/users/UserNoteResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single UserNote object. content: application/json: schema: diff --git a/openapi/components/responses/users/UserResponse.yaml b/openapi/components/responses/users/UserResponse.yaml index 7e1ca8b9..da155a8a 100644 --- a/openapi/components/responses/users/UserResponse.yaml +++ b/openapi/components/responses/users/UserResponse.yaml @@ -1,17 +1,8 @@ -description: |- - Return a single User object. - - Requesting your own ID returns your full `CurrentUser` record instead, carrying - the private fields (`emailVerified`, `steamDetails`, `twoFactorAuthEnabled`, …) - that never appear in responses for another user. +description: Requesting your own ID returns your full `CurrentUser` record, carrying the private fields (`emailVerified`, `steamDetails`, `twoFactorAuthEnabled`, …) that never appear in responses for another user. content: application/json: schema: - x-if: - when: jsonschema - then: - oneOf: - - $ref: ../../schemas/User.yaml - - $ref: ../../schemas/CurrentUser.yaml - else: - $ref: ../../schemas/User.yaml + title: UserResponse + oneOf: + - $ref: ../../schemas/User.yaml + - $ref: ../../schemas/CurrentUser.yaml diff --git a/openapi/components/responses/users/UsersInvalidSearchError.yaml b/openapi/components/responses/users/UsersInvalidSearchError.yaml index e1cc59d5..55e993d5 100644 --- a/openapi/components/responses/users/UsersInvalidSearchError.yaml +++ b/openapi/components/responses/users/UsersInvalidSearchError.yaml @@ -1,16 +1,16 @@ -description: Error response when trying to search list of users with an invalid request. -content: - application/json: - examples: - 400 N is too high: - value: - error: - message: n=1000 is much too high․ implement paging you savages․ - status_code: 400 - 400 N is too low: - value: - error: - message: "n must be a positive integer˸ '-1'" - status_code: 400 - schema: +description: Error response when trying to search list of users with an invalid request. +content: + application/json: + examples: + 400 N is too high: + value: + error: + message: n=1000 is much too high․ implement paging you savages․ + status_code: 400 + 400 N is too low: + value: + error: + message: "n must be a positive integer˸ '-1'" + status_code: 400 + schema: $ref: ../../schemas/Error.yaml diff --git a/openapi/components/responses/worlds/DeleteWorldResponse.yaml b/openapi/components/responses/worlds/DeleteWorldResponse.yaml new file mode 100644 index 00000000..5d738274 --- /dev/null +++ b/openapi/components/responses/worlds/DeleteWorldResponse.yaml @@ -0,0 +1,7 @@ +content: + application/json: + examples: + Deleted: + value: null + schema: + $ref: ../../schemas/Unknown.yaml diff --git a/openapi/components/responses/worlds/FavoritedWorldListResponse.yaml b/openapi/components/responses/worlds/FavoritedWorldListResponse.yaml index c7504e05..399e7965 100644 --- a/openapi/components/responses/worlds/FavoritedWorldListResponse.yaml +++ b/openapi/components/responses/worlds/FavoritedWorldListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of FavoritedWorld objects. content: application/json: schema: diff --git a/openapi/components/responses/worlds/LimitedWorldListResponse.yaml b/openapi/components/responses/worlds/LimitedWorldListResponse.yaml index b1e0fae5..9b04f8ce 100644 --- a/openapi/components/responses/worlds/LimitedWorldListResponse.yaml +++ b/openapi/components/responses/worlds/LimitedWorldListResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a list of LimitedWorld objects. content: application/json: schema: diff --git a/openapi/components/responses/worlds/WorldMetadataResponse.yaml b/openapi/components/responses/worlds/WorldMetadataResponse.yaml index b4f848bb..fa2fac01 100644 --- a/openapi/components/responses/worlds/WorldMetadataResponse.yaml +++ b/openapi/components/responses/worlds/WorldMetadataResponse.yaml @@ -1,4 +1,3 @@ -description: OK content: application/json: schema: diff --git a/openapi/components/responses/worlds/WorldPublishStatusResponse.yaml b/openapi/components/responses/worlds/WorldPublishStatusResponse.yaml index a61e5174..9ff59d87 100644 --- a/openapi/components/responses/worlds/WorldPublishStatusResponse.yaml +++ b/openapi/components/responses/worlds/WorldPublishStatusResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single WorldPublishStatus object. content: application/json: schema: diff --git a/openapi/components/responses/worlds/WorldResponse.yaml b/openapi/components/responses/worlds/WorldResponse.yaml index 7e28ccf7..500f58d6 100644 --- a/openapi/components/responses/worlds/WorldResponse.yaml +++ b/openapi/components/responses/worlds/WorldResponse.yaml @@ -1,4 +1,3 @@ -description: Returns a single World object. content: application/json: schema: diff --git a/openapi/components/schemas/APIConfig.yaml b/openapi/components/schemas/APIConfig.yaml index 991bee48..7f109e59 100644 --- a/openapi/components/schemas/APIConfig.yaml +++ b/openapi/components/schemas/APIConfig.yaml @@ -30,19 +30,23 @@ properties: properties: Default: type: string - example: https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR + examples: + - https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR format: uri Pico: type: string - example: https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR + examples: + - https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR format: uri Quest: type: string - example: https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR + examples: + - https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR format: uri XRElite: type: string - example: https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR + examples: + - https://help.vrchat.com/hc/en-us/articles/9521522810899-Where-do-I-find-my-output-logs#h_01HT1ZV67JGKX5AE4R1P28XMXR format: uri address: type: string @@ -200,7 +204,8 @@ properties: currentTOSVersion: type: integer description: Current version number of the Terms of Service - example: 7 + examples: + - 7 minimum: 0 defaultAvatar: $ref: ./AvatarID.yaml @@ -407,7 +412,8 @@ properties: properties: timeout: type: integer - example: -1 + examples: + - -1 maxUserEmoji: type: integer description: The maximum number of custom emoji each user may have at a given time. @@ -418,7 +424,8 @@ properties: default: 18 maximumUnityVersionForUploads: type: string - example: 2023.0.0f0 + examples: + - 2023.0.0f0 minSupportedClientBuildNumber: type: object description: Minimum supported client build number for various platforms @@ -504,7 +511,8 @@ properties: player-url-resolver-version-gfn-override: type: string description: Overrides `player-url-resolver-version` on GeForce Now. - example: 2026-07-04-GFN + examples: + - 2026-07-04-GFN profileDefaults: $ref: ./APIConfigProfileDefaults.yaml propComponentList: @@ -692,7 +700,6 @@ required: - downloadLinkWindows - downloadUrls - dynamicWorldRows - - economyLedgerBackfill - economyLedgerMode - economyPauseEnd - economyPauseStart diff --git a/openapi/components/schemas/APIConfigConstants.yaml b/openapi/components/schemas/APIConfigConstants.yaml index 277f7929..c8d92f29 100644 --- a/openapi/components/schemas/APIConfigConstants.yaml +++ b/openapi/components/schemas/APIConfigConstants.yaml @@ -1,101 +1,101 @@ -title: APIConfigConstants -type: object -description: Constants -properties: - GROUPS: - type: object - description: Group-related constants - properties: - CAPACITY: - type: integer - description: Maximum group capacity - default: 100000 - GROUP_TRANSFER_REQUIREMENTS: - type: array - description: Requirements for transferring group ownership - items: - type: string - description: Requirement for transferring group ownership - MAX_INVITES_REQUESTS: - type: integer - description: Maximum number of invite requests - default: 50 - MAX_JOINED: - type: integer - description: Maximum number of joined groups - default: 100 - MAX_JOINED_PLUS: - type: integer - description: Maximum number of joined groups for VRChat Plus members - default: 200 - MAX_LANGUAGES: - type: integer - description: Maximum number of supported languages - default: 10 - MAX_LINKS: - type: integer - description: Maximum number of group links - default: 3 - MAX_MANAGEMENT_ROLES: - type: integer - description: Maximum number of management roles in a group - default: 5 - MAX_OWNED: - type: integer - description: Maximum number of groups a user can own - default: 5 - MAX_ROLES: - type: integer - description: Maximum number of roles in a group - default: 50 - INSTANCE: - type: object - description: Instance-related constants - properties: - POPULATION_BRACKETS: - type: object - description: Population brackets based on instance population - properties: - CROWDED: - type: object - description: Crowded population range - properties: - max: - type: integer - description: Maximum population for a crowded instance - min: - type: integer - description: Minimum population for a crowded instance - FEW: - type: object - description: Few population range - properties: - max: - type: integer - description: Maximum population for a few instance - min: - type: integer - description: Minimum population for a few instance - MANY: - type: object - description: Many population range - properties: - max: - type: integer - description: Maximum population for a many instance - min: - type: integer - description: Minimum population for a many instance - LANGUAGE: - type: object - description: Language-related constants - properties: - SPOKEN_LANGUAGE_OPTIONS: - type: object - description: Supported spoken language options - additionalProperties: - type: string -required: - - GROUPS - - INSTANCE - - LANGUAGE +title: APIConfigConstants +type: object +description: Constants +properties: + GROUPS: + type: object + description: Group-related constants + properties: + CAPACITY: + type: integer + description: Maximum group capacity + default: 100000 + GROUP_TRANSFER_REQUIREMENTS: + type: array + description: Requirements for transferring group ownership + items: + type: string + description: Requirement for transferring group ownership + MAX_INVITES_REQUESTS: + type: integer + description: Maximum number of invite requests + default: 50 + MAX_JOINED: + type: integer + description: Maximum number of joined groups + default: 100 + MAX_JOINED_PLUS: + type: integer + description: Maximum number of joined groups for VRChat Plus members + default: 200 + MAX_LANGUAGES: + type: integer + description: Maximum number of supported languages + default: 10 + MAX_LINKS: + type: integer + description: Maximum number of group links + default: 3 + MAX_MANAGEMENT_ROLES: + type: integer + description: Maximum number of management roles in a group + default: 5 + MAX_OWNED: + type: integer + description: Maximum number of groups a user can own + default: 5 + MAX_ROLES: + type: integer + description: Maximum number of roles in a group + default: 50 + INSTANCE: + type: object + description: Instance-related constants + properties: + POPULATION_BRACKETS: + type: object + description: Population brackets based on instance population + properties: + CROWDED: + type: object + description: Crowded population range + properties: + max: + type: integer + description: Maximum population for a crowded instance + min: + type: integer + description: Minimum population for a crowded instance + FEW: + type: object + description: Few population range + properties: + max: + type: integer + description: Maximum population for a few instance + min: + type: integer + description: Minimum population for a few instance + MANY: + type: object + description: Many population range + properties: + max: + type: integer + description: Maximum population for a many instance + min: + type: integer + description: Minimum population for a many instance + LANGUAGE: + type: object + description: Language-related constants + properties: + SPOKEN_LANGUAGE_OPTIONS: + type: object + description: Supported spoken language options + additionalProperties: + type: string +required: + - GROUPS + - INSTANCE + - LANGUAGE diff --git a/openapi/components/schemas/APIConfigEventShelfCampaign.yaml b/openapi/components/schemas/APIConfigEventShelfCampaign.yaml index d4a6d969..df5180c5 100644 --- a/openapi/components/schemas/APIConfigEventShelfCampaign.yaml +++ b/openapi/components/schemas/APIConfigEventShelfCampaign.yaml @@ -4,13 +4,16 @@ description: A seasonal campaign a group event can be listed under. properties: description: type: string - example: Include this event in the VRChat Tanabata event shelf. + examples: + - Include this event in the VRChat Tanabata event shelf. key: type: string - example: tanabata + examples: + - tanabata name: type: string - example: Tanabata Homeworld Moderation + examples: + - Tanabata Homeworld Moderation required: - key - name diff --git a/openapi/components/schemas/APIConfigLoadingScreenWeights.yaml b/openapi/components/schemas/APIConfigLoadingScreenWeights.yaml index 7827698b..51ad3bef 100644 --- a/openapi/components/schemas/APIConfigLoadingScreenWeights.yaml +++ b/openapi/components/schemas/APIConfigLoadingScreenWeights.yaml @@ -3,10 +3,13 @@ type: object properties: announcement: type: integer - example: 1 + examples: + - 1 informational: type: integer - example: 89 + examples: + - 89 promotional: type: integer - example: 10 + examples: + - 10 diff --git a/openapi/components/schemas/APIConfigProfileDefaults.yaml b/openapi/components/schemas/APIConfigProfileDefaults.yaml index 0201e18f..3a1370f1 100644 --- a/openapi/components/schemas/APIConfigProfileDefaults.yaml +++ b/openapi/components/schemas/APIConfigProfileDefaults.yaml @@ -1,19 +1,14 @@ title: APIConfigProfileDefaults type: object -description: Default profile theme colours, each a hex RGB triplet without a leading `#`. +description: Default profile theme colors. properties: backgroundGradientBottom: - type: string - example: 9933FF + $ref: ./Color.yaml backgroundGradientTop: - type: string - example: 00C48A + $ref: ./Color.yaml themeButtonColor: - type: string - example: "009599" + $ref: ./Color.yaml themeIconColor: - type: string - example: 6BE4FA + $ref: ./Color.yaml themeSubtextColor: - type: string - example: A9A9A9 + $ref: ./Color.yaml diff --git a/openapi/components/schemas/AccountDeletionLog.yaml b/openapi/components/schemas/AccountDeletionLog.yaml index cbca3b38..7f6a6f8c 100644 --- a/openapi/components/schemas/AccountDeletionLog.yaml +++ b/openapi/components/schemas/AccountDeletionLog.yaml @@ -6,12 +6,14 @@ properties: description: Date and time of the deletion request. format: date-time deletionScheduled: - type: string + type: + - string + - "null" description: When the deletion is scheduled to happen, standard is 14 days after the request. - nullable: true format: date-time message: type: string description: Typically "Deletion requested" or "Deletion canceled". Other messages like "Deletion completed" may exist, but are these are not possible to see as a regular user. default: Deletion requested - example: Deletion requested + examples: + - Deletion requested diff --git a/openapi/components/schemas/AdminAssetBundle.yaml b/openapi/components/schemas/AdminAssetBundle.yaml index 11ad3e15..f25da23e 100644 --- a/openapi/components/schemas/AdminAssetBundle.yaml +++ b/openapi/components/schemas/AdminAssetBundle.yaml @@ -1,6 +1,5 @@ title: AdminAssetBundle type: object -description: "" properties: _created_at: type: string @@ -29,8 +28,9 @@ properties: thumbnailImageUrl: type: string unityPackageUrl: - type: string - nullable: true + type: + - string + - "null" unityPackages: type: array items: diff --git a/openapi/components/schemas/AdminUnityPackage.yaml b/openapi/components/schemas/AdminUnityPackage.yaml index 36b82f0c..e23154c0 100644 --- a/openapi/components/schemas/AdminUnityPackage.yaml +++ b/openapi/components/schemas/AdminUnityPackage.yaml @@ -1,20 +1,22 @@ title: AdminUnityPackage type: object -description: "" properties: assetUrl: type: string - example: https://assets.vrchat.com/adminfiles/adfl_fba880f3-7d8c-4429-87e6-0e2d50000076ie_chad_rat_standalonewindows + examples: + - https://assets.vrchat.com/adminfiles/adfl_fba880f3-7d8c-4429-87e6-0e2d50000076ie_chad_rat_standalonewindows assetVersion: type: integer - example: 4 + examples: + - 4 minimum: 0 platform: $ref: ./Platform.yaml unityVersion: type: string default: 2022.3.22f1-DWR - example: 2022.3.22f1-DWR + examples: + - 2022.3.22f1-DWR minLength: 1 variant: type: string diff --git a/openapi/components/schemas/AgeVerificationStatusResult.yaml b/openapi/components/schemas/AgeVerificationStatusResult.yaml new file mode 100644 index 00000000..c35ae0f9 --- /dev/null +++ b/openapi/components/schemas/AgeVerificationStatusResult.yaml @@ -0,0 +1,8 @@ +title: AgeVerificationStatusResult +type: object +description: The caller's age verification status. +properties: + status: + type: string +required: + - status diff --git a/openapi/components/schemas/Agreement.yaml b/openapi/components/schemas/Agreement.yaml index 80109971..87e5441f 100644 --- a/openapi/components/schemas/Agreement.yaml +++ b/openapi/components/schemas/Agreement.yaml @@ -6,11 +6,13 @@ properties: agreementFulltext: type: string description: The full text of the agreement. - example: By clicking OK, I certify that I have the necessary rights to upload this content and that it will not infringe on any third-party legal or intellectual property rights. + examples: + - By clicking OK, I certify that I have the necessary rights to upload this content and that it will not infringe on any third-party legal or intellectual property rights. contentId: type: string description: The id of the content being uploaded, such as a WorldID, AvatarID, or PropID. - example: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 + examples: + - avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 created: type: string description: When the agreement was created @@ -27,7 +29,8 @@ properties: version: type: integer description: The version of the agreement. - example: 1 + examples: + - 1 required: - agreementCode - contentId diff --git a/openapi/components/schemas/AgreementCode.yaml b/openapi/components/schemas/AgreementCode.yaml index 2bf3f176..4d83fd75 100644 --- a/openapi/components/schemas/AgreementCode.yaml +++ b/openapi/components/schemas/AgreementCode.yaml @@ -4,4 +4,5 @@ description: The type of agreement. enum: - content.copyright.owned default: content.copyright.owned -example: content.copyright.owned +examples: + - content.copyright.owned diff --git a/openapi/components/schemas/AgreementStatus.yaml b/openapi/components/schemas/AgreementStatus.yaml index 501b0bcd..419c2215 100644 --- a/openapi/components/schemas/AgreementStatus.yaml +++ b/openapi/components/schemas/AgreementStatus.yaml @@ -4,19 +4,22 @@ properties: agreed: type: boolean description: Whether the user has agreed for this content. - example: false + examples: + - false agreementCode: $ref: ./AgreementCode.yaml contentId: type: string description: The id of the content being uploaded, such as a WorldID, AvatarID, or PropID. - example: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 + examples: + - avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 userId: $ref: ./UserID.yaml version: type: integer description: The version of the agreement. - example: 1 + examples: + - 1 required: - agreed - agreementCode diff --git a/openapi/components/schemas/Avatar.yaml b/openapi/components/schemas/Avatar.yaml index 765ba15d..3fd8be9a 100644 --- a/openapi/components/schemas/Avatar.yaml +++ b/openapi/components/schemas/Avatar.yaml @@ -1,6 +1,5 @@ title: Avatar type: object -description: "" properties: acknowledgements: type: string @@ -17,7 +16,8 @@ properties: description: |- Not present from general search `/avatars`, only on specific requests `/avatars/{avatarId}`. **Deprecation:** `Object` has unknown usage/fields, and is always empty. Use normal `Url` field instead. - attribution: {} + attribution: + $ref: ./Unknown.yaml authorId: $ref: ./UserID.yaml authorName: @@ -40,8 +40,9 @@ properties: type: string minLength: 1 listingDate: - type: string - nullable: true + type: + - string + - "null" lock: type: boolean lowestPrice: @@ -95,18 +96,19 @@ properties: type: object properties: primary: - type: string - nullable: true + type: + - string + - "null" secondary: - type: string - nullable: true + type: + - string + - "null" supplementary: type: array items: type: string tags: type: array - description: " " items: $ref: ./Tag.yaml thumbnailImageUrl: @@ -134,7 +136,8 @@ properties: version: type: integer default: 0 - example: 68 + examples: + - 68 minimum: 0 required: - authorId diff --git a/openapi/components/schemas/AvatarID.yaml b/openapi/components/schemas/AvatarID.yaml index 740c4382..180939e7 100644 --- a/openapi/components/schemas/AvatarID.yaml +++ b/openapi/components/schemas/AvatarID.yaml @@ -1,3 +1,4 @@ title: AvatarID type: string -example: avtr_912d66a4-4714-43b8-8407-7de2cafbf55b +examples: + - avtr_912d66a4-4714-43b8-8407-7de2cafbf55b diff --git a/openapi/components/schemas/AvatarModerationType.yaml b/openapi/components/schemas/AvatarModerationType.yaml index cef00125..29fbbe63 100644 --- a/openapi/components/schemas/AvatarModerationType.yaml +++ b/openapi/components/schemas/AvatarModerationType.yaml @@ -1,5 +1,5 @@ title: AvatarModerationType type: string -enum: +const: block +examples: - block -example: block diff --git a/openapi/components/schemas/AvatarStyle.yaml b/openapi/components/schemas/AvatarStyle.yaml index 51e80b4d..c2b183bd 100644 --- a/openapi/components/schemas/AvatarStyle.yaml +++ b/openapi/components/schemas/AvatarStyle.yaml @@ -1,6 +1,5 @@ title: AvatarStyle type: object -description: "" properties: id: $ref: ./AvatarStyleID.yaml diff --git a/openapi/components/schemas/AvatarStyleID.yaml b/openapi/components/schemas/AvatarStyleID.yaml index 514034bd..f5b7c37f 100644 --- a/openapi/components/schemas/AvatarStyleID.yaml +++ b/openapi/components/schemas/AvatarStyleID.yaml @@ -1,3 +1,4 @@ title: AvatarStyleID type: string -example: avst_f0659ed2-094d-48fb-9e40-de05564d96c7 +examples: + - avst_f0659ed2-094d-48fb-9e40-de05564d96c7 diff --git a/openapi/components/schemas/Badge.yaml b/openapi/components/schemas/Badge.yaml index 75f400e9..2862dcda 100644 --- a/openapi/components/schemas/Badge.yaml +++ b/openapi/components/schemas/Badge.yaml @@ -2,9 +2,10 @@ title: Badge type: object properties: assignedAt: - type: string + type: + - string + - "null" description: only present in CurrentUser badges - nullable: true format: date-time badgeDescription: type: string @@ -16,17 +17,19 @@ properties: badgeName: type: string hidden: - type: boolean + type: + - boolean + - "null" description: only present in CurrentUser badges - nullable: true isQuantifiable: type: boolean showcased: type: boolean updatedAt: - type: string + type: + - string + - "null" description: only present in CurrentUser badges - nullable: true format: date-time required: - badgeDescription diff --git a/openapi/components/schemas/BadgeID.yaml b/openapi/components/schemas/BadgeID.yaml index 28dbf7aa..4ac20cf4 100644 --- a/openapi/components/schemas/BadgeID.yaml +++ b/openapi/components/schemas/BadgeID.yaml @@ -1,3 +1,4 @@ title: BadgeID type: string -example: bdg_a60e514a-8cb7-4702-8f24-2786992be1a8 +examples: + - bdg_a60e514a-8cb7-4702-8f24-2786992be1a8 diff --git a/openapi/components/schemas/Balance.yaml b/openapi/components/schemas/Balance.yaml index d74c0642..e0c41fbc 100644 --- a/openapi/components/schemas/Balance.yaml +++ b/openapi/components/schemas/Balance.yaml @@ -1,6 +1,5 @@ title: Balance type: object -description: "" properties: balance: type: integer diff --git a/openapi/components/schemas/BareError.yaml b/openapi/components/schemas/BareError.yaml index db0b955a..da31431c 100644 --- a/openapi/components/schemas/BareError.yaml +++ b/openapi/components/schemas/BareError.yaml @@ -7,6 +7,7 @@ description: >- properties: error: type: string - example: You're not who I was expecting! + examples: + - You're not who I was expecting! required: - error diff --git a/openapi/components/schemas/Beta.yaml b/openapi/components/schemas/Beta.yaml new file mode 100644 index 00000000..a4c90bc6 --- /dev/null +++ b/openapi/components/schemas/Beta.yaml @@ -0,0 +1,40 @@ +title: Beta +type: object +properties: + active: + type: boolean + betaAppId: + type: string + betaGroupId: + type: string + betaName: + type: string + created_at: + type: string + format: date-time + id: + type: string + examples: + - beta_872e10d7-699d-42cb-9e70-2373a9a044e1 + lastSynchronizedAt: + type: string + format: date-time + type: + type: string + updated_at: + type: string + format: date-time + userFields: + title: BetaUserFields + type: object + description: The fields a registration must supply, keyed by field name. + additionalProperties: + $ref: ./BetaUserField.yaml +required: + - active + - betaName + - created_at + - id + - type + - updated_at + - userFields diff --git a/openapi/components/schemas/BetaUserField.yaml b/openapi/components/schemas/BetaUserField.yaml new file mode 100644 index 00000000..e92b6f55 --- /dev/null +++ b/openapi/components/schemas/BetaUserField.yaml @@ -0,0 +1,13 @@ +title: BetaUserField +type: object +properties: + allowedValues: + type: array + items: + type: string + excludeFromAnalytics: + type: boolean + required: + type: boolean +required: + - required diff --git a/openapi/components/schemas/CalendarDayOfWeek.yaml b/openapi/components/schemas/CalendarDayOfWeek.yaml index c46625c1..c116402c 100644 --- a/openapi/components/schemas/CalendarDayOfWeek.yaml +++ b/openapi/components/schemas/CalendarDayOfWeek.yaml @@ -10,4 +10,5 @@ enum: - TU - WE default: SU -example: FR +examples: + - FR diff --git a/openapi/components/schemas/CalendarEvent.yaml b/openapi/components/schemas/CalendarEvent.yaml index 8cfd6fbf..71bd7bb0 100644 --- a/openapi/components/schemas/CalendarEvent.yaml +++ b/openapi/components/schemas/CalendarEvent.yaml @@ -12,8 +12,9 @@ properties: type: string format: date-time deletedAt: - type: string - nullable: true + type: + - string + - "null" format: date-time description: type: string @@ -32,11 +33,11 @@ properties: id: $ref: ./CalendarID.yaml imageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" imageUrl: type: string - nullable: true interestedUserCount: type: integer isDraft: @@ -50,7 +51,6 @@ properties: $ref: ./CalendarEventOccurrenceKind.yaml occurrenceModified: type: boolean - nullable: true ownerId: $ref: ./GroupID.yaml platforms: @@ -58,17 +58,20 @@ properties: items: $ref: ./CalendarEventPlatform.yaml recurrence: - $ref: ./CalendarEventRecurrence.yaml + anyOf: + - $ref: ./CalendarEventRecurrence.yaml + - type: "null" roleIds: - type: array + type: + - array + - "null" description: Group roles that may join this event - nullable: true items: $ref: ./GroupRoleID.yaml seriesId: - type: string - description: So far unused, always "null" - nullable: true + anyOf: + - $ref: ./CalendarID.yaml + - type: "null" startsAt: type: string format: date-time @@ -82,21 +85,13 @@ properties: minLength: 1 type: type: string - example: event + examples: + - event updatedAt: type: string format: date-time userInterest: - type: object - properties: - createdAt: - type: string - format: date-time - isFollowing: - type: boolean - updatedAt: - type: string - format: date-time + $ref: ./CalendarEventUserInterest.yaml usesInstanceOverflow: type: boolean required: diff --git a/openapi/components/schemas/CalendarEventAccess.yaml b/openapi/components/schemas/CalendarEventAccess.yaml index f8dd9095..30c90fdb 100644 --- a/openapi/components/schemas/CalendarEventAccess.yaml +++ b/openapi/components/schemas/CalendarEventAccess.yaml @@ -5,4 +5,5 @@ enum: - group - public default: public -example: group +examples: + - group diff --git a/openapi/components/schemas/CalendarEventCategory.yaml b/openapi/components/schemas/CalendarEventCategory.yaml index 7a6df512..b610595d 100644 --- a/openapi/components/schemas/CalendarEventCategory.yaml +++ b/openapi/components/schemas/CalendarEventCategory.yaml @@ -16,4 +16,5 @@ enum: - roleplaying - wellness default: other -example: performance +examples: + - performance diff --git a/openapi/components/schemas/CalendarEventDiscovery.yaml b/openapi/components/schemas/CalendarEventDiscovery.yaml index 8b7651df..48056858 100644 --- a/openapi/components/schemas/CalendarEventDiscovery.yaml +++ b/openapi/components/schemas/CalendarEventDiscovery.yaml @@ -3,34 +3,7 @@ type: object properties: nextCursor: type: string - description: |- - Base64-encoded JSON: - type: object - properties: - dataSource: - type: string - enum: - - featured - - personalized - dataIndex: - type: integer - format: int32 - phase: - type: string - enum: - - all - - live - - upcoming - description: see CalendarEventDiscoveryScope - asOf: - type: integer - format: int64 - description: milliseconds since Unix epoch - paramHash: - type: string - format: string - description: Base64-encoded 256-bit hash of the original query parameters - format: string + description: Pass back as the `nextCursor` query parameter to read the page after this one. results: type: array items: diff --git a/openapi/components/schemas/CalendarEventDiscoveryInclusion.yaml b/openapi/components/schemas/CalendarEventDiscoveryInclusion.yaml index dd8f6e39..89f3bc74 100644 --- a/openapi/components/schemas/CalendarEventDiscoveryInclusion.yaml +++ b/openapi/components/schemas/CalendarEventDiscoveryInclusion.yaml @@ -5,4 +5,5 @@ enum: - include - skip default: include -example: include +examples: + - include diff --git a/openapi/components/schemas/CalendarEventDiscoveryScope.yaml b/openapi/components/schemas/CalendarEventDiscoveryScope.yaml index a8853142..ab0f66a0 100644 --- a/openapi/components/schemas/CalendarEventDiscoveryScope.yaml +++ b/openapi/components/schemas/CalendarEventDiscoveryScope.yaml @@ -5,4 +5,5 @@ enum: - live - upcoming default: upcoming -example: upcoming +examples: + - upcoming diff --git a/openapi/components/schemas/CalendarEventFrequency.yaml b/openapi/components/schemas/CalendarEventFrequency.yaml index 44667cce..8289b5a2 100644 --- a/openapi/components/schemas/CalendarEventFrequency.yaml +++ b/openapi/components/schemas/CalendarEventFrequency.yaml @@ -7,4 +7,5 @@ enum: - weekly - yearly default: weekly -example: weekly +examples: + - weekly diff --git a/openapi/components/schemas/CalendarEventOccurrenceKind.yaml b/openapi/components/schemas/CalendarEventOccurrenceKind.yaml index e70967ed..78911ef7 100644 --- a/openapi/components/schemas/CalendarEventOccurrenceKind.yaml +++ b/openapi/components/schemas/CalendarEventOccurrenceKind.yaml @@ -6,4 +6,5 @@ enum: - series - single default: single -example: single +examples: + - single diff --git a/openapi/components/schemas/CalendarEventRecurrence.yaml b/openapi/components/schemas/CalendarEventRecurrence.yaml index 54aa32a1..45f30d33 100644 --- a/openapi/components/schemas/CalendarEventRecurrence.yaml +++ b/openapi/components/schemas/CalendarEventRecurrence.yaml @@ -1,7 +1,6 @@ title: CalendarEventRecurrence type: object description: Details about how a recurring event will be scheduled. If the event is to be scheduled indefinitely, this will lack an "end" property. -nullable: true properties: daysOfWeek: type: array @@ -19,7 +18,8 @@ properties: timezone: type: string description: The timezone the event will be scheduled in, in Area/Location format - example: America/Chicago + examples: + - America/Chicago required: - frequency - interval diff --git a/openapi/components/schemas/CalendarEventRecurrenceEnd.yaml b/openapi/components/schemas/CalendarEventRecurrenceEnd.yaml index b13e3364..6f75fa31 100644 --- a/openapi/components/schemas/CalendarEventRecurrenceEnd.yaml +++ b/openapi/components/schemas/CalendarEventRecurrenceEnd.yaml @@ -9,7 +9,8 @@ properties: date: type: string description: Required for "afterDate" - The date and time after which the event will stop being scheduled, **without timezone or offset** - example: 2026-12-31T23:59:00 + examples: + - 2026-12-31T23:59:00 type: $ref: ./CalendarEventRecurrenceEndType.yaml required: diff --git a/openapi/components/schemas/CalendarEventRecurrenceEndType.yaml b/openapi/components/schemas/CalendarEventRecurrenceEndType.yaml index 3862fae9..465c0604 100644 --- a/openapi/components/schemas/CalendarEventRecurrenceEndType.yaml +++ b/openapi/components/schemas/CalendarEventRecurrenceEndType.yaml @@ -5,4 +5,5 @@ enum: - afterDate - afterOccurrences default: afterDate -example: afterOccurrences +examples: + - afterOccurrences diff --git a/openapi/components/schemas/CalendarEventUserInterest.yaml b/openapi/components/schemas/CalendarEventUserInterest.yaml new file mode 100644 index 00000000..0e230ecd --- /dev/null +++ b/openapi/components/schemas/CalendarEventUserInterest.yaml @@ -0,0 +1,12 @@ +title: CalendarEventUserInterest +type: object +description: The currently logged in user's interest in an event. +properties: + createdAt: + type: string + format: date-time + isFollowing: + type: boolean + updatedAt: + type: string + format: date-time diff --git a/openapi/components/schemas/CalendarID.yaml b/openapi/components/schemas/CalendarID.yaml index 9f019997..557f6416 100644 --- a/openapi/components/schemas/CalendarID.yaml +++ b/openapi/components/schemas/CalendarID.yaml @@ -1,3 +1,4 @@ title: CalendarID type: string -example: cal_6b182f0c-61ef-4bdf-97fe-94f63bcba27b +examples: + - cal_6b182f0c-61ef-4bdf-97fe-94f63bcba27b diff --git a/openapi/components/schemas/Color.yaml b/openapi/components/schemas/Color.yaml new file mode 100644 index 00000000..256579d3 --- /dev/null +++ b/openapi/components/schemas/Color.yaml @@ -0,0 +1,5 @@ +title: Color +type: string +description: "Six hexadecimal digits, without a leading `#`. May be empty." +examples: + - 3cc92c diff --git a/openapi/components/schemas/ConnectedAccountDetails.yaml b/openapi/components/schemas/ConnectedAccountDetails.yaml new file mode 100644 index 00000000..ddb430e1 --- /dev/null +++ b/openapi/components/schemas/ConnectedAccountDetails.yaml @@ -0,0 +1,3 @@ +title: ConnectedAccountDetails +type: object +description: Details of an account on another service linked to this one. diff --git a/openapi/components/schemas/CurrentAvatarImageUrl.yaml b/openapi/components/schemas/CurrentAvatarImageUrl.yaml index e01a718b..fae27102 100644 --- a/openapi/components/schemas/CurrentAvatarImageUrl.yaml +++ b/openapi/components/schemas/CurrentAvatarImageUrl.yaml @@ -1,4 +1,5 @@ title: CurrentAvatarImageUrl type: string description: "When profilePicOverride is not empty, use it instead." -example: "https://api.vrchat.cloud/api/1/file/file_ae46d521-7281-4b38-b365-804b32a1d6a7/1/file" +examples: + - "https://api.vrchat.cloud/api/1/file/file_ae46d521-7281-4b38-b365-804b32a1d6a7/1/file" diff --git a/openapi/components/schemas/CurrentAvatarThumbnailImageUrl.yaml b/openapi/components/schemas/CurrentAvatarThumbnailImageUrl.yaml index cb4f7f72..135b5175 100644 --- a/openapi/components/schemas/CurrentAvatarThumbnailImageUrl.yaml +++ b/openapi/components/schemas/CurrentAvatarThumbnailImageUrl.yaml @@ -1,4 +1,5 @@ title: CurrentAvatarThumbnailImageUrl type: string description: "When profilePicOverride is not empty, use it instead." -example: "https://api.vrchat.cloud/api/1/image/file_aae83ed9-d42d-4d72-9f4b-9f1e41ed17e1/1/256" +examples: + - "https://api.vrchat.cloud/api/1/image/file_aae83ed9-d42d-4d72-9f4b-9f1e41ed17e1/1/256" diff --git a/openapi/components/schemas/CurrentUser.yaml b/openapi/components/schemas/CurrentUser.yaml index 8527effa..61dad2af 100644 --- a/openapi/components/schemas/CurrentUser.yaml +++ b/openapi/components/schemas/CurrentUser.yaml @@ -3,25 +3,31 @@ type: object properties: acceptedPrivacyVersion: type: integer - example: 0 + examples: + - 0 minimum: 0 acceptedTOSVersion: type: integer - example: 7 + examples: + - 7 minimum: 0 accountDeletionDate: - type: string - nullable: true + type: + - string + - "null" format: date accountDeletionLog: - type: array - description: " " - nullable: true + type: + - array + - "null" items: $ref: ./AccountDeletionLog.yaml + accountStanding: + type: string + examples: + - good activeFriends: type: array - description: " " items: $ref: ./UserID.yaml ageVerificationStatus: @@ -30,29 +36,22 @@ properties: $ref: ./AgeVerified.yaml allowAvatarCopying: type: boolean + allowWorldsToCountFriendsInInstance: + type: boolean + description: 'The "Allow Worlds to Count Friends in Instance" setting, introduced under [Udon Methods for Friend Info](https://ask.vrchat.com/t/developer-update-24-september-2026/48972#p-90922-udon-methods-for-friend-info-13) in the Developer Update of September 24, 2026.' appleDetails: - type: object + $ref: ./ConnectedAccountDetails.yaml appleId: type: string authToken: type: string description: The auth token for NEWLY REGISTERED ACCOUNTS ONLY (/auth/register) - badges: - type: array - description: " " - items: - $ref: ./Badge.yaml bannerColor: - type: string + $ref: ./Color.yaml bannerType: type: string - bio: + bannerUrl: type: string - bioLinks: - type: array - description: " " - items: - type: string completedTutorials: type: array items: @@ -103,7 +102,7 @@ properties: items: $ref: ./UserID.yaml googleDetails: - type: object + $ref: ./ConnectedAccountDetails.yaml googleId: type: string hasBirthday: @@ -151,8 +150,9 @@ properties: type: string format: date-time last_mobile: - type: string - nullable: true + type: + - string + - "null" format: date-time last_platform: $ref: ./Platform.yaml @@ -178,7 +178,6 @@ properties: $ref: ./UserID.yaml pastDisplayNames: type: array - description: " " items: $ref: ./PastDisplayName.yaml personalizationOptOut: @@ -190,24 +189,11 @@ properties: platform_history: type: array items: - type: object - properties: - isMobile: - type: boolean - platform: - $ref: ./Platform.yaml - nullable: true - recorded: - type: string - format: date-time + $ref: ./PlatformHistoryEntry.yaml presence: $ref: ./CurrentUserPresence.yaml profileEffect: type: string - profilePicOverride: - type: string - profilePicOverrideThumbnail: - type: string pronouns: type: string pronounsHistory: @@ -215,8 +201,9 @@ properties: items: type: string queuedInstance: - type: string - nullable: true + type: + - string + - "null" receiveMobileInvitations: type: boolean state: @@ -232,14 +219,15 @@ properties: items: type: string steamDetails: - type: object + $ref: ./ConnectedAccountDetails.yaml steamId: type: string tags: type: array items: $ref: ./Tag.yaml - temporaryExpiryDate: {} + temporaryExpiryDate: + $ref: ./Unknown.yaml travelingToInstance: type: string travelingToLocation: @@ -247,28 +235,29 @@ properties: travelingToWorld: type: string twitchDetails: - type: object + $ref: ./ConnectedAccountDetails.yaml twitchId: type: string twoFactorAuthEnabled: type: boolean twoFactorAuthEnabledDate: - type: string - nullable: true + type: + - string + - "null" format: date-time unsubscribe: type: boolean updated_at: type: string format: date-time - userIcon: - type: string userLanguage: - type: string - nullable: true + type: + - string + - "null" userLanguageCode: - type: string - nullable: true + type: + - string + - "null" username: type: string description: Your own unique name, used during login. Distinct from @@ -284,8 +273,6 @@ required: - ageVerificationStatus - ageVerified - allowAvatarCopying - - bio - - bioLinks - currentAvatar - currentAvatarImageUrl - currentAvatarTags @@ -312,8 +299,6 @@ required: - obfuscatedPendingEmail - oculusId - pastDisplayNames - - profilePicOverride - - profilePicOverrideThumbnail - pronouns - pronounsHistory - state @@ -326,5 +311,4 @@ required: - tags - twoFactorAuthEnabled - unsubscribe - - userIcon - usesGeneratedPassword diff --git a/openapi/components/schemas/CurrentUserPresence.yaml b/openapi/components/schemas/CurrentUserPresence.yaml index 065a610e..9e9fd110 100644 --- a/openapi/components/schemas/CurrentUserPresence.yaml +++ b/openapi/components/schemas/CurrentUserPresence.yaml @@ -4,61 +4,79 @@ properties: avatarImageUrl: type: string avatarThumbnail: - type: string - nullable: true + type: + - string + - "null" banner: type: string + bannerColor: + $ref: ./Color.yaml + bannerType: + type: string + bannerUrl: + type: string currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml + type: string debugflag: type: string displayName: type: string groups: - type: array - nullable: true + type: + - array + - "null" items: $ref: ./GroupID.yaml iconFrame: type: string + iconUrl: + type: string id: $ref: ./UserID.yaml instance: - type: string - nullable: true + type: + - string + - "null" instanceType: - type: string + type: + - string + - "null" description: either an InstanceType or an empty string - nullable: true isRejoining: - type: string - nullable: true + type: + - string + - "null" nameplateEffect: type: string platform: - $ref: ./Platform.yaml description: either a Platform or an empty string - nullable: true + anyOf: + - $ref: ./Platform.yaml + - type: "null" profileEffect: type: string profilePicOverride: - type: string - nullable: true + type: + - string + - "null" status: - type: string + type: + - string + - "null" description: either a UserStatus or empty string - nullable: true travelingToInstance: - type: string - nullable: true + type: + - string + - "null" travelingToWorld: - $ref: ./LocationID.yaml - nullable: true + anyOf: + - $ref: ./LocationID.yaml + - type: "null" userIcon: - type: string - nullable: true + type: + - string + - "null" world: - $ref: ./WorldID.yaml - nullable: true + anyOf: + - $ref: ./WorldID.yaml + - type: "null" diff --git a/openapi/components/schemas/DiscordDetails.yaml b/openapi/components/schemas/DiscordDetails.yaml index 93fabf1e..b7db681c 100644 --- a/openapi/components/schemas/DiscordDetails.yaml +++ b/openapi/components/schemas/DiscordDetails.yaml @@ -1,6 +1,5 @@ title: DiscordDetails type: object -description: "" properties: global_name: type: string diff --git a/openapi/components/schemas/DiscordID.yaml b/openapi/components/schemas/DiscordID.yaml index a3a1898c..7f10984f 100644 --- a/openapi/components/schemas/DiscordID.yaml +++ b/openapi/components/schemas/DiscordID.yaml @@ -1,4 +1,5 @@ title: DiscordID type: string description: https://discord.com/developers/docs/reference#snowflakes -example: "1280064052206370848" +examples: + - "1280064052206370848" diff --git a/openapi/components/schemas/DynamicContentRow.yaml b/openapi/components/schemas/DynamicContentRow.yaml index e3dcf8bf..2fdfe3c2 100644 --- a/openapi/components/schemas/DynamicContentRow.yaml +++ b/openapi/components/schemas/DynamicContentRow.yaml @@ -2,13 +2,15 @@ title: DynamicContentRow type: object properties: anyStyle: - type: array - nullable: true + type: + - array + - "null" items: type: string anyTag: - type: array - nullable: true + type: + - array + - "null" items: type: string avatarSpecific: @@ -21,6 +23,10 @@ properties: type: string featuredResults: type: string + groupPool: + type: string + examples: + - mine index: type: integer minimum: 0 @@ -41,20 +47,16 @@ properties: n: type: integer name: - minLength: 1 - x-if: - when: jsonschema - then: - oneOf: - - type: string - - $ref: ./LocalizedString.yaml - else: - type: string + oneOf: + - type: string + minLength: 1 + - $ref: ./LocalizedString.yaml nonFeaturedResults: type: string notag: - type: array - nullable: true + type: + - array + - "null" items: type: string params: @@ -62,28 +64,25 @@ properties: additionalProperties: true personalizedResults: type: string - example: include + examples: + - include platform: - $ref: ./Platform.yaml + type: string description: 'Usually "ThisPlatformSupported", but can also be other values such as "all" or platform specific identifiers.' minLength: 1 region: - type: string - nullable: true + type: + - string + - "null" scope: type: string - example: all + examples: + - all shortName: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - type: "null" - - $ref: ./LocalizedString.yaml - else: - type: string - nullable: true + oneOf: + - type: string + - type: "null" + - $ref: ./LocalizedString.yaml sortHeading: type: string minLength: 1 @@ -94,27 +93,37 @@ properties: type: string minLength: 1 style: - type: string - nullable: true + type: + - string + - "null" tag: - type: string + type: + - string + - "null" description: |- Tag to filter content for this row. Not a `Tag`: that type forbids the empty string, which this field uses for a row that is not tag-filtered. - nullable: true - example: admin_spotlight_pc + examples: + - admin_spotlight_pc tags: - type: array - nullable: true + type: + - array + - "null" items: $ref: ./Tag.yaml type: type: string description: Type is not present if it is a world. - example: avatar + examples: + - avatar upcomingOffsetMinutes: type: integer - example: 10080 + examples: + - 10080 + worldPool: + type: string + examples: + - trending required: - name - platform diff --git a/openapi/components/schemas/EconomyAccount.yaml b/openapi/components/schemas/EconomyAccount.yaml index 01b6648d..60920552 100644 --- a/openapi/components/schemas/EconomyAccount.yaml +++ b/openapi/components/schemas/EconomyAccount.yaml @@ -1,21 +1,24 @@ title: EconomyAccount type: object -nullable: true properties: accountActivatedOn: - type: string - nullable: true + type: + - string + - "null" format: date-time accountId: - type: string - nullable: true + type: + - integer + - "null" accountSellerRegisteredOn: - type: string - nullable: true + type: + - string + - "null" format: date-time accountSellerStatus: - type: string - nullable: true + type: + - string + - "null" blocked: type: boolean canEarn: @@ -24,17 +27,22 @@ properties: type: boolean canSpend: type: boolean + limits: + $ref: ./EconomyAccountLimits.yaml skrillEmail: - type: string - nullable: true + type: + - string + - "null" source: type: string tiliaId: - type: string - nullable: true + type: + - string + - "null" tiliaType: - type: string - nullable: true + type: + - string + - "null" userId: $ref: ./UserID.yaml required: diff --git a/openapi/components/schemas/EconomyAccountLimits.yaml b/openapi/components/schemas/EconomyAccountLimits.yaml new file mode 100644 index 00000000..d1766b1b --- /dev/null +++ b/openapi/components/schemas/EconomyAccountLimits.yaml @@ -0,0 +1,13 @@ +title: EconomyAccountLimits +type: object +description: Returned only when `getLimits` is set. +properties: + buyingTokenMaxPerDay: + type: integer + minimum: 0 + buyingTokenRemainingAllowed: + type: integer + minimum: 0 +required: + - buyingTokenMaxPerDay + - buyingTokenRemainingAllowed diff --git a/openapi/components/schemas/EconomyPayout.yaml b/openapi/components/schemas/EconomyPayout.yaml index 380eb8e6..41043e72 100644 --- a/openapi/components/schemas/EconomyPayout.yaml +++ b/openapi/components/schemas/EconomyPayout.yaml @@ -22,24 +22,30 @@ properties: type: string format: date-time platformPaymentGuid: - type: string - nullable: true + type: + - string + - "null" platformPaymentMethod: - type: string - nullable: true + type: + - string + - "null" reversalDate: - type: string - nullable: true + type: + - string + - "null" format: date-time reversalReason: - type: string - nullable: true + type: + - string + - "null" reversalReasonCode: - type: integer - nullable: true + type: + - integer + - "null" reversalTransactionId: - type: integer - nullable: true + type: + - integer + - "null" transactionId: type: integer required: diff --git a/openapi/components/schemas/EconomyPayoutStatus.yaml b/openapi/components/schemas/EconomyPayoutStatus.yaml index 13a8a3db..c378b051 100644 --- a/openapi/components/schemas/EconomyPayoutStatus.yaml +++ b/openapi/components/schemas/EconomyPayoutStatus.yaml @@ -4,8 +4,9 @@ properties: accountId: type: integer activePayout: - $ref: ./EconomyPayout.yaml - nullable: true + anyOf: + - $ref: ./EconomyPayout.yaml + - type: "null" activePayoutCancellable: type: boolean activePayoutTiliaAmount: diff --git a/openapi/components/schemas/EconomyStatus.yaml b/openapi/components/schemas/EconomyStatus.yaml new file mode 100644 index 00000000..43213516 --- /dev/null +++ b/openapi/components/schemas/EconomyStatus.yaml @@ -0,0 +1,11 @@ +title: EconomyStatus +type: object +description: Whether the economy is accepting requests. +properties: + economyOnline: + type: boolean + economyState: + type: integer +required: + - economyOnline + - economyState diff --git a/openapi/components/schemas/EmojiID.yaml b/openapi/components/schemas/EmojiID.yaml index 422cf195..3ddd8246 100644 --- a/openapi/components/schemas/EmojiID.yaml +++ b/openapi/components/schemas/EmojiID.yaml @@ -1,134 +1,135 @@ title: EmojiID type: string description: Either a FileID or a string constant for default emojis -example: > - Angry: - value: default_angry - Arrow Point: - value: default_arrowpoint - Bats: - value: default_bats - Beachball: - value: default_beachball - Beer: - value: default_beer - Blushing: - value: default_blushing - Boo: - value: default_boo - Broken Heart: - value: default_broken_heart - Candy: - value: default_candy - Candy Cane: - value: default_candy_cane - Candy Corn: - value: default_candy_corn - CantSee: - value: default_cantsee - Champagne: - value: default_champagne - Cloud: - value: default_cloud - Coal: - value: default_coal - Confetti: - value: default_confetti - Crying: - value: default_crying - Drink: - value: default_drink - Exclamation: - value: default_exclamation - Fire: - value: default_fire - Frown: - value: default_frown - Gift: - value: default_gift - Gifts: - value: default_gifts - Gingerbread: - value: default_gingerbread - Go: - value: default_go - Hand Wave: - value: default_hand_wave - Hang Ten: - value: default_hang_ten - Heart: - value: default_heart - Hourglass: - value: default_hourglass - Ice Cream: - value: default_ice_cream - In Love: - value: default_in_love - Jack O Lantern: - value: default_jack_o_lantern - Keyboard: - value: default_keyboard - Kiss: - value: default_kiss - Laugh: - value: default_laugh - Life Ring: - value: default_life_ring - Mistletoe: - value: default_mistletoe - Money: - value: default_money - Music Note: - value: default_music_note - Neon Shades: - value: default_neon_shades - NoHeadphones: - value: default_noheadphones - NoMic: - value: default_nomic - Pineapple: - value: default_pineapple - Pizza: - value: default_pizza - Portal: - value: default_portal - Question: - value: default_question - Shush: - value: default_shush - Skull: - value: default_skull - Smile: - value: default_smile - Snow Fall: - value: default_snow_fall - Snowball: - value: default_snowball - Splash: - value: default_splash - Spooky Ghost: - value: default_spooky_ghost - Stoic: - value: default_stoic - Stop: - value: default_stop - Sun Lotion: - value: default_sun_lotion - Sunglasses: - value: default_sunglasses - Thinking: - value: default_thinking - Thumbs Down: - value: default_thumbs_down - Thumbs Up: - value: default_thumbs_up - Tomato: - value: default_tomato - Tongue Out: - value: default_tongue_out - Web: - value: default_web - Wow: - value: default_wow - Zzz: - value: default_zzz +examples: + - > + Angry: + value: default_angry + Arrow Point: + value: default_arrowpoint + Bats: + value: default_bats + Beachball: + value: default_beachball + Beer: + value: default_beer + Blushing: + value: default_blushing + Boo: + value: default_boo + Broken Heart: + value: default_broken_heart + Candy: + value: default_candy + Candy Cane: + value: default_candy_cane + Candy Corn: + value: default_candy_corn + CantSee: + value: default_cantsee + Champagne: + value: default_champagne + Cloud: + value: default_cloud + Coal: + value: default_coal + Confetti: + value: default_confetti + Crying: + value: default_crying + Drink: + value: default_drink + Exclamation: + value: default_exclamation + Fire: + value: default_fire + Frown: + value: default_frown + Gift: + value: default_gift + Gifts: + value: default_gifts + Gingerbread: + value: default_gingerbread + Go: + value: default_go + Hand Wave: + value: default_hand_wave + Hang Ten: + value: default_hang_ten + Heart: + value: default_heart + Hourglass: + value: default_hourglass + Ice Cream: + value: default_ice_cream + In Love: + value: default_in_love + Jack O Lantern: + value: default_jack_o_lantern + Keyboard: + value: default_keyboard + Kiss: + value: default_kiss + Laugh: + value: default_laugh + Life Ring: + value: default_life_ring + Mistletoe: + value: default_mistletoe + Money: + value: default_money + Music Note: + value: default_music_note + Neon Shades: + value: default_neon_shades + NoHeadphones: + value: default_noheadphones + NoMic: + value: default_nomic + Pineapple: + value: default_pineapple + Pizza: + value: default_pizza + Portal: + value: default_portal + Question: + value: default_question + Shush: + value: default_shush + Skull: + value: default_skull + Smile: + value: default_smile + Snow Fall: + value: default_snow_fall + Snowball: + value: default_snowball + Splash: + value: default_splash + Spooky Ghost: + value: default_spooky_ghost + Stoic: + value: default_stoic + Stop: + value: default_stop + Sun Lotion: + value: default_sun_lotion + Sunglasses: + value: default_sunglasses + Thinking: + value: default_thinking + Thumbs Down: + value: default_thumbs_down + Thumbs Up: + value: default_thumbs_up + Tomato: + value: default_tomato + Tongue Out: + value: default_tongue_out + Web: + value: default_web + Wow: + value: default_wow + Zzz: + value: default_zzz diff --git a/openapi/components/schemas/Favorite.yaml b/openapi/components/schemas/Favorite.yaml index 3393b3fe..845f2ff2 100644 --- a/openapi/components/schemas/Favorite.yaml +++ b/openapi/components/schemas/Favorite.yaml @@ -1,6 +1,5 @@ title: Favorite type: object -description: "" properties: favoriteId: type: string @@ -9,7 +8,6 @@ properties: $ref: ./FavoriteID.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml type: diff --git a/openapi/components/schemas/FavoriteGroup.yaml b/openapi/components/schemas/FavoriteGroup.yaml index 050216ac..947ab1be 100644 --- a/openapi/components/schemas/FavoriteGroup.yaml +++ b/openapi/components/schemas/FavoriteGroup.yaml @@ -1,6 +1,5 @@ title: FavoriteGroup type: object -description: "" properties: displayName: type: string @@ -17,7 +16,6 @@ properties: $ref: ./UserID.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml type: diff --git a/openapi/components/schemas/FavoriteGroupContents.yaml b/openapi/components/schemas/FavoriteGroupContents.yaml new file mode 100644 index 00000000..8a0155ad --- /dev/null +++ b/openapi/components/schemas/FavoriteGroupContents.yaml @@ -0,0 +1,12 @@ +title: FavoriteGroupContents +type: object +properties: + favorites: + type: array + items: + $ref: ./FavoriteGroupContentsEntry.yaml + totalCount: + type: integer +required: + - favorites + - totalCount diff --git a/openapi/components/schemas/FavoriteGroupContentsEntry.yaml b/openapi/components/schemas/FavoriteGroupContentsEntry.yaml new file mode 100644 index 00000000..a1a39d10 --- /dev/null +++ b/openapi/components/schemas/FavoriteGroupContentsEntry.yaml @@ -0,0 +1,25 @@ +title: FavoriteGroupContentsEntry +type: object +description: A favorite alongside the object it points at. The object appears under a property named for the favorite's type. +properties: + avatar: + $ref: ./Avatar.yaml + favoriteId: + type: string + id: + type: string + tags: + type: array + items: + type: string + type: + $ref: ./FavoriteType.yaml + world: + oneOf: + - $ref: ./FavoritedWorld.yaml + - $ref: ./UnavailableWorld.yaml +required: + - favoriteId + - id + - tags + - type diff --git a/openapi/components/schemas/FavoriteGroupID.yaml b/openapi/components/schemas/FavoriteGroupID.yaml index bf9cd65b..ad9a6676 100644 --- a/openapi/components/schemas/FavoriteGroupID.yaml +++ b/openapi/components/schemas/FavoriteGroupID.yaml @@ -1,3 +1,4 @@ title: FavoriteGroupID type: string -example: fvgrp_8a02a44b-dc3a-4a9a-bc77-77fa37996fc7 +examples: + - fvgrp_8a02a44b-dc3a-4a9a-bc77-77fa37996fc7 diff --git a/openapi/components/schemas/FavoriteGroupList.yaml b/openapi/components/schemas/FavoriteGroupList.yaml new file mode 100644 index 00000000..8a1f425d --- /dev/null +++ b/openapi/components/schemas/FavoriteGroupList.yaml @@ -0,0 +1,18 @@ +title: FavoriteGroupList +type: object +description: A user's favorite groups of one type, with the limits that apply to them. +properties: + favoriteGroups: + type: array + items: + $ref: ./FavoriteGroupSummary.yaml + maxFavoriteGroups: + type: integer + description: Only returned when the owner is the currently authenticated user. + minimum: 0 + maxFavoritesPerGroup: + type: integer + description: Only returned when the owner is the currently authenticated user. + minimum: 0 +required: + - favoriteGroups diff --git a/openapi/components/schemas/FavoriteGroupSummary.yaml b/openapi/components/schemas/FavoriteGroupSummary.yaml new file mode 100644 index 00000000..1e4162b8 --- /dev/null +++ b/openapi/components/schemas/FavoriteGroupSummary.yaml @@ -0,0 +1,23 @@ +title: FavoriteGroupSummary +type: object +description: A favorite group as listed for one favorite type. +properties: + displayName: + type: string + minLength: 1 + id: + $ref: ./FavoriteGroupID.yaml + name: + type: string + minLength: 1 + numFavorites: + type: integer + minimum: 0 + visibility: + $ref: ./FavoriteGroupVisibility.yaml +required: + - displayName + - id + - name + - numFavorites + - visibility diff --git a/openapi/components/schemas/FavoriteGroupVisibility.yaml b/openapi/components/schemas/FavoriteGroupVisibility.yaml index aae29acb..7230a78c 100644 --- a/openapi/components/schemas/FavoriteGroupVisibility.yaml +++ b/openapi/components/schemas/FavoriteGroupVisibility.yaml @@ -5,4 +5,5 @@ enum: - private - public default: private -example: private +examples: + - private diff --git a/openapi/components/schemas/FavoriteID.yaml b/openapi/components/schemas/FavoriteID.yaml index 797eca28..bbf4c0c7 100644 --- a/openapi/components/schemas/FavoriteID.yaml +++ b/openapi/components/schemas/FavoriteID.yaml @@ -1,3 +1,4 @@ title: FavoriteID type: string -example: fvrt_9568d189-8776-44a5-a8c8-defc981e44de +examples: + - fvrt_9568d189-8776-44a5-a8c8-defc981e44de diff --git a/openapi/components/schemas/FavoriteName.yaml b/openapi/components/schemas/FavoriteName.yaml index 56b6ad89..82218ba9 100644 --- a/openapi/components/schemas/FavoriteName.yaml +++ b/openapi/components/schemas/FavoriteName.yaml @@ -1,8 +1,9 @@ title: FavoriteName type: string default: group_0 -example: > - avatar: [ avatars1, avatars2, avatars3, avatars4, avatars5, avatars6 ] - friend: [ group_0, group_1, group_2 ] - vrcPlusWorld: [ vrcPlusWorlds1, vrcPlusWorlds2, vrcPlusWorlds3, vrcPlusWorlds4 ] - world: [ worlds1, worlds2, worlds3, worlds4 ] +examples: + - > + avatar: [ avatars1, avatars2, avatars3, avatars4, avatars5, avatars6 ] + friend: [ group_0, group_1, group_2 ] + vrcPlusWorld: [ vrcPlusWorlds1, vrcPlusWorlds2, vrcPlusWorlds3, vrcPlusWorlds4 ] + world: [ worlds1, worlds2, worlds3, worlds4 ] diff --git a/openapi/components/schemas/FavoritedWorld.yaml b/openapi/components/schemas/FavoritedWorld.yaml index c1c18b55..4c723bf1 100644 --- a/openapi/components/schemas/FavoritedWorld.yaml +++ b/openapi/components/schemas/FavoritedWorld.yaml @@ -1,6 +1,5 @@ title: FavoritedWorld type: object -description: "" properties: authorId: $ref: ./UserID.yaml @@ -9,7 +8,8 @@ properties: minLength: 1 capacity: type: integer - example: 8 + examples: + - 8 created_at: type: string format: date-time @@ -17,10 +17,11 @@ properties: $ref: ./InstanceContentSettings.yaml description: type: string - minLength: 1 + minLength: 0 disabledPropAbilities: type: array - items: {} + items: + $ref: ./Unknown.yaml favoriteGroup: type: string minLength: 1 @@ -29,7 +30,8 @@ properties: favorites: type: integer default: 0 - example: 12024 + examples: + - 12024 minimum: 0 featured: type: boolean @@ -37,24 +39,29 @@ properties: heat: type: integer default: 0 - example: 5 + examples: + - 5 minimum: 0 id: $ref: ./WorldID.yaml imageUrl: type: string minLength: 1 + isHypeTrainEligible: + type: boolean labsPublicationDate: type: string - example: none + examples: + - none minLength: 1 name: type: string - minLength: 1 + minLength: 0 occupants: type: integer default: 0 - example: 47 + examples: + - 47 minimum: 0 organization: type: string @@ -63,23 +70,28 @@ properties: popularity: type: integer default: 0 - example: 8 + examples: + - 8 minimum: 0 previewYoutubeId: - type: string - nullable: true + type: + - string + - "null" publicationDate: type: string - example: none + examples: + - none minLength: 1 recommendedCapacity: type: integer - example: 16 + examples: + - 16 releaseStatus: $ref: ./ReleaseStatus.yaml + storeId: + $ref: ./StoreID.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml thumbnailImageUrl: @@ -91,7 +103,6 @@ properties: $ref: ./UdonProductId.yaml unityPackages: type: array - description: " " items: $ref: ./UnityPackage.yaml minItems: 1 @@ -108,16 +119,14 @@ properties: visits: type: integer default: 0 - example: 9988675 + examples: + - 9988675 minimum: 0 required: - authorName - capacity - - favoriteGroup - - favoriteId - id - imageUrl - name - - occupants - releaseStatus - thumbnailImageUrl diff --git a/openapi/components/schemas/Feedback.yaml b/openapi/components/schemas/Feedback.yaml index a6a84c9f..5c91e800 100644 --- a/openapi/components/schemas/Feedback.yaml +++ b/openapi/components/schemas/Feedback.yaml @@ -6,11 +6,13 @@ properties: commenterName: type: string contentAuthorId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" contentAuthorName: - type: string - nullable: true + type: + - string + - "null" contentId: type: string contentName: @@ -18,11 +20,13 @@ properties: contentType: type: string contentVersion: - type: integer - nullable: true + type: + - integer + - "null" description: - type: string - nullable: true + type: + - string + - "null" id: $ref: ./FeedbackID.yaml reason: diff --git a/openapi/components/schemas/FeedbackID.yaml b/openapi/components/schemas/FeedbackID.yaml index aae13ac3..bf241cf7 100644 --- a/openapi/components/schemas/FeedbackID.yaml +++ b/openapi/components/schemas/FeedbackID.yaml @@ -1,3 +1,4 @@ title: FeedbackID type: string -example: feedback_8cffb23a-f961-444e-b496-0196d1c90adb +examples: + - feedback_8cffb23a-f961-444e-b496-0196d1c90adb diff --git a/openapi/components/schemas/File.yaml b/openapi/components/schemas/File.yaml index 6b9feffe..0e4fbd3c 100644 --- a/openapi/components/schemas/File.yaml +++ b/openapi/components/schemas/File.yaml @@ -1,12 +1,12 @@ title: File type: object -description: "" properties: animationStyle: $ref: ./ImageAnimationStyle.yaml extension: type: string - example: .unitypackage + examples: + - .unitypackage minLength: 1 frames: type: integer @@ -28,22 +28,21 @@ properties: $ref: ./MIMEType.yaml modifiedThumbnailFileName: type: string - example: thumbnails/file_00000000-0000-0000-0000-000000000000.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff.1.modified-thumbnail-256.png + examples: + - thumbnails/file_00000000-0000-0000-0000-000000000000.ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff.1.modified-thumbnail-256.png name: type: string - description: "" - example: Example File + examples: + - Example File minLength: 0 ownerId: $ref: ./UserID.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml versions: type: array - description: " " items: $ref: ./FileVersion.yaml minItems: 1 diff --git a/openapi/components/schemas/FileData.yaml b/openapi/components/schemas/FileData.yaml index 58c6312d..4ca3c330 100644 --- a/openapi/components/schemas/FileData.yaml +++ b/openapi/components/schemas/FileData.yaml @@ -1,6 +1,5 @@ title: FileData type: object -description: "" properties: category: type: string diff --git a/openapi/components/schemas/FileID.yaml b/openapi/components/schemas/FileID.yaml index 90a3c852..15fb4ea6 100644 --- a/openapi/components/schemas/FileID.yaml +++ b/openapi/components/schemas/FileID.yaml @@ -1,3 +1,4 @@ title: FileID type: string -example: file_ce35d830-e20a-4df0-a6d4-5aaef4508044 +examples: + - file_ce35d830-e20a-4df0-a6d4-5aaef4508044 diff --git a/openapi/components/schemas/FileStatus.yaml b/openapi/components/schemas/FileStatus.yaml index 9b9bb9d4..940bef01 100644 --- a/openapi/components/schemas/FileStatus.yaml +++ b/openapi/components/schemas/FileStatus.yaml @@ -6,4 +6,5 @@ enum: - queued - waiting default: waiting -example: complete +examples: + - complete diff --git a/openapi/components/schemas/FileUploadURL.yaml b/openapi/components/schemas/FileUploadURL.yaml index 0d47a95a..6c00165f 100644 --- a/openapi/components/schemas/FileUploadURL.yaml +++ b/openapi/components/schemas/FileUploadURL.yaml @@ -1,10 +1,8 @@ title: FileUploadURL type: object -description: "" properties: url: type: string - description: "" minLength: 1 required: - url diff --git a/openapi/components/schemas/FileVersion.yaml b/openapi/components/schemas/FileVersion.yaml index 405493c6..9e46a4d5 100644 --- a/openapi/components/schemas/FileVersion.yaml +++ b/openapi/components/schemas/FileVersion.yaml @@ -1,6 +1,5 @@ title: FileVersion type: object -description: "" properties: created_at: type: string diff --git a/openapi/components/schemas/FileVersionUploadStatus.yaml b/openapi/components/schemas/FileVersionUploadStatus.yaml index 3bf8b960..b9d2f332 100644 --- a/openapi/components/schemas/FileVersionUploadStatus.yaml +++ b/openapi/components/schemas/FileVersionUploadStatus.yaml @@ -1,6 +1,5 @@ title: FileVersionUploadStatus type: object -description: "" properties: etags: type: array @@ -10,15 +9,18 @@ properties: minItems: 0 fileName: type: string - example: Avatar-MyAvatar-Un.file_00000000-0000-0000-0000-000000000000.1.unitypackage + examples: + - Avatar-MyAvatar-Un.file_00000000-0000-0000-0000-000000000000.1.unitypackage minLength: 1 maxParts: type: integer - example: 1000 + examples: + - 1000 minimum: 1 nextPartNumber: type: integer - example: 0 + examples: + - 0 minimum: 0 parts: type: array @@ -27,7 +29,8 @@ properties: minItems: 0 uploadId: type: string - example: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxx + examples: + - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx..xxxxxxxxxxxxxxxxxxxxxxx minLength: 1 required: - etags diff --git a/openapi/components/schemas/FriendRequestStatus.yaml b/openapi/components/schemas/FriendRequestStatus.yaml index 26bbfaaf..5eb1c878 100644 --- a/openapi/components/schemas/FriendRequestStatus.yaml +++ b/openapi/components/schemas/FriendRequestStatus.yaml @@ -1,4 +1,5 @@ title: FriendRequestStatus type: string description: State of a friend request between the caller and this user. VRChat sends the string `"null"`, not JSON `null`. -example: "null" +examples: + - "null" diff --git a/openapi/components/schemas/Group.yaml b/openapi/components/schemas/Group.yaml index e64115dd..62878f5d 100644 --- a/openapi/components/schemas/Group.yaml +++ b/openapi/components/schemas/Group.yaml @@ -3,10 +3,12 @@ type: object properties: ageVerificationBetaCode: type: string - example: abc1234 + examples: + - abc1234 ageVerificationBetaSlots: type: number - example: 500 + examples: + - 500 ageVerificationSlotsAvailable: type: boolean allowGroupJoinPrompt: @@ -16,11 +18,13 @@ properties: items: type: string bannerId: - type: string - nullable: true + type: + - string + - "null" bannerUrl: - type: string - nullable: true + type: + - string + - "null" createdAt: type: string format: date-time @@ -33,11 +37,13 @@ properties: items: $ref: ./GroupGallery.yaml iconId: - type: string - nullable: true + type: + - string + - "null" iconUrl: - type: string - nullable: true + type: + - string + - "null" id: $ref: ./GroupID.yaml isVerified: @@ -50,8 +56,9 @@ properties: items: type: string lastPostCreatedAt: - type: string - nullable: true + type: + - string + - "null" format: date-time links: type: array @@ -65,12 +72,15 @@ properties: membershipStatus: $ref: ./GroupMemberStatus.yaml myMember: - $ref: ./GroupMyMember.yaml - nullable: true + anyOf: + - $ref: ./GroupMyMember.yaml + - type: "null" name: type: string - nameplateId: {} - nameplateUrl: {} + nameplateId: + $ref: ./Unknown.yaml + nameplateUrl: + $ref: ./Unknown.yaml onlineMemberCount: type: integer ownerId: @@ -78,23 +88,30 @@ properties: privacy: $ref: ./GroupPrivacy.yaml roles: - type: array + type: + - array + - "null" description: Only returned if ?includeRoles=true is specified. - nullable: true items: $ref: ./GroupRole.yaml rules: - type: string - nullable: true + type: + - string + - "null" shortCode: $ref: ./GroupShortCode.yaml + storeId: + anyOf: + - $ref: ./StoreID.yaml + - type: "null" tags: type: array items: $ref: ./Tag.yaml transferTargetId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" updatedAt: type: string format: date-time diff --git a/openapi/components/schemas/GroupAccessType.yaml b/openapi/components/schemas/GroupAccessType.yaml index 5d29ed39..829f5e09 100644 --- a/openapi/components/schemas/GroupAccessType.yaml +++ b/openapi/components/schemas/GroupAccessType.yaml @@ -6,4 +6,5 @@ enum: - plus - public default: members -example: members +examples: + - members diff --git a/openapi/components/schemas/GroupAnnouncement.yaml b/openapi/components/schemas/GroupAnnouncement.yaml index d7e680dd..60012ccc 100644 --- a/openapi/components/schemas/GroupAnnouncement.yaml +++ b/openapi/components/schemas/GroupAnnouncement.yaml @@ -5,38 +5,48 @@ description: >- answers with the post fields below as well as the announcement ones. properties: authorId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" createdAt: - type: string - nullable: true + type: + - string + - "null" format: date-time editorId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" groupId: - $ref: ./GroupID.yaml - nullable: true + anyOf: + - $ref: ./GroupID.yaml + - type: "null" id: - $ref: ./GroupAnnouncementID.yaml - nullable: true + anyOf: + - $ref: ./GroupAnnouncementID.yaml + - type: "null" imageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" imageUrl: - type: string - nullable: true + type: + - string + - "null" roleIds: $ref: ./GroupRoleIDList.yaml text: - type: string - nullable: true + type: + - string + - "null" title: - type: string - nullable: true + type: + - string + - "null" updatedAt: - type: string - nullable: true + type: + - string + - "null" format: date-time visibility: type: string diff --git a/openapi/components/schemas/GroupAnnouncementID.yaml b/openapi/components/schemas/GroupAnnouncementID.yaml index 9ca6f168..1a065fa7 100644 --- a/openapi/components/schemas/GroupAnnouncementID.yaml +++ b/openapi/components/schemas/GroupAnnouncementID.yaml @@ -1,3 +1,4 @@ title: GroupAnnouncementID type: string -example: gpos_71a7ff59-112c-4e78-a990-c7cc650776e5 +examples: + - gpos_71a7ff59-112c-4e78-a990-c7cc650776e5 diff --git a/openapi/components/schemas/GroupAuditLogEntry.yaml b/openapi/components/schemas/GroupAuditLogEntry.yaml index 9757bf34..ca1f8ba6 100644 --- a/openapi/components/schemas/GroupAuditLogEntry.yaml +++ b/openapi/components/schemas/GroupAuditLogEntry.yaml @@ -1,33 +1,73 @@ title: GroupAuditLogEntry -type: object -properties: - actorDisplayName: - type: string - actorId: - $ref: ./UserID.yaml - created_at: - type: string - format: date-time - data: - type: object - description: The data associated with the event. The format of this data is dependent on the event type. - example: - description: - new: "My exciting new group. It's pretty nifty!" - old: "My exciting new group. It's pretty nifty!" - joinState: - new: request - old: closed - description: - type: string - description: A human-readable description of the event. - example: Group role updated - eventType: - $ref: ./GroupAuditLogEntryType.yaml - groupId: - $ref: ./GroupID.yaml - id: - $ref: ./GroupAuditLogID.yaml - targetId: - type: string - description: Typically a UserID, GroupID, GroupRoleID, or Location, but could be other types of IDs. +description: A group audit log entry. The shape of `data` depends on `eventType`. +discriminator: + defaultMapping: ./GroupAuditLogEntryUnknown.yaml + mapping: + group.announcement: ./GroupAuditLogEntryGroupAnnouncement.yaml + group.calendarEvent.create: ./GroupAuditLogEntryGroupCalendarEventCreate.yaml + group.calendarEvent.delete: ./GroupAuditLogEntryGroupCalendarEventDelete.yaml + group.gallery.create: ./GroupAuditLogEntryGroupGalleryCreate.yaml + group.gallery.delete: ./GroupAuditLogEntryGroupGalleryDelete.yaml + group.gallery.update: ./GroupAuditLogEntryGroupGalleryUpdate.yaml + group.instance.announcement: ./GroupAuditLogEntryGroupInstanceAnnouncement.yaml + group.instance.close: ./GroupAuditLogEntryGroupInstanceClose.yaml + group.instance.create: ./GroupAuditLogEntryGroupInstanceCreate.yaml + group.instance.kick: ./GroupAuditLogEntryGroupInstanceKick.yaml + group.instance.warn: ./GroupAuditLogEntryGroupInstanceWarn.yaml + group.invite.cancel: ./GroupAuditLogEntryGroupInviteCancel.yaml + group.invite.create: ./GroupAuditLogEntryGroupInviteCreate.yaml + group.member.join: ./GroupAuditLogEntryGroupMemberJoin.yaml + group.member.leave: ./GroupAuditLogEntryGroupMemberLeave.yaml + group.member.remove: ./GroupAuditLogEntryGroupMemberRemove.yaml + group.member.role.assign: ./GroupAuditLogEntryGroupMemberRoleAssign.yaml + group.member.role.unassign: ./GroupAuditLogEntryGroupMemberRoleUnassign.yaml + group.member.user.update: ./GroupAuditLogEntryGroupMemberUserUpdate.yaml + group.post.create: ./GroupAuditLogEntryGroupPostCreate.yaml + group.post.delete: ./GroupAuditLogEntryGroupPostDelete.yaml + group.post.update: ./GroupAuditLogEntryGroupPostUpdate.yaml + group.request.block: ./GroupAuditLogEntryGroupRequestBlock.yaml + group.request.create: ./GroupAuditLogEntryGroupRequestCreate.yaml + group.request.reject: ./GroupAuditLogEntryGroupRequestReject.yaml + group.request.withdraw: ./GroupAuditLogEntryGroupRequestWithdraw.yaml + group.role.create: ./GroupAuditLogEntryGroupRoleCreate.yaml + group.role.delete: ./GroupAuditLogEntryGroupRoleDelete.yaml + group.role.update: ./GroupAuditLogEntryGroupRoleUpdate.yaml + group.update: ./GroupAuditLogEntryGroupUpdate.yaml + group.user.ban: ./GroupAuditLogEntryGroupUserBan.yaml + group.user.unban: ./GroupAuditLogEntryGroupUserUnban.yaml + propertyName: eventType + x-vrchatapi-downlevel-default-mapping: GroupAuditLogEntryUnknown +oneOf: + - $ref: ./GroupAuditLogEntryGroupAnnouncement.yaml + - $ref: ./GroupAuditLogEntryGroupCalendarEventCreate.yaml + - $ref: ./GroupAuditLogEntryGroupCalendarEventDelete.yaml + - $ref: ./GroupAuditLogEntryGroupGalleryCreate.yaml + - $ref: ./GroupAuditLogEntryGroupGalleryDelete.yaml + - $ref: ./GroupAuditLogEntryGroupGalleryUpdate.yaml + - $ref: ./GroupAuditLogEntryGroupInstanceAnnouncement.yaml + - $ref: ./GroupAuditLogEntryGroupInstanceClose.yaml + - $ref: ./GroupAuditLogEntryGroupInstanceCreate.yaml + - $ref: ./GroupAuditLogEntryGroupInstanceKick.yaml + - $ref: ./GroupAuditLogEntryGroupInstanceWarn.yaml + - $ref: ./GroupAuditLogEntryGroupInviteCancel.yaml + - $ref: ./GroupAuditLogEntryGroupInviteCreate.yaml + - $ref: ./GroupAuditLogEntryGroupMemberJoin.yaml + - $ref: ./GroupAuditLogEntryGroupMemberLeave.yaml + - $ref: ./GroupAuditLogEntryGroupMemberRemove.yaml + - $ref: ./GroupAuditLogEntryGroupMemberRoleAssign.yaml + - $ref: ./GroupAuditLogEntryGroupMemberRoleUnassign.yaml + - $ref: ./GroupAuditLogEntryGroupMemberUserUpdate.yaml + - $ref: ./GroupAuditLogEntryGroupPostCreate.yaml + - $ref: ./GroupAuditLogEntryGroupPostDelete.yaml + - $ref: ./GroupAuditLogEntryGroupPostUpdate.yaml + - $ref: ./GroupAuditLogEntryGroupRequestBlock.yaml + - $ref: ./GroupAuditLogEntryGroupRequestCreate.yaml + - $ref: ./GroupAuditLogEntryGroupRequestReject.yaml + - $ref: ./GroupAuditLogEntryGroupRequestWithdraw.yaml + - $ref: ./GroupAuditLogEntryGroupRoleCreate.yaml + - $ref: ./GroupAuditLogEntryGroupRoleDelete.yaml + - $ref: ./GroupAuditLogEntryGroupRoleUpdate.yaml + - $ref: ./GroupAuditLogEntryGroupUpdate.yaml + - $ref: ./GroupAuditLogEntryGroupUserBan.yaml + - $ref: ./GroupAuditLogEntryGroupUserUnban.yaml + - $ref: ./GroupAuditLogEntryUnknown.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryBase.yaml b/openapi/components/schemas/GroupAuditLogEntryBase.yaml new file mode 100644 index 00000000..3441d02f --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryBase.yaml @@ -0,0 +1,33 @@ +title: GroupAuditLogEntryBase +type: object +properties: + actorDisplayName: + type: string + description: The display name of the user who performed the action. + actorId: + $ref: ./UserID.yaml + description: The ID of the user who performed the action. + created_at: + type: string + description: When the action was performed. + format: date-time + description: + type: string + description: A human-readable description of the event. + eventType: + $ref: ./GroupAuditLogEntryType.yaml + description: The type of event that occurred. + groupId: + $ref: ./GroupID.yaml + description: The ID of the group the entry belongs to. + id: + $ref: ./GroupAuditLogID.yaml + description: The unique ID of this audit log entry. +required: + - actorDisplayName + - actorId + - created_at + - description + - eventType + - groupId + - id diff --git a/openapi/components/schemas/GroupAuditLogEntryBooleanChange.yaml b/openapi/components/schemas/GroupAuditLogEntryBooleanChange.yaml new file mode 100644 index 00000000..b24ac2f5 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryBooleanChange.yaml @@ -0,0 +1,11 @@ +title: GroupAuditLogEntryBooleanChange +type: object +description: A boolean field's value before and after an update. +properties: + new: + type: boolean + old: + type: boolean +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogEntryDataEmpty.yaml b/openapi/components/schemas/GroupAuditLogEntryDataEmpty.yaml new file mode 100644 index 00000000..88689727 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataEmpty.yaml @@ -0,0 +1,4 @@ +title: GroupAuditLogEntryDataEmpty +type: object +additionalProperties: false +properties: {} diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupAnnouncement.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupAnnouncement.yaml new file mode 100644 index 00000000..c5b72b0e --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupAnnouncement.yaml @@ -0,0 +1,26 @@ +title: GroupAuditLogEntryDataGroupAnnouncement +type: object +properties: + authorId: + $ref: ./UserID.yaml + description: The ID of the announcement author. + imageId: + description: The image file ID attached to the announcement. + anyOf: + - $ref: ./FileID.yaml + - type: "null" + sendNotification: + type: boolean + description: Whether a notification was sent for this announcement. + text: + type: string + description: The text content of the announcement. + title: + type: string + description: The title of the announcement. +required: + - authorId + - imageId + - sendNotification + - text + - title diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupCalendarEventCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupCalendarEventCreate.yaml new file mode 100644 index 00000000..de9892e0 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupCalendarEventCreate.yaml @@ -0,0 +1,25 @@ +title: GroupAuditLogEntryDataGroupCalendarEventCreate +type: object +properties: + accessType: + $ref: ./CalendarEventAccess.yaml + description: + type: string + description: The description of the calendar event. + imageId: + description: The image file ID for the event. + anyOf: + - $ref: ./FileID.yaml + - type: "null" + title: + type: string + description: The title of the calendar event. + type: + type: string + description: The type of calendar entry. +required: + - accessType + - description + - imageId + - title + - type diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupCalendarEventDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupCalendarEventDelete.yaml new file mode 100644 index 00000000..fdbf118c --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupCalendarEventDelete.yaml @@ -0,0 +1,125 @@ +title: GroupAuditLogEntryDataGroupCalendarEventDelete +type: object +properties: + category: + type: string + description: The category of the event. + closeInstanceAfterEndMinutes: + type: integer + description: Minutes after the event ends to close the instance. + createdAt: + type: string + description: The creation timestamp. + format: date-time + deletedAt: + type: + - string + - "null" + description: The deletion timestamp. + format: date-time + durationInMs: + type: integer + description: The duration of the event in milliseconds. + endsAt: + type: string + description: The end timestamp. + format: date-time + featured: + type: boolean + description: Whether the event is featured. + guestEarlyJoinMinutes: + type: integer + description: Minutes before the start that guests can join. + hostEarlyJoinMinutes: + type: integer + description: Minutes before the start that hosts can join. + interestedUserCount: + type: integer + description: The number of interested users. + isDraft: + type: boolean + description: Whether the event is a draft. + languages: + type: array + description: The languages for the event. + items: + type: string + occurrenceKind: + $ref: ./CalendarEventOccurrenceKind.yaml + occurrenceModified: + type: + - string + - "null" + ownerId: + $ref: ./GroupID.yaml + description: The ID of the group that owns the event. + platforms: + type: array + description: The supported platforms. + items: + type: string + recurrence: + description: The recurrence rule. + anyOf: + - $ref: ./CalendarEventRecurrence.yaml + - type: "null" + roleIds: + type: + - array + - "null" + description: Group roles that may join this event. + items: + $ref: ./GroupRoleID.yaml + seriesId: + type: + - string + - "null" + description: The ID of the recurring series the event belongs to. + shortCode: + type: + - string + - "null" + description: The short code. + startsAt: + type: string + description: The start timestamp. + format: date-time + tags: + type: array + description: The event tags. + items: + type: string + updatedAt: + type: string + description: The last update timestamp. + format: date-time + usesInstanceOverflow: + type: boolean + description: Whether the event uses instance overflow. +required: + - category + - closeInstanceAfterEndMinutes + - createdAt + - deletedAt + - durationInMs + - endsAt + - featured + - guestEarlyJoinMinutes + - hostEarlyJoinMinutes + - interestedUserCount + - isDraft + - languages + - occurrenceKind + - occurrenceModified + - ownerId + - platforms + - recurrence + - roleIds + - seriesId + - shortCode + - startsAt + - tags + - updatedAt + - usesInstanceOverflow +allOf: + - $ref: ./GroupAuditLogEntryDataGroupCalendarEventCreate.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryCreate.yaml new file mode 100644 index 00000000..8d59f44a --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryCreate.yaml @@ -0,0 +1,48 @@ +title: GroupAuditLogEntryDataGroupGalleryCreate +type: object +properties: + description: + type: string + description: The gallery description. + membersOnly: + type: boolean + description: Whether the gallery is members only. + name: + type: string + description: The gallery name. + roleIdsToAutoApprove: + type: + - array + - "null" + description: The role IDs whose submissions are approved automatically. + items: + $ref: ./GroupRoleID.yaml + roleIdsToManage: + type: + - array + - "null" + description: The role IDs that can manage the gallery. + items: + $ref: ./GroupRoleID.yaml + roleIdsToSubmit: + type: + - array + - "null" + description: The role IDs that can submit to the gallery. + items: + $ref: ./GroupRoleID.yaml + roleIdsToView: + type: + - array + - "null" + description: The role IDs that can view the gallery. + items: + $ref: ./GroupRoleID.yaml +required: + - description + - membersOnly + - name + - roleIdsToAutoApprove + - roleIdsToManage + - roleIdsToSubmit + - roleIdsToView diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryDelete.yaml new file mode 100644 index 00000000..525611ad --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryDelete.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryDataGroupGalleryDelete +type: object +properties: + createdAt: + type: string + description: The creation timestamp of the gallery. + format: date-time + updatedAt: + type: string + description: The last update timestamp of the gallery. + format: date-time +required: + - createdAt + - updatedAt +allOf: + - $ref: ./GroupAuditLogEntryDataGroupGalleryCreate.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryUpdate.yaml new file mode 100644 index 00000000..038c348d --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupGalleryUpdate.yaml @@ -0,0 +1,8 @@ +title: GroupAuditLogEntryDataGroupGalleryUpdate +type: object +description: Carries only the fields the update changed. +properties: + membersOnly: + $ref: ./GroupAuditLogEntryBooleanChange.yaml + name: + $ref: ./GroupAuditLogEntryStringChange.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceAnnouncement.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceAnnouncement.yaml new file mode 100644 index 00000000..a8caa85c --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceAnnouncement.yaml @@ -0,0 +1,12 @@ +title: GroupAuditLogEntryDataGroupInstanceAnnouncement +type: object +properties: + message: + type: string + description: The announcement message. + title: + type: string + description: The announcement title. +required: + - message + - title diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceClose.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceClose.yaml new file mode 100644 index 00000000..f3c0a0f7 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceClose.yaml @@ -0,0 +1,15 @@ +title: GroupAuditLogEntryDataGroupInstanceClose +type: object +properties: + groupAccessType: + $ref: ./GroupAccessType.yaml + roleIds: + type: + - array + - "null" + description: The role IDs that have access to the instance. + items: + $ref: ./GroupRoleID.yaml +required: + - groupAccessType + - roleIds diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceCreate.yaml new file mode 100644 index 00000000..e5dfdd94 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceCreate.yaml @@ -0,0 +1,17 @@ +title: GroupAuditLogEntryDataGroupInstanceCreate +type: object +properties: + calendarEntryId: + description: The calendar entry ID if the instance was created from a calendar event. + anyOf: + - $ref: ./CalendarID.yaml + - type: "null" + groupAccessType: + $ref: ./GroupAccessType.yaml + roleIds: + $ref: ./GroupRoleIDList.yaml + description: The role IDs that have access to the instance. +required: + - calendarEntryId + - groupAccessType + - roleIds diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceModeration.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceModeration.yaml new file mode 100644 index 00000000..2d95bf66 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupInstanceModeration.yaml @@ -0,0 +1,8 @@ +title: GroupAuditLogEntryDataGroupInstanceModeration +type: object +properties: + location: + $ref: ./LocationID.yaml + description: The instance the target was kicked from or warned in. +required: + - location diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupMemberRole.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupMemberRole.yaml new file mode 100644 index 00000000..8aaa77d9 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupMemberRole.yaml @@ -0,0 +1,12 @@ +title: GroupAuditLogEntryDataGroupMemberRole +type: object +properties: + roleId: + $ref: ./GroupRoleID.yaml + description: The ID of the role that was assigned or unassigned. + roleName: + type: string + description: The name of the role that was assigned or unassigned. +required: + - roleId + - roleName diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupMemberUserUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupMemberUserUpdate.yaml new file mode 100644 index 00000000..49ea9287 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupMemberUserUpdate.yaml @@ -0,0 +1,6 @@ +title: GroupAuditLogEntryDataGroupMemberUserUpdate +type: object +description: Carries only the fields the update changed. +properties: + managerNotes: + $ref: ./GroupAuditLogEntryStringChange.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupPost.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupPost.yaml new file mode 100644 index 00000000..d6bf219d --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupPost.yaml @@ -0,0 +1,25 @@ +title: GroupAuditLogEntryDataGroupPost +type: object +properties: + authorId: + $ref: ./UserID.yaml + description: The ID of the post author. + imageId: + description: The image file ID attached to the post. + anyOf: + - $ref: ./FileID.yaml + - type: "null" + text: + type: string + description: The text content of the post. + title: + type: string + description: The title of the post. + visibility: + $ref: ./GroupPostVisibility.yaml +required: + - authorId + - imageId + - text + - title + - visibility diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupPostCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupPostCreate.yaml new file mode 100644 index 00000000..b364d3b2 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupPostCreate.yaml @@ -0,0 +1,18 @@ +title: GroupAuditLogEntryDataGroupPostCreate +type: object +properties: + roleIds: + type: + - array + - "null" + description: The role IDs that can see the post. + items: + $ref: ./GroupRoleID.yaml + sendNotification: + type: boolean + description: Whether a notification was sent for this post. +required: + - roleIds + - sendNotification +allOf: + - $ref: ./GroupAuditLogEntryDataGroupPost.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupPostDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupPostDelete.yaml new file mode 100644 index 00000000..81ce76ca --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupPostDelete.yaml @@ -0,0 +1,33 @@ +title: GroupAuditLogEntryDataGroupPostDelete +type: object +properties: + createdAt: + type: string + description: The creation timestamp of the post. + format: date-time + editorId: + description: The ID of the user who last edited the post. + anyOf: + - $ref: ./UserID.yaml + - type: "null" + imageUrl: + type: + - string + - "null" + description: The URL of the post image. + format: uri + roleIds: + $ref: ./GroupRoleIDList.yaml + description: The role IDs that could see the post. + updatedAt: + type: string + description: The last update timestamp of the post. + format: date-time +required: + - createdAt + - editorId + - imageUrl + - roleIds + - updatedAt +allOf: + - $ref: ./GroupAuditLogEntryDataGroupPost.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupPostUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupPostUpdate.yaml new file mode 100644 index 00000000..ad10fb3f --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupPostUpdate.yaml @@ -0,0 +1,10 @@ +title: GroupAuditLogEntryDataGroupPostUpdate +type: object +description: Carries only the fields the update changed. +properties: + editorId: + $ref: ./GroupAuditLogEntryUserIdChange.yaml + text: + $ref: ./GroupAuditLogEntryStringChange.yaml + title: + $ref: ./GroupAuditLogEntryStringChange.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupRole.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupRole.yaml new file mode 100644 index 00000000..d2e02ffe --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupRole.yaml @@ -0,0 +1,37 @@ +title: GroupAuditLogEntryDataGroupRole +type: object +properties: + description: + type: string + description: The role description. + isAddedOnJoin: + type: boolean + description: Whether the role is automatically assigned on join. + isSelfAssignable: + type: boolean + description: Whether users can self-assign this role. + name: + type: string + description: The role name. + order: + type: integer + description: The display order of the role. + permissions: + type: array + description: The permissions assigned to this role. + items: + $ref: ./GroupPermissions.yaml + requiresPurchase: + type: boolean + description: Whether the role requires a purchase. + requiresTwoFactor: + type: boolean + description: Whether the role requires two-factor authentication. +required: + - description + - isAddedOnJoin + - isSelfAssignable + - name + - permissions + - requiresPurchase + - requiresTwoFactor diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleCreate.yaml new file mode 100644 index 00000000..c5b41eb8 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleCreate.yaml @@ -0,0 +1,14 @@ +title: GroupAuditLogEntryDataGroupRoleCreate +type: object +properties: + groupId: + $ref: ./GroupID.yaml + description: The group ID. + lastUpdatedByUserId: + $ref: ./UserID.yaml + description: The ID of the user who last updated the role. +required: + - groupId + - lastUpdatedByUserId +allOf: + - $ref: ./GroupAuditLogEntryDataGroupRole.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleDelete.yaml new file mode 100644 index 00000000..1601a90d --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleDelete.yaml @@ -0,0 +1,20 @@ +title: GroupAuditLogEntryDataGroupRoleDelete +type: object +properties: + createdAt: + type: string + description: The creation timestamp of the role. + format: date-time + defaultRole: + type: boolean + description: Whether the role is the group's default role. + isManagementRole: + type: boolean + description: Whether the role is a management role. +required: + - createdAt + - defaultRole + - isManagementRole + - order +allOf: + - $ref: ./GroupAuditLogEntryDataGroupRole.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleUpdate.yaml new file mode 100644 index 00000000..4ebac353 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupRoleUpdate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryDataGroupRoleUpdate +type: object +description: Carries only the fields the update changed. +properties: + description: + $ref: ./GroupAuditLogEntryStringChange.yaml + isAddedOnJoin: + $ref: ./GroupAuditLogEntryBooleanChange.yaml + isSelfAssignable: + $ref: ./GroupAuditLogEntryBooleanChange.yaml + name: + $ref: ./GroupAuditLogEntryStringChange.yaml + order: + $ref: ./GroupAuditLogEntryIntegerChange.yaml + permissions: + $ref: ./GroupAuditLogEntryStringListChange.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataGroupUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryDataGroupUpdate.yaml new file mode 100644 index 00000000..3dc305c6 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataGroupUpdate.yaml @@ -0,0 +1,28 @@ +title: GroupAuditLogEntryDataGroupUpdate +type: object +description: Carries only the fields the update changed. +properties: + allowGroupJoinPrompt: + $ref: ./GroupAuditLogEntryBooleanChange.yaml + bannerId: + $ref: ./GroupAuditLogEntryFileIDChange.yaml + description: + $ref: ./GroupAuditLogEntryStringChange.yaml + iconId: + $ref: ./GroupAuditLogEntryFileIDChange.yaml + joinState: + $ref: ./GroupAuditLogEntryJoinStateChange.yaml + languages: + $ref: ./GroupAuditLogEntryStringListChange.yaml + links: + $ref: ./GroupAuditLogEntryStringListChange.yaml + name: + $ref: ./GroupAuditLogEntryStringChange.yaml + nameplateId: + $ref: ./GroupAuditLogEntryFileIDChange.yaml + rules: + $ref: ./GroupAuditLogEntryStringChange.yaml + shortCode: + $ref: ./GroupAuditLogEntryStringChange.yaml + tags: + $ref: ./GroupAuditLogEntryStringListChange.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryDataUnknown.yaml b/openapi/components/schemas/GroupAuditLogEntryDataUnknown.yaml new file mode 100644 index 00000000..74aab99e --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryDataUnknown.yaml @@ -0,0 +1,3 @@ +title: GroupAuditLogEntryDataUnknown +type: object +additionalProperties: true diff --git a/openapi/components/schemas/GroupAuditLogEntryFileIDChange.yaml b/openapi/components/schemas/GroupAuditLogEntryFileIDChange.yaml new file mode 100644 index 00000000..3ff8d5c6 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryFileIDChange.yaml @@ -0,0 +1,11 @@ +title: GroupAuditLogEntryFileIDChange +type: object +description: A File ID field's value before and after an update. +properties: + new: + $ref: ./FileID.yaml + old: + $ref: ./FileID.yaml +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupAnnouncement.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupAnnouncement.yaml new file mode 100644 index 00000000..745f4557 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupAnnouncement.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupAnnouncement +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupAnnouncement.yaml + eventType: + type: string + const: group.announcement + targetId: + $ref: ./NotificationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupCalendarEventCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupCalendarEventCreate.yaml new file mode 100644 index 00000000..8145c490 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupCalendarEventCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupCalendarEventCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupCalendarEventCreate.yaml + eventType: + type: string + const: group.calendarEvent.create + targetId: + $ref: ./CalendarID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupCalendarEventDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupCalendarEventDelete.yaml new file mode 100644 index 00000000..e020cfe9 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupCalendarEventDelete.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupCalendarEventDelete +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupCalendarEventDelete.yaml + eventType: + type: string + const: group.calendarEvent.delete + targetId: + $ref: ./CalendarID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupGalleryCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupGalleryCreate.yaml new file mode 100644 index 00000000..adb572d6 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupGalleryCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupGalleryCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupGalleryCreate.yaml + eventType: + type: string + const: group.gallery.create + targetId: + $ref: ./GroupGalleryID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupGalleryDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupGalleryDelete.yaml new file mode 100644 index 00000000..5cf784e4 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupGalleryDelete.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupGalleryDelete +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupGalleryDelete.yaml + eventType: + type: string + const: group.gallery.delete + targetId: + $ref: ./GroupGalleryID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupGalleryUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupGalleryUpdate.yaml new file mode 100644 index 00000000..1ce44224 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupGalleryUpdate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupGalleryUpdate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupGalleryUpdate.yaml + eventType: + type: string + const: group.gallery.update + targetId: + $ref: ./GroupGalleryID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInstanceAnnouncement.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceAnnouncement.yaml new file mode 100644 index 00000000..dcd1f20e --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceAnnouncement.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInstanceAnnouncement +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupInstanceAnnouncement.yaml + eventType: + type: string + const: group.instance.announcement + targetId: + $ref: ./LocationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInstanceClose.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceClose.yaml new file mode 100644 index 00000000..09f4c846 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceClose.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInstanceClose +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupInstanceClose.yaml + eventType: + type: string + const: group.instance.close + targetId: + $ref: ./LocationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInstanceCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceCreate.yaml new file mode 100644 index 00000000..3933fd8e --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInstanceCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupInstanceCreate.yaml + eventType: + type: string + const: group.instance.create + targetId: + $ref: ./LocationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInstanceKick.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceKick.yaml new file mode 100644 index 00000000..a7ed77a7 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceKick.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInstanceKick +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupInstanceModeration.yaml + eventType: + type: string + const: group.instance.kick + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInstanceWarn.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceWarn.yaml new file mode 100644 index 00000000..7b01b5d1 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInstanceWarn.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInstanceWarn +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupInstanceModeration.yaml + eventType: + type: string + const: group.instance.warn + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInviteCancel.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInviteCancel.yaml new file mode 100644 index 00000000..89fd50e5 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInviteCancel.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInviteCancel +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.invite.cancel + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupInviteCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupInviteCreate.yaml new file mode 100644 index 00000000..86e3296a --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupInviteCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupInviteCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.invite.create + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupMemberJoin.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupMemberJoin.yaml new file mode 100644 index 00000000..895763d0 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupMemberJoin.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupMemberJoin +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.member.join + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupMemberLeave.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupMemberLeave.yaml new file mode 100644 index 00000000..a18d9af3 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupMemberLeave.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupMemberLeave +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.member.leave + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupMemberRemove.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupMemberRemove.yaml new file mode 100644 index 00000000..88317404 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupMemberRemove.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupMemberRemove +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.member.remove + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupMemberRoleAssign.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupMemberRoleAssign.yaml new file mode 100644 index 00000000..df6363dd --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupMemberRoleAssign.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupMemberRoleAssign +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupMemberRole.yaml + eventType: + type: string + const: group.member.role.assign + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupMemberRoleUnassign.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupMemberRoleUnassign.yaml new file mode 100644 index 00000000..2fd52f54 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupMemberRoleUnassign.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupMemberRoleUnassign +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupMemberRole.yaml + eventType: + type: string + const: group.member.role.unassign + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupMemberUserUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupMemberUserUpdate.yaml new file mode 100644 index 00000000..df6fd160 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupMemberUserUpdate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupMemberUserUpdate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupMemberUserUpdate.yaml + eventType: + type: string + const: group.member.user.update + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupPostCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupPostCreate.yaml new file mode 100644 index 00000000..6ea62914 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupPostCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupPostCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupPostCreate.yaml + eventType: + type: string + const: group.post.create + targetId: + $ref: ./NotificationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupPostDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupPostDelete.yaml new file mode 100644 index 00000000..15ce33e0 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupPostDelete.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupPostDelete +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupPostDelete.yaml + eventType: + type: string + const: group.post.delete + targetId: + $ref: ./NotificationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupPostUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupPostUpdate.yaml new file mode 100644 index 00000000..1300c5f7 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupPostUpdate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupPostUpdate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupPostUpdate.yaml + eventType: + type: string + const: group.post.update + targetId: + $ref: ./NotificationID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRequestBlock.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRequestBlock.yaml new file mode 100644 index 00000000..cb2d97d7 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRequestBlock.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRequestBlock +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.request.block + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRequestCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRequestCreate.yaml new file mode 100644 index 00000000..c19cb0d2 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRequestCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRequestCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.request.create + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRequestReject.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRequestReject.yaml new file mode 100644 index 00000000..63c2dd76 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRequestReject.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRequestReject +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.request.reject + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRequestWithdraw.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRequestWithdraw.yaml new file mode 100644 index 00000000..e1f222d6 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRequestWithdraw.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRequestWithdraw +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.request.withdraw + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRoleCreate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRoleCreate.yaml new file mode 100644 index 00000000..60c69df4 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRoleCreate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRoleCreate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupRoleCreate.yaml + eventType: + type: string + const: group.role.create + targetId: + $ref: ./GroupRoleID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRoleDelete.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRoleDelete.yaml new file mode 100644 index 00000000..20ea2288 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRoleDelete.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRoleDelete +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupRoleDelete.yaml + eventType: + type: string + const: group.role.delete + targetId: + $ref: ./GroupRoleID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupRoleUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupRoleUpdate.yaml new file mode 100644 index 00000000..b2462e91 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupRoleUpdate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupRoleUpdate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupRoleUpdate.yaml + eventType: + type: string + const: group.role.update + targetId: + $ref: ./GroupRoleID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupUpdate.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupUpdate.yaml new file mode 100644 index 00000000..e25dca32 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupUpdate.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupUpdate +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataGroupUpdate.yaml + eventType: + type: string + const: group.update + targetId: + $ref: ./GroupID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupUserBan.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupUserBan.yaml new file mode 100644 index 00000000..7100415d --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupUserBan.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupUserBan +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.user.ban + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryGroupUserUnban.yaml b/openapi/components/schemas/GroupAuditLogEntryGroupUserUnban.yaml new file mode 100644 index 00000000..07ae7dda --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryGroupUserUnban.yaml @@ -0,0 +1,16 @@ +title: GroupAuditLogEntryGroupUserUnban +type: object +properties: + data: + $ref: ./GroupAuditLogEntryDataEmpty.yaml + eventType: + type: string + const: group.user.unban + targetId: + $ref: ./UserID.yaml +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryIntegerChange.yaml b/openapi/components/schemas/GroupAuditLogEntryIntegerChange.yaml new file mode 100644 index 00000000..538c2d0c --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryIntegerChange.yaml @@ -0,0 +1,11 @@ +title: GroupAuditLogEntryIntegerChange +type: object +description: An integer field's value before and after an update. +properties: + new: + type: integer + old: + type: integer +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogEntryJoinStateChange.yaml b/openapi/components/schemas/GroupAuditLogEntryJoinStateChange.yaml new file mode 100644 index 00000000..b0ee16d0 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryJoinStateChange.yaml @@ -0,0 +1,11 @@ +title: GroupAuditLogEntryJoinStateChange +type: object +description: A join state field's value before and after an update. +properties: + new: + $ref: ./GroupJoinState.yaml + old: + $ref: ./GroupJoinState.yaml +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogEntryStringChange.yaml b/openapi/components/schemas/GroupAuditLogEntryStringChange.yaml new file mode 100644 index 00000000..4a4ba7e8 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryStringChange.yaml @@ -0,0 +1,11 @@ +title: GroupAuditLogEntryStringChange +type: object +description: A text field's value before and after an update. +properties: + new: + type: string + old: + type: string +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogEntryStringListChange.yaml b/openapi/components/schemas/GroupAuditLogEntryStringListChange.yaml new file mode 100644 index 00000000..809bc1ff --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryStringListChange.yaml @@ -0,0 +1,15 @@ +title: GroupAuditLogEntryStringListChange +type: object +description: A list field's value before and after an update. +properties: + new: + type: array + items: + type: string + old: + type: array + items: + type: string +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogEntryType.yaml b/openapi/components/schemas/GroupAuditLogEntryType.yaml index 1d87c3ca..51e7d1b6 100644 --- a/openapi/components/schemas/GroupAuditLogEntryType.yaml +++ b/openapi/components/schemas/GroupAuditLogEntryType.yaml @@ -2,4 +2,5 @@ title: GroupAuditLogEntryType type: string description: The type of event that occurred. This is a string that is prefixed with the type of object that the event occurred on. For example, a group role update event would be prefixed with `group.role`. default: group.update -example: group.role.update +examples: + - group.role.update diff --git a/openapi/components/schemas/GroupAuditLogEntryUnknown.yaml b/openapi/components/schemas/GroupAuditLogEntryUnknown.yaml new file mode 100644 index 00000000..015d1596 --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryUnknown.yaml @@ -0,0 +1,50 @@ +title: GroupAuditLogEntryUnknown +type: object +description: An event whose `eventType` has no schema of its own. +properties: + data: + $ref: ./GroupAuditLogEntryDataUnknown.yaml + eventType: + type: string + not: + enum: + - group.announcement + - group.calendarEvent.create + - group.calendarEvent.delete + - group.gallery.create + - group.gallery.delete + - group.gallery.update + - group.instance.announcement + - group.instance.close + - group.instance.create + - group.instance.kick + - group.instance.warn + - group.invite.cancel + - group.invite.create + - group.member.join + - group.member.leave + - group.member.remove + - group.member.role.assign + - group.member.role.unassign + - group.member.user.update + - group.post.create + - group.post.delete + - group.post.update + - group.request.block + - group.request.create + - group.request.reject + - group.request.withdraw + - group.role.create + - group.role.delete + - group.role.update + - group.update + - group.user.ban + - group.user.unban + targetId: + type: string +required: + - data + - eventType + - targetId +allOf: + - $ref: ./GroupAuditLogEntryBase.yaml diff --git a/openapi/components/schemas/GroupAuditLogEntryUserIdChange.yaml b/openapi/components/schemas/GroupAuditLogEntryUserIdChange.yaml new file mode 100644 index 00000000..3eabd3fe --- /dev/null +++ b/openapi/components/schemas/GroupAuditLogEntryUserIdChange.yaml @@ -0,0 +1,15 @@ +title: GroupAuditLogEntryUserIdChange +type: object +description: A user ID field's value before and after an update. +properties: + new: + anyOf: + - $ref: ./UserID.yaml + - type: "null" + old: + anyOf: + - $ref: ./UserID.yaml + - type: "null" +required: + - new + - old diff --git a/openapi/components/schemas/GroupAuditLogID.yaml b/openapi/components/schemas/GroupAuditLogID.yaml index 4ee3d0b7..cdfd5c2e 100644 --- a/openapi/components/schemas/GroupAuditLogID.yaml +++ b/openapi/components/schemas/GroupAuditLogID.yaml @@ -1,3 +1,4 @@ title: GroupAuditLogID type: string -example: gaud_71a7ff59-112c-4e78-a990-c7cc650776e5 +examples: + - gaud_71a7ff59-112c-4e78-a990-c7cc650776e5 diff --git a/openapi/components/schemas/GroupDiscriminator.yaml b/openapi/components/schemas/GroupDiscriminator.yaml index 087412bf..06c915f3 100644 --- a/openapi/components/schemas/GroupDiscriminator.yaml +++ b/openapi/components/schemas/GroupDiscriminator.yaml @@ -1,3 +1,4 @@ title: GroupDiscriminator type: string -example: "0000" +examples: + - "0000" diff --git a/openapi/components/schemas/GroupGallery.yaml b/openapi/components/schemas/GroupGallery.yaml index c188e0d3..a3ad2b22 100644 --- a/openapi/components/schemas/GroupGallery.yaml +++ b/openapi/components/schemas/GroupGallery.yaml @@ -1,50 +1,53 @@ -title: GroupGallery -type: object -properties: - createdAt: - type: string - format: date-time - description: - type: string - description: Description of the gallery. - example: Example Description - minLength: 0 - id: - $ref: ./GroupGalleryID.yaml - membersOnly: - type: boolean - description: Whether the gallery is members only. - default: false - example: false - name: - type: string - description: Name of the gallery. - example: Example Gallery - minLength: 1 - roleIdsToAutoApprove: - type: array - description: " " - nullable: true - items: - $ref: ./GroupRoleID.yaml - roleIdsToManage: - type: array - description: " " - nullable: true - items: - $ref: ./GroupRoleID.yaml - roleIdsToSubmit: - type: array - description: " " - nullable: true - items: - $ref: ./GroupRoleID.yaml - roleIdsToView: - type: array - description: " " - nullable: true - items: - $ref: ./GroupRoleID.yaml - updatedAt: - type: string - format: date-time +title: GroupGallery +type: object +properties: + createdAt: + type: string + format: date-time + description: + type: string + description: Description of the gallery. + examples: + - Example Description + minLength: 0 + id: + $ref: ./GroupGalleryID.yaml + membersOnly: + type: boolean + description: Whether the gallery is members only. + default: false + examples: + - false + name: + type: string + description: Name of the gallery. + examples: + - Example Gallery + minLength: 1 + roleIdsToAutoApprove: + type: + - array + - "null" + items: + $ref: ./GroupRoleID.yaml + roleIdsToManage: + type: + - array + - "null" + items: + $ref: ./GroupRoleID.yaml + roleIdsToSubmit: + type: + - array + - "null" + items: + $ref: ./GroupRoleID.yaml + roleIdsToView: + type: + - array + - "null" + items: + $ref: ./GroupRoleID.yaml + updatedAt: + type: string + format: date-time diff --git a/openapi/components/schemas/GroupGalleryID.yaml b/openapi/components/schemas/GroupGalleryID.yaml index dac6fb92..aeb84238 100644 --- a/openapi/components/schemas/GroupGalleryID.yaml +++ b/openapi/components/schemas/GroupGalleryID.yaml @@ -1,3 +1,4 @@ title: GroupGalleryID type: string -example: ggal_a03a4b55-4ca6-4490-9519-40ba6351a233 +examples: + - ggal_a03a4b55-4ca6-4490-9519-40ba6351a233 diff --git a/openapi/components/schemas/GroupGalleryImage.yaml b/openapi/components/schemas/GroupGalleryImage.yaml index badc7737..7812c079 100644 --- a/openapi/components/schemas/GroupGalleryImage.yaml +++ b/openapi/components/schemas/GroupGalleryImage.yaml @@ -4,7 +4,8 @@ properties: approved: type: boolean default: false - example: true + examples: + - true approvedAt: type: string format: date-time @@ -23,7 +24,8 @@ properties: $ref: ./GroupGalleryImageID.yaml imageUrl: type: string - example: "https://api.vrchat.cloud/api/1/file/file_ce35d830-e20a-4df0-a6d4-5aaef4508044/1/file" + examples: + - "https://api.vrchat.cloud/api/1/file/file_ce35d830-e20a-4df0-a6d4-5aaef4508044/1/file" format: uri submittedByUserId: $ref: ./UserID.yaml diff --git a/openapi/components/schemas/GroupGalleryImageID.yaml b/openapi/components/schemas/GroupGalleryImageID.yaml index 3de3ca7c..a1448512 100644 --- a/openapi/components/schemas/GroupGalleryImageID.yaml +++ b/openapi/components/schemas/GroupGalleryImageID.yaml @@ -1,3 +1,4 @@ title: GroupGalleryImageID type: string -example: ggim_71a7ff59-112c-4e78-a990-c7cc650776e5 +examples: + - ggim_71a7ff59-112c-4e78-a990-c7cc650776e5 diff --git a/openapi/components/schemas/GroupGalleryImageList.yaml b/openapi/components/schemas/GroupGalleryImageList.yaml new file mode 100644 index 00000000..30c0d303 --- /dev/null +++ b/openapi/components/schemas/GroupGalleryImageList.yaml @@ -0,0 +1,14 @@ +title: GroupGalleryImageList +type: object +description: A page of a group gallery's images. +properties: + results: + type: array + items: + $ref: ./GroupGalleryImage.yaml + totalCount: + type: integer + minimum: 0 +required: + - results + - totalCount diff --git a/openapi/components/schemas/GroupID.yaml b/openapi/components/schemas/GroupID.yaml index 0a59a3a3..b6eeaceb 100644 --- a/openapi/components/schemas/GroupID.yaml +++ b/openapi/components/schemas/GroupID.yaml @@ -1,3 +1,4 @@ title: GroupID type: string -example: grp_71a7ff59-112c-4e78-a990-c7cc650776e5 +examples: + - grp_71a7ff59-112c-4e78-a990-c7cc650776e5 diff --git a/openapi/components/schemas/GroupInstance.yaml b/openapi/components/schemas/GroupInstance.yaml index d289a172..bf66d0ce 100644 --- a/openapi/components/schemas/GroupInstance.yaml +++ b/openapi/components/schemas/GroupInstance.yaml @@ -7,7 +7,8 @@ properties: $ref: ./LocationID.yaml memberCount: type: integer - example: 6 + examples: + - 6 minimum: 0 world: $ref: ./World.yaml diff --git a/openapi/components/schemas/GroupJoinRequestAction.yaml b/openapi/components/schemas/GroupJoinRequestAction.yaml index 3dc4794a..89a97c66 100644 --- a/openapi/components/schemas/GroupJoinRequestAction.yaml +++ b/openapi/components/schemas/GroupJoinRequestAction.yaml @@ -3,4 +3,5 @@ type: string enum: - accept - reject -example: accept +examples: + - accept diff --git a/openapi/components/schemas/GroupMember.yaml b/openapi/components/schemas/GroupMember.yaml index fb212b44..177c376f 100644 --- a/openapi/components/schemas/GroupMember.yaml +++ b/openapi/components/schemas/GroupMember.yaml @@ -1,82 +1,87 @@ -title: GroupMember -type: object -description: May be null when attempting to retrieve group membership for a user who is not part of the group -nullable: true -properties: - acceptedByDisplayName: - type: string - description: Only missing when explicitly fetching own user. - nullable: true - acceptedById: - type: string - description: Only missing when explicitly fetching own user. - nullable: true - bannedAt: - type: string - description: Only missing when explicitly fetching own user. - nullable: true - format: date-time - createdAt: - type: string - description: Only missing when explicitly fetching own user. - nullable: true - format: date-time - groupId: - $ref: ./GroupID.yaml - hasJoinedFromPurchase: - type: boolean - description: Missing when explicitly fetching own user, or when group isn't linked to a purchase. - id: - $ref: ./GroupMemberID.yaml - isRepresenting: - type: boolean - description: Whether the user is representing the group. This makes the group show up above the name tag in-game. - default: false - example: true - isSubscribedToAnnouncements: - type: boolean - default: false - isSubscribedToEventAnnouncements: - type: boolean - description: Only missing when explicitly fetching own user. - joinedAt: - type: string - nullable: true - format: date-time - lastPostReadAt: - type: string - nullable: true - format: date-time - mRoleIds: - type: array - items: - $ref: ./GroupRoleID.yaml - managerNotes: - type: string - description: Only missing when explicitly fetching own user. - nullable: true - membershipStatus: - $ref: ./GroupMemberStatus.yaml - roleIds: - type: array - items: - $ref: ./GroupRoleID.yaml - user: - $ref: ./GroupMemberLimitedUser.yaml - userId: - $ref: ./UserID.yaml - visibility: - type: string - example: visible -required: - - groupId - - id - - isRepresenting - - isSubscribedToAnnouncements - - joinedAt - - lastPostReadAt - - mRoleIds - - membershipStatus - - roleIds - - userId - - visibility +title: GroupMember +type: object +description: May be null when attempting to retrieve group membership for a user who is not part of the group +properties: + acceptedByDisplayName: + type: + - string + - "null" + description: Only missing when explicitly fetching own user. + acceptedById: + type: + - string + - "null" + description: Only missing when explicitly fetching own user. + bannedAt: + type: + - string + - "null" + description: Only missing when explicitly fetching own user. + format: date-time + createdAt: + type: + - string + - "null" + description: Only missing when explicitly fetching own user. + format: date-time + groupId: + $ref: ./GroupID.yaml + hasJoinedFromPurchase: + type: boolean + description: Missing when explicitly fetching own user, or when group isn't linked to a purchase. + id: + $ref: ./GroupMemberID.yaml + isRepresenting: + type: boolean + description: Whether the user is representing the group. This makes the group show up above the name tag in-game. + default: false + examples: + - true + isSubscribedToAnnouncements: + type: boolean + default: false + isSubscribedToEventAnnouncements: + type: boolean + description: Only missing when explicitly fetching own user. + joinedAt: + type: + - string + - "null" + format: date-time + lastPostReadAt: + type: + - string + - "null" + format: date-time + mRoleIds: + type: array + items: + $ref: ./GroupRoleID.yaml + managerNotes: + type: + - string + - "null" + description: Only missing when explicitly fetching own user. + membershipStatus: + $ref: ./GroupMemberStatus.yaml + roleIds: + type: array + items: + $ref: ./GroupRoleID.yaml + user: + anyOf: + - $ref: ./GroupMemberLimitedUser.yaml + - type: "null" + userId: + $ref: ./UserID.yaml + visibility: + type: string + examples: + - visible +required: + - groupId + - id + - isRepresenting + - mRoleIds + - roleIds + - userId diff --git a/openapi/components/schemas/GroupMemberID.yaml b/openapi/components/schemas/GroupMemberID.yaml index a940f8e6..8be74541 100644 --- a/openapi/components/schemas/GroupMemberID.yaml +++ b/openapi/components/schemas/GroupMemberID.yaml @@ -1,3 +1,4 @@ title: GroupMemberID type: string -example: gmem_95cdb3b4-4643-4eb6-bdab-46a4e1e5ce37 +examples: + - gmem_95cdb3b4-4643-4eb6-bdab-46a4e1e5ce37 diff --git a/openapi/components/schemas/GroupMemberLimitedUser.yaml b/openapi/components/schemas/GroupMemberLimitedUser.yaml index d1cf3814..cf5b6521 100644 --- a/openapi/components/schemas/GroupMemberLimitedUser.yaml +++ b/openapi/components/schemas/GroupMemberLimitedUser.yaml @@ -1,23 +1,22 @@ -title: GroupMemberLimitedUser -type: object -description: "Only visible via the /groups/:groupId/members endpoint, **not** when fetching a specific user." -nullable: true -properties: - currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml - currentAvatarThumbnailImageUrl: - type: string - nullable: true - displayName: - type: string - iconUrl: - type: string - id: - $ref: ./UserID.yaml - profilePicOverride: - type: string - thumbnailUrl: - type: string - nullable: true +title: GroupMemberLimitedUser +type: object +description: "Only visible via the /groups/:groupId/members endpoint, **not** when fetching a specific user." +properties: + bannerColor: + $ref: ./Color.yaml + bannerType: + type: string + bannerUrl: + type: string + displayName: + type: string + iconFrame: + type: string + iconUrl: + type: string + id: + $ref: ./UserID.yaml + nameplateEffect: + type: string + profileEffect: + type: string diff --git a/openapi/components/schemas/GroupMemberStatus.yaml b/openapi/components/schemas/GroupMemberStatus.yaml index ab391730..f26de276 100644 --- a/openapi/components/schemas/GroupMemberStatus.yaml +++ b/openapi/components/schemas/GroupMemberStatus.yaml @@ -7,4 +7,5 @@ enum: - requested - userblocked default: inactive -example: member +examples: + - member diff --git a/openapi/components/schemas/GroupMyMember.yaml b/openapi/components/schemas/GroupMyMember.yaml index 7b50caa5..fc305fc4 100644 --- a/openapi/components/schemas/GroupMyMember.yaml +++ b/openapi/components/schemas/GroupMyMember.yaml @@ -2,14 +2,17 @@ title: GroupMyMember type: object properties: acceptedByDisplayName: - type: string - nullable: true + type: + - string + - "null" acceptedById: - type: string - nullable: true + type: + - string + - "null" bannedAt: - type: string - nullable: true + type: + - string + - "null" createdAt: type: string format: date-time @@ -35,8 +38,9 @@ properties: type: string format: date-time lastPostReadAt: - type: string - nullable: true + type: + - string + - "null" format: date-time mRoleIds: type: array @@ -46,7 +50,8 @@ properties: type: string membershipStatus: type: string - example: member + examples: + - member permissions: type: array items: @@ -59,4 +64,5 @@ properties: $ref: ./UserID.yaml visibility: type: string - example: visible + examples: + - visible diff --git a/openapi/components/schemas/GroupPermission.yaml b/openapi/components/schemas/GroupPermission.yaml index cb28e9ee..7e82aa52 100644 --- a/openapi/components/schemas/GroupPermission.yaml +++ b/openapi/components/schemas/GroupPermission.yaml @@ -6,7 +6,8 @@ properties: type: boolean description: Whether the user is allowed to add this permission to a role. default: false - example: true + examples: + - true dependsOn: type: array description: Other permission names this one is listed against. @@ -15,17 +16,21 @@ properties: displayName: type: string description: The display name of the permission. - example: Manage Group Data + examples: + - Manage Group Data help: type: string description: Human-readable description of the permission. - example: Allows role to edit group details (name, description, joinState, initialRoles, etc). + examples: + - Allows role to edit group details (name, description, joinState, initialRoles, etc). isManagementPermission: type: boolean description: Whether this permission is a "management" permission. default: false - example: true + examples: + - true name: type: string description: The name of the permission. - example: group-data-manage + examples: + - group-data-manage diff --git a/openapi/components/schemas/GroupPost.yaml b/openapi/components/schemas/GroupPost.yaml index 83431991..ae3a7bf7 100644 --- a/openapi/components/schemas/GroupPost.yaml +++ b/openapi/components/schemas/GroupPost.yaml @@ -7,18 +7,21 @@ properties: type: string format: date-time editorId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" groupId: $ref: ./GroupID.yaml id: $ref: ./NotificationID.yaml imageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" imageUrl: - type: string - nullable: true + type: + - string + - "null" roleIds: $ref: ./GroupRoleIDList.yaml text: diff --git a/openapi/components/schemas/GroupPostVisibility.yaml b/openapi/components/schemas/GroupPostVisibility.yaml index 2763113d..3e8f91e8 100644 --- a/openapi/components/schemas/GroupPostVisibility.yaml +++ b/openapi/components/schemas/GroupPostVisibility.yaml @@ -3,4 +3,5 @@ type: string enum: - group - public -example: public +examples: + - public diff --git a/openapi/components/schemas/GroupRole.yaml b/openapi/components/schemas/GroupRole.yaml index 4f9f8ecf..74e56996 100644 --- a/openapi/components/schemas/GroupRole.yaml +++ b/openapi/components/schemas/GroupRole.yaml @@ -30,6 +30,8 @@ properties: type: array items: $ref: ./GroupPermissions.yaml + productId: + $ref: ./ProductID.yaml requiresPurchase: type: boolean default: false diff --git a/openapi/components/schemas/GroupRoleID.yaml b/openapi/components/schemas/GroupRoleID.yaml index 2fb36203..3f87a3e9 100644 --- a/openapi/components/schemas/GroupRoleID.yaml +++ b/openapi/components/schemas/GroupRoleID.yaml @@ -1,3 +1,4 @@ title: GroupRoleID type: string -example: grol_459d3911-f672-44bc-b84d-e54ffe7960fe +examples: + - grol_459d3911-f672-44bc-b84d-e54ffe7960fe diff --git a/openapi/components/schemas/GroupRoleIDList.yaml b/openapi/components/schemas/GroupRoleIDList.yaml index 2a302db7..a159e432 100644 --- a/openapi/components/schemas/GroupRoleIDList.yaml +++ b/openapi/components/schemas/GroupRoleIDList.yaml @@ -1,5 +1,4 @@ title: GroupRoleIDList type: array -description: " " items: $ref: ./GroupRoleID.yaml diff --git a/openapi/components/schemas/GroupSearchSort.yaml b/openapi/components/schemas/GroupSearchSort.yaml index dd7bb476..f501bbb5 100644 --- a/openapi/components/schemas/GroupSearchSort.yaml +++ b/openapi/components/schemas/GroupSearchSort.yaml @@ -3,4 +3,5 @@ type: string enum: - joinedAt:asc - joinedAt:desc -example: joinedAt:asc +examples: + - joinedAt:asc diff --git a/openapi/components/schemas/GroupShortCode.yaml b/openapi/components/schemas/GroupShortCode.yaml index e09a6732..fb774789 100644 --- a/openapi/components/schemas/GroupShortCode.yaml +++ b/openapi/components/schemas/GroupShortCode.yaml @@ -1,3 +1,4 @@ title: GroupShortCode type: string -example: VRCHAT +examples: + - VRCHAT diff --git a/openapi/components/schemas/GroupUserVisibility.yaml b/openapi/components/schemas/GroupUserVisibility.yaml index 1de40d7b..5c547970 100644 --- a/openapi/components/schemas/GroupUserVisibility.yaml +++ b/openapi/components/schemas/GroupUserVisibility.yaml @@ -4,4 +4,5 @@ enum: - friends - hidden - visible -example: visible +examples: + - visible diff --git a/openapi/components/schemas/ImageAnimationStyle.yaml b/openapi/components/schemas/ImageAnimationStyle.yaml index 544918ef..2a468d2f 100644 --- a/openapi/components/schemas/ImageAnimationStyle.yaml +++ b/openapi/components/schemas/ImageAnimationStyle.yaml @@ -29,4 +29,5 @@ enum: - splash - stop - zzz -example: bats +examples: + - bats diff --git a/openapi/components/schemas/ImageMask.yaml b/openapi/components/schemas/ImageMask.yaml index 4a6fe4fe..e9fff2a5 100644 --- a/openapi/components/schemas/ImageMask.yaml +++ b/openapi/components/schemas/ImageMask.yaml @@ -9,4 +9,5 @@ enum: - square - star default: square -example: circle +examples: + - circle diff --git a/openapi/components/schemas/ImagePurpose.yaml b/openapi/components/schemas/ImagePurpose.yaml index a1e07213..d983fa25 100644 --- a/openapi/components/schemas/ImagePurpose.yaml +++ b/openapi/components/schemas/ImagePurpose.yaml @@ -14,4 +14,5 @@ enum: - product - sticker default: gallery -example: emojianimated +examples: + - emojianimated diff --git a/openapi/components/schemas/InfoPush.yaml b/openapi/components/schemas/InfoPush.yaml index fd52b754..4ab2e57c 100644 --- a/openapi/components/schemas/InfoPush.yaml +++ b/openapi/components/schemas/InfoPush.yaml @@ -1,16 +1,17 @@ title: InfoPush type: object -description: "" properties: - clientMinVersion: {} + clientMinVersion: + $ref: ./Unknown.yaml createdAt: type: string format: date-time data: $ref: ./InfoPushData.yaml endDate: - type: string - nullable: true + type: + - string + - "null" format: date-time experiment: $ref: ./InfoPushExperiment.yaml @@ -20,7 +21,8 @@ properties: minLength: 1 id: type: string - example: launch-beta + examples: + - launch-beta minLength: 1 isEnabled: type: boolean @@ -38,15 +40,18 @@ properties: items: type: string startDate: - type: string - description: "" - nullable: true + type: + - string + - "null" format: date-time tags: type: array - description: " " items: $ref: ./Tag.yaml + type: + type: string + examples: + - ContentShelf updatedAt: type: string format: date-time diff --git a/openapi/components/schemas/InfoPushData.yaml b/openapi/components/schemas/InfoPushData.yaml index 97f13d9e..1a5d7d90 100644 --- a/openapi/components/schemas/InfoPushData.yaml +++ b/openapi/components/schemas/InfoPushData.yaml @@ -1,6 +1,5 @@ title: InfoPushData type: object -description: "" properties: article: $ref: ./InfoPushDataArticle.yaml @@ -10,6 +9,8 @@ properties: $ref: ./AvatarID.yaml bannerImageUrl: type: string + body: + type: string categories: type: array items: @@ -18,15 +19,20 @@ properties: type: string contentList: $ref: ./DynamicContentRow.yaml + contentSource: + $ref: ./InfoPushDataContentSource.yaml + controls: + type: array + items: + $ref: ./InfoPushDataControl.yaml + cta: + $ref: ./InfoPushDataCallToAction.yaml + deliveryBehavior: + $ref: ./InfoPushDataDeliveryBehavior.yaml description: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - $ref: ./LocalizedString.yaml - else: - type: string + oneOf: + - type: string + - $ref: ./LocalizedString.yaml disclaimerText: type: string domainList: @@ -40,11 +46,16 @@ properties: type: string finalName: type: string + hoverToJoin: + type: boolean iconImageUrl: type: string + imageFileId: + $ref: ./FileID.yaml imageUrl: - type: string - nullable: true + type: + - string + - "null" ipsQuery: $ref: ./InfoPushIpsQuery.yaml isNew: @@ -53,56 +64,68 @@ properties: type: array items: type: string + mediaType: + type: string + examples: + - video name: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - $ref: ./LocalizedString.yaml - else: - type: string + oneOf: + - type: string + - $ref: ./LocalizedString.yaml onPressed: - $ref: ./InfoPushDataClickable.yaml - overrideName: {} + anyOf: + - $ref: ./InfoPushDataClickable.yaml + - type: "null" + overrideName: + $ref: ./Unknown.yaml + presentation: + $ref: ./InfoPushDataPresentation.yaml + promotion: + $ref: ./InfoPushDataPromotion.yaml rows: - type: integer + type: + - integer + - "null" description: Number of rows to render. - nullable: true + schemaVersion: + type: integer + examples: + - 1 search: $ref: ./InfoPushDataSearch.yaml shortName: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - type: "null" - - $ref: ./LocalizedString.yaml - else: - type: string - nullable: true + oneOf: + - type: string + - type: "null" + - $ref: ./LocalizedString.yaml + showInWorldIds: + $ref: ./Unknown.yaml + subtitle: + type: string + examples: + - Hangouts where everyone's still finding their feet template: type: string thumbnailImageUrl: + type: + - string + - "null" + title: type: string - nullable: true tooltipDescription: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - $ref: ./LocalizedString.yaml - else: - type: string + oneOf: + - type: string + - $ref: ./LocalizedString.yaml version: type: string - example: 2021.3.4 + examples: + - 2021.3.4 minLength: 1 - + videoFileId: + $ref: ./FileID.yaml + videoUrl: + type: string weight: type: integer - worldTag: type: string diff --git a/openapi/components/schemas/InfoPushDataCallToAction.yaml b/openapi/components/schemas/InfoPushDataCallToAction.yaml new file mode 100644 index 00000000..b5adf4e9 --- /dev/null +++ b/openapi/components/schemas/InfoPushDataCallToAction.yaml @@ -0,0 +1,5 @@ +title: InfoPushDataCallToAction +type: object +properties: + text: + type: string diff --git a/openapi/components/schemas/InfoPushDataCategory.yaml b/openapi/components/schemas/InfoPushDataCategory.yaml index 07629ca8..f2de78ff 100644 --- a/openapi/components/schemas/InfoPushDataCategory.yaml +++ b/openapi/components/schemas/InfoPushDataCategory.yaml @@ -10,13 +10,8 @@ properties: maxCells: type: integer name: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - $ref: ./LocalizedString.yaml - else: - type: string + oneOf: + - type: string + - $ref: ./LocalizedString.yaml type: type: string diff --git a/openapi/components/schemas/InfoPushDataClickable.yaml b/openapi/components/schemas/InfoPushDataClickable.yaml index 988977de..48f54dfb 100644 --- a/openapi/components/schemas/InfoPushDataClickable.yaml +++ b/openapi/components/schemas/InfoPushDataClickable.yaml @@ -19,7 +19,10 @@ properties: - OpenVRCPlusMenu - OpenVRChatStore - OpenWorldDetails - example: OpenURL + - OpenWorldsMenu + - scrollToShelf + examples: + - OpenURL minLength: 1 required: - command diff --git a/openapi/components/schemas/InfoPushDataContentSource.yaml b/openapi/components/schemas/InfoPushDataContentSource.yaml new file mode 100644 index 00000000..a7e04ea0 --- /dev/null +++ b/openapi/components/schemas/InfoPushDataContentSource.yaml @@ -0,0 +1,56 @@ +title: InfoPushDataContentSource +type: object +properties: + attributionResponseField: + type: string + examples: + - attributionId + computedParams: + type: object + additionalProperties: + type: string + endpoint: + type: string + examples: + - /api/1/instances/discover + kind: + type: string + examples: + - instanceDiscover + method: + type: string + examples: + - GET + pagination: + anyOf: + - $ref: ./InfoPushDataContentSourcePagination.yaml + - type: "null" + paramModifiability: + type: object + additionalProperties: true + params: + type: object + additionalProperties: true + responseType: + type: string + examples: + - instance + resultsField: + type: string + examples: + - instances + schemaVersion: + type: integer + examples: + - 1 +required: + - computedParams + - endpoint + - kind + - method + - pagination + - paramModifiability + - params + - responseType + - resultsField + - schemaVersion diff --git a/openapi/components/schemas/InfoPushDataContentSourcePagination.yaml b/openapi/components/schemas/InfoPushDataContentSourcePagination.yaml new file mode 100644 index 00000000..1098a0f9 --- /dev/null +++ b/openapi/components/schemas/InfoPushDataContentSourcePagination.yaml @@ -0,0 +1,29 @@ +title: InfoPushDataContentSourcePagination +type: object +properties: + cursorParam: + type: string + examples: + - nextCursor + cursorResponseField: + type: string + examples: + - nextCursor + pageSize: + type: integer + examples: + - 50 + pageSizeParam: + type: string + examples: + - n + style: + type: string + examples: + - cursor +required: + - cursorParam + - cursorResponseField + - pageSize + - pageSizeParam + - style diff --git a/openapi/components/schemas/InfoPushDataControl.yaml b/openapi/components/schemas/InfoPushDataControl.yaml new file mode 100644 index 00000000..c9f9b386 --- /dev/null +++ b/openapi/components/schemas/InfoPushDataControl.yaml @@ -0,0 +1,37 @@ +title: InfoPushDataControl +type: object +properties: + control: + type: string + examples: + - select + display: + type: string + examples: + - overflow + id: + type: string + examples: + - categories + kind: + type: string + examples: + - filter + label: + $ref: ./LocalizedString.yaml + options: + type: array + items: + $ref: ./InfoPushDataControlOption.yaml + selection: + type: string + examples: + - multiple +required: + - control + - display + - id + - kind + - label + - options + - selection diff --git a/openapi/components/schemas/InfoPushDataControlOption.yaml b/openapi/components/schemas/InfoPushDataControlOption.yaml new file mode 100644 index 00000000..6c4831da --- /dev/null +++ b/openapi/components/schemas/InfoPushDataControlOption.yaml @@ -0,0 +1,16 @@ +title: InfoPushDataControlOption +type: object +properties: + id: + type: string + examples: + - music + label: + $ref: ./LocalizedString.yaml + params: + type: object + additionalProperties: true +required: + - id + - label + - params diff --git a/openapi/components/schemas/InfoPushDataDeliveryBehavior.yaml b/openapi/components/schemas/InfoPushDataDeliveryBehavior.yaml new file mode 100644 index 00000000..4d3ffadc --- /dev/null +++ b/openapi/components/schemas/InfoPushDataDeliveryBehavior.yaml @@ -0,0 +1,9 @@ +title: InfoPushDataDeliveryBehavior +type: object +properties: + bypass24HourWindow: + type: boolean + maxRedeliveryAttempts: + type: integer + redeliverIfNoEngagement: + type: boolean diff --git a/openapi/components/schemas/InfoPushDataPresentation.yaml b/openapi/components/schemas/InfoPushDataPresentation.yaml new file mode 100644 index 00000000..dfc31c83 --- /dev/null +++ b/openapi/components/schemas/InfoPushDataPresentation.yaml @@ -0,0 +1,9 @@ +title: InfoPushDataPresentation +type: object +properties: + layout: + type: string + examples: + - EqualParts_4_Grid +required: + - layout diff --git a/openapi/components/schemas/InfoPushDataPromotion.yaml b/openapi/components/schemas/InfoPushDataPromotion.yaml new file mode 100644 index 00000000..363acaee --- /dev/null +++ b/openapi/components/schemas/InfoPushDataPromotion.yaml @@ -0,0 +1,22 @@ +title: InfoPushDataPromotion +type: object +properties: + id: + type: string + examples: + - kaguyaEN-content + impressions: + type: integer + examples: + - 1 + notification: + $ref: ./InfoPushDataPromotionNotification.yaml + type: + type: string + examples: + - notification +required: + - id + - impressions + - notification + - type diff --git a/openapi/components/schemas/InfoPushDataPromotionNotification.yaml b/openapi/components/schemas/InfoPushDataPromotionNotification.yaml new file mode 100644 index 00000000..792900d9 --- /dev/null +++ b/openapi/components/schemas/InfoPushDataPromotionNotification.yaml @@ -0,0 +1,29 @@ +title: InfoPushDataPromotionNotification +type: object +properties: + body: + type: string + examples: + - Visit the store to check out the new Cosmic Princess Kaguya items! + command: + type: string + examples: + - OpenListingDetails + imageUrl: + type: string + examples: + - https://assets.vrchat.com/ips/assets/ipsai_4b9857b7-4396-488a-931a-cbd71a445e81.png + parameter: + type: string + examples: + - prod_efc9804b-d0d7-477b-ac4d-3b9663dca14b + title: + type: string + examples: + - Cosmic Princess Kaguya! +required: + - body + - command + - imageUrl + - parameter + - title diff --git a/openapi/components/schemas/Instance.yaml b/openapi/components/schemas/Instance.yaml index 71a3e1b6..95f45349 100644 --- a/openapi/components/schemas/Instance.yaml +++ b/openapi/components/schemas/Instance.yaml @@ -8,50 +8,66 @@ properties: active: type: boolean default: true - example: true + examples: + - true ageGate: - type: boolean - nullable: true + type: + - boolean + - "null" calendarEntryId: - type: string - nullable: true + type: + - string + - "null" canRequestInvite: type: boolean default: true - example: true + examples: + - true capacity: type: integer - example: 8 + examples: + - 8 minimum: 0 categoryId: - $ref: ./InstanceCategoryID.yaml - nullable: true + anyOf: + - $ref: ./InstanceCategoryID.yaml + - type: "null" clientNumber: deprecated: true type: string description: Always returns "unknown". minLength: 1 closedAt: - type: string - nullable: true + type: + - string + - "null" format: date-time contentSettings: $ref: ./InstanceContentSettings.yaml creationLanguages: type: array - items: {} + items: + $ref: ./Unknown.yaml creatorId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" description: - type: string - nullable: true + type: + - string + - "null" disabledPropAbilities: type: array - items: {} + items: + $ref: ./Unknown.yaml displayName: - type: string - nullable: true + type: + - string + - "null" + displayVibeId: + anyOf: + - $ref: ./InstanceVibeID.yaml + - type: "null" dominantLanguage: type: string friends: @@ -60,13 +76,15 @@ properties: type: boolean default: false gameServerVersion: - type: integer - nullable: true + type: + - integer + - "null" groupAccessType: $ref: ./GroupAccessType.yaml hardClose: - type: boolean - nullable: true + type: + - boolean + - "null" hasCapacityForYou: type: boolean hidden: @@ -76,8 +94,9 @@ properties: instanceId: $ref: ./InstanceID.yaml instancePersistenceEnabled: - type: boolean - nullable: true + type: + - boolean + - "null" languageRatio: type: object additionalProperties: true @@ -86,7 +105,8 @@ properties: description: The keys of languageRatio, ordered by their share of the instance. items: type: string - example: en + examples: + - en languagesIso639: type: array items: @@ -94,15 +114,18 @@ properties: location: $ref: ./LocationID.yaml minimumAvatarPerformance: - type: string - nullable: true + type: + - string + - "null" n_users: type: integer - example: 6 + examples: + - 6 minimum: 0 name: type: string - example: "12345" + examples: + - "12345" minLength: 1 nonce: type: string @@ -116,19 +139,22 @@ properties: platforms: $ref: ./InstancePlatforms.yaml playerPersistenceEnabled: - type: boolean - nullable: true + type: + - boolean + - "null" private: $ref: ./UserID.yaml queueEnabled: type: boolean queueSize: type: integer - example: 6 + examples: + - 6 minimum: 0 recommendedCapacity: type: integer - example: 6 + examples: + - 6 minimum: 0 region: $ref: ./InstanceRegion.yaml @@ -136,35 +162,41 @@ properties: type: boolean secureName: type: string - example: 7eavhhng + examples: + - 7eavhhng minLength: 1 shortName: - type: string - nullable: true - example: 02u7yz8j + type: + - string + - "null" + examples: + - 02u7yz8j minLength: 1 strict: type: boolean tags: type: array description: "The tags array on Instances usually contain the language tags of the people in the instance. " - example: - - language_eng - - language_jpn - - show_social_rank + examples: + - + - language_eng + - language_jpn + - show_social_rank items: $ref: ./Tag.yaml type: $ref: ./InstanceType.yaml userCount: type: integer - example: 6 + examples: + - 6 minimum: 0 userIcons: type: array items: type: string - example: https://api.vrchat.cloud/api/1/image/file_12ca2b06-c08d-4023-b06f-b60691d9946e/1/256 + examples: + - https://api.vrchat.cloud/api/1/image/file_12ca2b06-c08d-4023-b06f-b60691d9946e/1/256 users: type: array description: The users field is present on instances created by the requesting user. diff --git a/openapi/components/schemas/InstanceCategory.yaml b/openapi/components/schemas/InstanceCategory.yaml index d8c22e04..26e136c3 100644 --- a/openapi/components/schemas/InstanceCategory.yaml +++ b/openapi/components/schemas/InstanceCategory.yaml @@ -6,15 +6,18 @@ properties: type: boolean iconUrl: type: string - example: vrchat://category_hangout + examples: + - vrchat://category_hangout id: $ref: ./InstanceCategoryID.yaml name: type: string - example: Hangout + examples: + - Hangout order: type: integer - example: 0 + examples: + - 0 required: - deleted - iconUrl diff --git a/openapi/components/schemas/InstanceCategoryID.yaml b/openapi/components/schemas/InstanceCategoryID.yaml index 94278957..c67cfd9c 100644 --- a/openapi/components/schemas/InstanceCategoryID.yaml +++ b/openapi/components/schemas/InstanceCategoryID.yaml @@ -1,3 +1,4 @@ title: InstanceCategoryID type: string -example: icat_44bc6a70-493f-4f84-8a3b-1f290c864c2a +examples: + - icat_44bc6a70-493f-4f84-8a3b-1f290c864c2a diff --git a/openapi/components/schemas/InstanceID.yaml b/openapi/components/schemas/InstanceID.yaml index bfb6c2e3..8c8257ac 100644 --- a/openapi/components/schemas/InstanceID.yaml +++ b/openapi/components/schemas/InstanceID.yaml @@ -1,4 +1,5 @@ title: InstanceID type: string description: InstanceID can be "offline" on User profiles if you are not friends with that user and "private" if you are friends and user is in private instance. -example: 12345~hidden(usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469)~region(eu)~nonce(27e8414a-59a0-4f3d-af1f-f27557eb49a2) +examples: + - 12345~hidden(usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469)~region(eu)~nonce(27e8414a-59a0-4f3d-af1f-f27557eb49a2) diff --git a/openapi/components/schemas/InstanceOwnerId.yaml b/openapi/components/schemas/InstanceOwnerId.yaml index ea10736c..9ec1d2c1 100644 --- a/openapi/components/schemas/InstanceOwnerId.yaml +++ b/openapi/components/schemas/InstanceOwnerId.yaml @@ -1,5 +1,7 @@ title: InstanceOwnerId -type: string +type: + - string + - "null" description: A groupId if the instance type is "group", null if instance type is public, or a userId otherwise -nullable: true -example: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 +examples: + - usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 diff --git a/openapi/components/schemas/InstancePlatforms.yaml b/openapi/components/schemas/InstancePlatforms.yaml index e2fe7357..8d82f1c5 100644 --- a/openapi/components/schemas/InstancePlatforms.yaml +++ b/openapi/components/schemas/InstancePlatforms.yaml @@ -4,15 +4,18 @@ additionalProperties: false properties: android: type: integer - example: 1 + examples: + - 1 minimum: 0 ios: type: integer - example: 1 + examples: + - 1 minimum: 0 standalonewindows: type: integer - example: 5 + examples: + - 5 minimum: 0 required: - android diff --git a/openapi/components/schemas/InstanceRegion.yaml b/openapi/components/schemas/InstanceRegion.yaml index 41d30b3f..02b79bbd 100644 --- a/openapi/components/schemas/InstanceRegion.yaml +++ b/openapi/components/schemas/InstanceRegion.yaml @@ -8,4 +8,5 @@ enum: - us - use default: us -example: us +examples: + - us diff --git a/openapi/components/schemas/InstanceShortNameResponse.yaml b/openapi/components/schemas/InstanceShortNameResponse.yaml index 25e37b6f..0f07bf2c 100644 --- a/openapi/components/schemas/InstanceShortNameResponse.yaml +++ b/openapi/components/schemas/InstanceShortNameResponse.yaml @@ -3,12 +3,15 @@ type: object properties: secureName: type: string - example: 7eavhhng + examples: + - 7eavhhng minLength: 1 shortName: - type: string - nullable: true - example: 02u7yz8j + type: + - string + - "null" + examples: + - 02u7yz8j minLength: 1 required: - secureName diff --git a/openapi/components/schemas/InstanceType.yaml b/openapi/components/schemas/InstanceType.yaml index 55fff007..b4c74dd5 100644 --- a/openapi/components/schemas/InstanceType.yaml +++ b/openapi/components/schemas/InstanceType.yaml @@ -1,10 +1,10 @@ title: InstanceType type: string -description: "" enum: - friends - group - hidden - private - public -example: hidden +examples: + - hidden diff --git a/openapi/components/schemas/InstanceVibe.yaml b/openapi/components/schemas/InstanceVibe.yaml index aa9c69fb..5b5495e5 100644 --- a/openapi/components/schemas/InstanceVibe.yaml +++ b/openapi/components/schemas/InstanceVibe.yaml @@ -8,7 +8,8 @@ properties: $ref: ./InstanceVibeID.yaml title: type: string - example: adventure + examples: + - adventure required: - deleted - id diff --git a/openapi/components/schemas/InstanceVibeID.yaml b/openapi/components/schemas/InstanceVibeID.yaml index 3b54934f..eb7a5dfd 100644 --- a/openapi/components/schemas/InstanceVibeID.yaml +++ b/openapi/components/schemas/InstanceVibeID.yaml @@ -1,3 +1,4 @@ title: InstanceVibeID type: string -example: ivib_2d8445c4-f47b-4635-b565-467fc32c4003 +examples: + - ivib_2d8445c4-f47b-4635-b565-467fc32c4003 diff --git a/openapi/components/schemas/InterestsAndPreferences.yaml b/openapi/components/schemas/InterestsAndPreferences.yaml new file mode 100644 index 00000000..68179d4e --- /dev/null +++ b/openapi/components/schemas/InterestsAndPreferences.yaml @@ -0,0 +1,38 @@ +title: InterestsAndPreferences +type: object +description: Interests and preferences the current user has turned on. A key is present only while its value is `true`. +properties: + Anime: + type: boolean + Art: + type: boolean + Avatars: + type: boolean + BigGroup: + type: boolean + Explore: + type: boolean + Fantasy: + type: boolean + Fashion: + type: boolean + FindAvatars: + type: boolean + Furries: + type: boolean + Horror: + type: boolean + LanguageLearning: + type: boolean + MeetPeople: + type: boolean + Music: + type: boolean + Mystery: + type: boolean + SciFi: + type: boolean + SmallGroup: + type: boolean + Surprise: + type: boolean diff --git a/openapi/components/schemas/InventoryAsset.yaml b/openapi/components/schemas/InventoryAsset.yaml new file mode 100644 index 00000000..118b0091 --- /dev/null +++ b/openapi/components/schemas/InventoryAsset.yaml @@ -0,0 +1,20 @@ +title: InventoryAsset +type: object +properties: + fileId: + type: string + frameCount: + type: integer + framesPerSecond: + type: number + loopCount: + type: integer + totalDurationMs: + type: integer + type: + type: string + url: + type: string +required: + - type + - url diff --git a/openapi/components/schemas/InventoryDrop.yaml b/openapi/components/schemas/InventoryDrop.yaml index 19c2fb80..2aca692d 100644 --- a/openapi/components/schemas/InventoryDrop.yaml +++ b/openapi/components/schemas/InventoryDrop.yaml @@ -5,17 +5,20 @@ properties: $ref: ./UserID.yaml created_at: type: string - example: "2025-06-10T20:37:31.837Z" + examples: + - "2025-06-10T20:37:31.837Z" format: date-time dropExpiryDate: - type: string - nullable: true + type: + - string + - "null" format: date-time dropStatus: type: string endDropDate: type: string - example: "2184-07-24T00:00:00.000Z" + examples: + - "2184-07-24T00:00:00.000Z" format: date-time id: $ref: ./InventoryDropID.yaml @@ -27,7 +30,8 @@ properties: $ref: ./InventoryNotificationDetails.yaml startDropDate: type: string - example: "2025-06-09T10:00:00.000Z" + examples: + - "2025-06-09T10:00:00.000Z" format: date-time tags: type: array @@ -35,14 +39,16 @@ properties: $ref: ./Tag.yaml targetGroup: type: string - example: everyone + examples: + - everyone templateIds: type: array items: $ref: ./InventoryTemplateID.yaml updated_at: type: string - example: "2025-06-10T20:37:31.837Z" + examples: + - "2025-06-10T20:37:31.837Z" format: date-time required: - authorId diff --git a/openapi/components/schemas/InventoryDropID.yaml b/openapi/components/schemas/InventoryDropID.yaml index 495201c1..e86b1e3a 100644 --- a/openapi/components/schemas/InventoryDropID.yaml +++ b/openapi/components/schemas/InventoryDropID.yaml @@ -1,3 +1,4 @@ title: InventoryDropID type: string -example: invd_ee3a8f7f-1454-4748-a935-99bf9865f33d +examples: + - invd_ee3a8f7f-1454-4748-a935-99bf9865f33d diff --git a/openapi/components/schemas/InventoryEquipSlot.yaml b/openapi/components/schemas/InventoryEquipSlot.yaml index 27b86117..a2c1e0f1 100644 --- a/openapi/components/schemas/InventoryEquipSlot.yaml +++ b/openapi/components/schemas/InventoryEquipSlot.yaml @@ -3,7 +3,11 @@ type: string enum: - "" - drone + - iconFrame + - nameplateEffect - portal + - profileEffect - warp default: "" -example: drone +examples: + - drone diff --git a/openapi/components/schemas/InventoryFlag.yaml b/openapi/components/schemas/InventoryFlag.yaml index 9701198a..387ea515 100644 --- a/openapi/components/schemas/InventoryFlag.yaml +++ b/openapi/components/schemas/InventoryFlag.yaml @@ -5,9 +5,13 @@ enum: - cloneable - consumable - equippable + - global + - global_visible - instantiatable - trashable - ugc - unique + - vrc_plus_exclusive default: instantiatable -example: consumable +examples: + - consumable diff --git a/openapi/components/schemas/InventoryItem.yaml b/openapi/components/schemas/InventoryItem.yaml index 9b18c308..962fd4a8 100644 --- a/openapi/components/schemas/InventoryItem.yaml +++ b/openapi/components/schemas/InventoryItem.yaml @@ -3,14 +3,16 @@ type: object properties: acquisition: type: string - attribution: {} + attribution: + $ref: ./Unknown.yaml collections: type: array items: type: string created_at: type: string - example: "2025-06-13T05:00:45.455Z" + examples: + - "2025-06-13T05:00:45.455Z" format: date-time defaultAttributes: $ref: ./InventoryDefaultAttributes.yaml @@ -23,9 +25,11 @@ properties: items: $ref: ./InventoryEquipSlot.yaml expiryDate: - type: string - nullable: true - example: "2025-06-13T05:00:45.455Z" + type: + - string + - "null" + examples: + - "2025-06-13T05:00:45.455Z" format: date-time flags: type: array @@ -62,15 +66,18 @@ properties: $ref: ./InventoryTemplateID.yaml template_created_at: type: string - example: "2025-06-09T16:31:40.785Z" + examples: + - "2025-06-09T16:31:40.785Z" format: date-time template_updated_at: type: string - example: "2025-06-25T00:34:14.578Z" + examples: + - "2025-06-25T00:34:14.578Z" format: date-time updated_at: type: string - example: "2025-06-25T00:34:15.965Z" + examples: + - "2025-06-25T00:34:15.965Z" format: date-time userAttributes: $ref: ./InventoryUserAttributes.yaml diff --git a/openapi/components/schemas/InventoryItemID.yaml b/openapi/components/schemas/InventoryItemID.yaml index 3fca31fb..57e3fcd9 100644 --- a/openapi/components/schemas/InventoryItemID.yaml +++ b/openapi/components/schemas/InventoryItemID.yaml @@ -1,3 +1,4 @@ title: InventoryItemID type: string -example: inv_10bce5b0-2d2b-44e0-900d-db6534615162 +examples: + - inv_10bce5b0-2d2b-44e0-900d-db6534615162 diff --git a/openapi/components/schemas/InventoryItemType.yaml b/openapi/components/schemas/InventoryItemType.yaml index 87d365e6..6de3ade8 100644 --- a/openapi/components/schemas/InventoryItemType.yaml +++ b/openapi/components/schemas/InventoryItemType.yaml @@ -4,9 +4,13 @@ enum: - bundle - droneskin - emoji + - iconFrame + - nameplateEffect - portalskin + - profileEffect - prop - sticker - warpeffect default: bundle -example: prop +examples: + - prop diff --git a/openapi/components/schemas/InventoryMetadata.yaml b/openapi/components/schemas/InventoryMetadata.yaml index 83728cd3..1eb5c35e 100644 --- a/openapi/components/schemas/InventoryMetadata.yaml +++ b/openapi/components/schemas/InventoryMetadata.yaml @@ -7,8 +7,16 @@ properties: type: string assetBundleId: type: string + assets: + type: array + items: + $ref: ./InventoryAsset.yaml fileId: type: string + gradientEnd: + $ref: ./Color.yaml + gradientStart: + $ref: ./Color.yaml imageUrl: type: string inventoryItemsToInstantiate: @@ -22,3 +30,5 @@ properties: $ref: ./PropID.yaml propKind: type: integer + viewfinderBundleId: + type: string diff --git a/openapi/components/schemas/InventoryTemplate.yaml b/openapi/components/schemas/InventoryTemplate.yaml index 8c0f00de..703c9b20 100644 --- a/openapi/components/schemas/InventoryTemplate.yaml +++ b/openapi/components/schemas/InventoryTemplate.yaml @@ -1,7 +1,8 @@ title: InventoryTemplate type: object properties: - attribution: {} + attribution: + $ref: ./Unknown.yaml authorId: $ref: ./UserID.yaml collections: @@ -10,7 +11,8 @@ properties: type: string created_at: type: string - example: "2025-06-12T20:21:15.056Z" + examples: + - "2025-06-12T20:21:15.056Z" format: date-time defaultAttributes: type: object @@ -30,6 +32,8 @@ properties: $ref: ./InventoryTemplateID.yaml imageUrl: type: string + initialToggleState: + type: boolean itemType: $ref: ./InventoryItemType.yaml itemTypeLabel: @@ -40,16 +44,24 @@ properties: type: string notificationDetails: $ref: ./InventoryNotificationDetails.yaml + productId: + $ref: ./ProductID.yaml + publishedListings: + type: array + items: + $ref: ./ProductID.yaml status: type: string - example: live + examples: + - live tags: type: array items: $ref: ./Tag.yaml updated_at: type: string - example: "2025-06-10T20:37:31.837Z" + examples: + - "2025-06-10T20:37:31.837Z" format: date-time validateUserAttributes: type: boolean diff --git a/openapi/components/schemas/InventoryTemplateID.yaml b/openapi/components/schemas/InventoryTemplateID.yaml index d6f1f03d..1b94b6e2 100644 --- a/openapi/components/schemas/InventoryTemplateID.yaml +++ b/openapi/components/schemas/InventoryTemplateID.yaml @@ -1,3 +1,4 @@ title: InventoryTemplateID type: string -example: invt_b80ce14b-038b-4f56-b970-d232771d62e3 +examples: + - invt_b80ce14b-038b-4f56-b970-d232771d62e3 diff --git a/openapi/components/schemas/InviteMessage.yaml b/openapi/components/schemas/InviteMessage.yaml index 045a4c60..75bf6cb0 100644 --- a/openapi/components/schemas/InviteMessage.yaml +++ b/openapi/components/schemas/InviteMessage.yaml @@ -1,6 +1,5 @@ title: InviteMessage type: object -description: "" properties: canBeUpdated: type: boolean diff --git a/openapi/components/schemas/InviteMessageID.yaml b/openapi/components/schemas/InviteMessageID.yaml index 0bc36b3e..10be8249 100644 --- a/openapi/components/schemas/InviteMessageID.yaml +++ b/openapi/components/schemas/InviteMessageID.yaml @@ -1,3 +1,4 @@ title: InviteMessageID type: string -example: invm_24a1c14d-5e24-48e5-90e3-c3f712420ffa +examples: + - invm_24a1c14d-5e24-48e5-90e3-c3f712420ffa diff --git a/openapi/components/schemas/InviteMessageType.yaml b/openapi/components/schemas/InviteMessageType.yaml index 00d06bc1..64bc0b72 100644 --- a/openapi/components/schemas/InviteMessageType.yaml +++ b/openapi/components/schemas/InviteMessageType.yaml @@ -1,6 +1,5 @@ title: InviteMessageType type: string -description: "" enum: - message - request diff --git a/openapi/components/schemas/Jam.yaml b/openapi/components/schemas/Jam.yaml index b0b2a2d0..34bfdd82 100644 --- a/openapi/components/schemas/Jam.yaml +++ b/openapi/components/schemas/Jam.yaml @@ -1,6 +1,5 @@ title: Jam type: object -description: "" properties: created_at: type: string @@ -26,25 +25,31 @@ properties: type: object properties: closed: - type: string - nullable: true + type: + - string + - "null" format: date-time submissionsClosed: - type: string - nullable: true + type: + - string + - "null" format: date-time submissionsOpened: - type: string - nullable: true + type: + - string + - "null" format: date-time winnersSelected: - type: string - nullable: true - example: null + type: + - string + - "null" + examples: + - null format: date-time submissionContentGateDate: - type: string - nullable: true + type: + - string + - "null" format: date-time submissionContentGated: type: boolean diff --git a/openapi/components/schemas/JamID.yaml b/openapi/components/schemas/JamID.yaml index 01e82379..cf46cc09 100644 --- a/openapi/components/schemas/JamID.yaml +++ b/openapi/components/schemas/JamID.yaml @@ -1,3 +1,4 @@ title: JamID type: string -example: jam_0b7e3f6d-4647-4648-b2a1-1431e76906d9 +examples: + - jam_0b7e3f6d-4647-4648-b2a1-1431e76906d9 diff --git a/openapi/components/schemas/JamSubmission.yaml b/openapi/components/schemas/JamSubmission.yaml index cd0aabef..2a9092ff 100644 --- a/openapi/components/schemas/JamSubmission.yaml +++ b/openapi/components/schemas/JamSubmission.yaml @@ -1,6 +1,5 @@ title: JamSubmission type: object -description: "" properties: contentId: type: string diff --git a/openapi/components/schemas/JamSubmissionID.yaml b/openapi/components/schemas/JamSubmissionID.yaml index 6534729b..47fb2bb2 100644 --- a/openapi/components/schemas/JamSubmissionID.yaml +++ b/openapi/components/schemas/JamSubmissionID.yaml @@ -1,3 +1,4 @@ title: JamSubmissionID type: string -example: jsub_f01f44fa-89fa-443c-ab4c-7fed9245970f +examples: + - jsub_f01f44fa-89fa-443c-ab4c-7fed9245970f diff --git a/openapi/components/schemas/LanguageCode.yaml b/openapi/components/schemas/LanguageCode.yaml index f15040a5..c3d1850b 100644 --- a/openapi/components/schemas/LanguageCode.yaml +++ b/openapi/components/schemas/LanguageCode.yaml @@ -1,4 +1,5 @@ title: LanguageCode type: string description: "Represents a spoken language, signed language, or the absence of linguistic content. Valid language codes and display names are the keys and values respectively in the `$.constants.LANGUAGE.SPOKEN_LANGUAGE_OPTIONS` object from `GET /config`." -example: eng +examples: + - eng diff --git a/openapi/components/schemas/LicenseAction.yaml b/openapi/components/schemas/LicenseAction.yaml index e4060102..8df607b8 100644 --- a/openapi/components/schemas/LicenseAction.yaml +++ b/openapi/components/schemas/LicenseAction.yaml @@ -4,4 +4,5 @@ enum: - have - wear default: have -example: have +examples: + - have diff --git a/openapi/components/schemas/LicenseGroup.yaml b/openapi/components/schemas/LicenseGroup.yaml index 90b889ef..e968e369 100644 --- a/openapi/components/schemas/LicenseGroup.yaml +++ b/openapi/components/schemas/LicenseGroup.yaml @@ -1,6 +1,5 @@ title: LicenseGroup type: object -description: "" properties: description: type: string @@ -18,28 +17,28 @@ required: - id - licenses - name -example: - id: lgrp_608513da-b213-4e15-80af-bd88c27f0979 - name: vrcplus - description: VRC+ benefits - licenses: - - forAction: have - forId: prms_1d9549db-d30a-48f3-a6b8-6741ce5a4283 - forName: permission-user-icons - forType: permission - - forAction: have - forId: prms_76f33deb-dd5d-46b7-b79d-e1f8f0a9a1e0 - forName: permission-supporter-tags - forType: permission - - forAction: have - forId: prms_0d9549db-d30a-48f3-a6b8-6741ce5a4283 - forName: permission-invite-photos - forType: permission - - forAction: have - forId: prms_dc02c512-4c03-479c-8c6a-d9329c023baf - forName: permission-user-gallery - forType: permission - - forAction: have - forId: prms_153ac0b7-c2dd-43f9-96e3-c61fd2e85509 - forName: permission-profile-pic-override - forType: permission +examples: + - id: lgrp_608513da-b213-4e15-80af-bd88c27f0979 + name: vrcplus + description: VRC+ benefits + licenses: + - forAction: have + forId: prms_1d9549db-d30a-48f3-a6b8-6741ce5a4283 + forName: permission-user-icons + forType: permission + - forAction: have + forId: prms_76f33deb-dd5d-46b7-b79d-e1f8f0a9a1e0 + forName: permission-supporter-tags + forType: permission + - forAction: have + forId: prms_0d9549db-d30a-48f3-a6b8-6741ce5a4283 + forName: permission-invite-photos + forType: permission + - forAction: have + forId: prms_dc02c512-4c03-479c-8c6a-d9329c023baf + forName: permission-user-gallery + forType: permission + - forAction: have + forId: prms_153ac0b7-c2dd-43f9-96e3-c61fd2e85509 + forName: permission-profile-pic-override + forType: permission diff --git a/openapi/components/schemas/LicenseGroupID.yaml b/openapi/components/schemas/LicenseGroupID.yaml index 98751ce1..2ab3db86 100644 --- a/openapi/components/schemas/LicenseGroupID.yaml +++ b/openapi/components/schemas/LicenseGroupID.yaml @@ -1,3 +1,4 @@ title: LicenseGroupID type: string -example: lgrp_608513da-b213-4e15-80af-bd88c27f0979 +examples: + - lgrp_608513da-b213-4e15-80af-bd88c27f0979 diff --git a/openapi/components/schemas/LicenseType.yaml b/openapi/components/schemas/LicenseType.yaml index fa5cac95..c18cd4a6 100644 --- a/openapi/components/schemas/LicenseType.yaml +++ b/openapi/components/schemas/LicenseType.yaml @@ -6,4 +6,5 @@ enum: - permission - product default: permission -example: permission +examples: + - permission diff --git a/openapi/components/schemas/LimitedGroup.yaml b/openapi/components/schemas/LimitedGroup.yaml index e7015f78..86aada23 100644 --- a/openapi/components/schemas/LimitedGroup.yaml +++ b/openapi/components/schemas/LimitedGroup.yaml @@ -2,11 +2,13 @@ title: LimitedGroup type: object properties: bannerId: - type: string - nullable: true + type: + - string + - "null" bannerUrl: - type: string - nullable: true + type: + - string + - "null" createdAt: type: string format: date-time @@ -16,15 +18,16 @@ properties: $ref: ./GroupDiscriminator.yaml galleries: type: array - description: " " items: $ref: ./GroupGallery.yaml iconId: - type: string - nullable: true + type: + - string + - "null" iconUrl: - type: string - nullable: true + type: + - string + - "null" id: $ref: ./GroupID.yaml isSearchable: @@ -35,17 +38,19 @@ properties: $ref: ./GroupMemberStatus.yaml name: type: string - nameplateId: {} - nameplateUrl: {} + nameplateId: + $ref: ./Unknown.yaml + nameplateUrl: + $ref: ./Unknown.yaml ownerId: $ref: ./UserID.yaml rules: - type: string - nullable: true + type: + - string + - "null" shortCode: $ref: ./GroupShortCode.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml diff --git a/openapi/components/schemas/LimitedUnityPackage.yaml b/openapi/components/schemas/LimitedUnityPackage.yaml index 3489c046..7a7724d8 100644 --- a/openapi/components/schemas/LimitedUnityPackage.yaml +++ b/openapi/components/schemas/LimitedUnityPackage.yaml @@ -1,16 +1,17 @@ title: LimitedUnityPackage type: object -description: "" properties: created_at: - type: string - nullable: true + type: + - string + - "null" format: date-time platform: $ref: ./Platform.yaml unityVersion: type: string - example: 2022.3.6f1 + examples: + - 2022.3.6f1 minLength: 1 required: - created_at diff --git a/openapi/components/schemas/LimitedUserFriend.yaml b/openapi/components/schemas/LimitedUserFriend.yaml index d1644d77..96b9992d 100644 --- a/openapi/components/schemas/LimitedUserFriend.yaml +++ b/openapi/components/schemas/LimitedUserFriend.yaml @@ -3,24 +3,13 @@ type: object description: User object received when querying your friends list properties: bannerColor: - type: string + $ref: ./Color.yaml bannerType: type: string - bio: + bannerUrl: type: string - bioLinks: - type: array - description: " " - items: - type: string currentAvatarImageUrl: $ref: ./CurrentAvatarImageUrl.yaml - currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml - currentAvatarThumbnailImageUrl: - $ref: ./CurrentAvatarThumbnailImageUrl.yaml developerType: $ref: ./DeveloperType.yaml discordId: @@ -35,21 +24,22 @@ properties: type: string id: $ref: ./UserID.yaml - imageUrl: - type: string isFriend: type: boolean last_activity: - type: string - nullable: true + type: + - string + - "null" format: date-time last_login: - type: string - nullable: true + type: + - string + - "null" format: date-time last_mobile: - type: string - nullable: true + type: + - string + - "null" format: date-time last_platform: $ref: ./Platform.yaml @@ -61,10 +51,6 @@ properties: type: string profileEffect: type: string - profilePicOverride: - type: string - profilePicOverrideThumbnail: - type: string status: $ref: ./UserStatus.yaml statusDescription: @@ -74,14 +60,11 @@ properties: description: <- Always empty. items: $ref: ./Tag.yaml - userIcon: - type: string required: - developerType - displayName - friendKey - id - - imageUrl - isFriend - last_activity - last_login diff --git a/openapi/components/schemas/LimitedUserGroups.yaml b/openapi/components/schemas/LimitedUserGroups.yaml index 7774afb4..26e4e7c2 100644 --- a/openapi/components/schemas/LimitedUserGroups.yaml +++ b/openapi/components/schemas/LimitedUserGroups.yaml @@ -2,11 +2,13 @@ title: LimitedUserGroups type: object properties: bannerId: - type: string - nullable: true + type: + - string + - "null" bannerUrl: - type: string - nullable: true + type: + - string + - "null" description: type: string discriminator: @@ -14,22 +16,26 @@ properties: groupId: $ref: ./GroupID.yaml iconId: - type: string - nullable: true + type: + - string + - "null" iconUrl: - type: string - nullable: true + type: + - string + - "null" id: $ref: ./GroupMemberID.yaml isRepresenting: type: boolean lastPostCreatedAt: - type: string - nullable: true + type: + - string + - "null" format: date-time lastPostReadAt: - type: string - nullable: true + type: + - string + - "null" format: date-time memberCount: type: integer @@ -39,11 +45,15 @@ properties: type: boolean name: type: string - nameplateId: {} - nameplateUrl: {} + nameplateId: + $ref: ./Unknown.yaml + nameplateUrl: + $ref: ./Unknown.yaml ownerId: $ref: ./UserID.yaml privacy: type: string shortCode: $ref: ./GroupShortCode.yaml + storeId: + $ref: ./StoreID.yaml diff --git a/openapi/components/schemas/LimitedUserInstance.yaml b/openapi/components/schemas/LimitedUserInstance.yaml index a2f2e311..b3a2c5ae 100644 --- a/openapi/components/schemas/LimitedUserInstance.yaml +++ b/openapi/components/schemas/LimitedUserInstance.yaml @@ -12,7 +12,6 @@ properties: type: string bioLinks: type: array - description: " " items: type: string currentAvatarImageUrl: @@ -24,8 +23,9 @@ properties: currentAvatarThumbnailImageUrl: $ref: ./CurrentAvatarThumbnailImageUrl.yaml date_joined: - type: string - nullable: true + type: + - string + - "null" format: date-time developerType: $ref: ./DeveloperType.yaml @@ -40,12 +40,14 @@ properties: isFriend: type: boolean last_activity: - type: string - nullable: true + type: + - string + - "null" format: date-time last_mobile: - type: string - nullable: true + type: + - string + - "null" format: date-time last_platform: $ref: ./Platform.yaml @@ -73,9 +75,6 @@ required: - ageVerificationStatus - ageVerified - allowAvatarCopying - - currentAvatarImageUrl - - currentAvatarTags - - currentAvatarThumbnailImageUrl - date_joined - developerType - displayName diff --git a/openapi/components/schemas/LimitedUserSearch.yaml b/openapi/components/schemas/LimitedUserSearch.yaml index e8917824..8fb2e0e4 100644 --- a/openapi/components/schemas/LimitedUserSearch.yaml +++ b/openapi/components/schemas/LimitedUserSearch.yaml @@ -3,26 +3,11 @@ type: object description: User object received when searching properties: bannerColor: - type: string + $ref: ./Color.yaml bannerType: type: string bannerUrl: type: string - bio: - type: string - bioLinks: - type: array - description: " " - items: - type: string - currentAvatarImageUrl: - $ref: ./CurrentAvatarImageUrl.yaml - currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml - currentAvatarThumbnailImageUrl: - $ref: ./CurrentAvatarThumbnailImageUrl.yaml developerType: $ref: ./DeveloperType.yaml displayName: @@ -41,8 +26,6 @@ properties: type: string profileEffect: type: string - profilePicOverride: - type: string pronouns: type: string status: @@ -54,12 +37,7 @@ properties: description: <- Always empty. items: $ref: ./Tag.yaml - userIcon: - type: string required: - - currentAvatarImageUrl - - currentAvatarTags - - currentAvatarThumbnailImageUrl - developerType - displayName - id diff --git a/openapi/components/schemas/LimitedWorld.yaml b/openapi/components/schemas/LimitedWorld.yaml index ef4c4928..4bf198fa 100644 --- a/openapi/components/schemas/LimitedWorld.yaml +++ b/openapi/components/schemas/LimitedWorld.yaml @@ -1,6 +1,5 @@ title: LimitedWorld type: object -description: "" properties: authorId: $ref: ./UserID.yaml @@ -9,7 +8,8 @@ properties: minLength: 1 capacity: type: integer - example: 8 + examples: + - 8 created_at: type: string format: date-time @@ -17,25 +17,31 @@ properties: $ref: ./InstanceContentSettings.yaml disabledPropAbilities: type: array - items: {} + items: + $ref: ./Unknown.yaml favorites: type: integer default: 0 - example: 12024 + examples: + - 12024 minimum: 0 heat: type: integer default: 0 - example: 5 + examples: + - 5 minimum: 0 id: $ref: ./WorldID.yaml imageUrl: type: string minLength: 1 + isHypeTrainEligible: + type: boolean labsPublicationDate: type: string - example: none + examples: + - none minLength: 1 name: type: string @@ -43,34 +49,40 @@ properties: occupants: type: integer default: 0 - example: 47 + examples: + - 47 minimum: 0 organization: type: string default: vrchat minLength: 1 + pendingUpload: + type: boolean popularity: type: integer default: 0 - example: 8 + examples: + - 8 minimum: 0 previewYoutubeId: - type: string - nullable: true + type: + - string + - "null" publicationDate: type: string - example: none + examples: + - none minLength: 1 recommendedCapacity: type: integer - example: 16 + examples: + - 16 releaseStatus: $ref: ./ReleaseStatus.yaml storeId: $ref: ./StoreID.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml thumbnailImageUrl: @@ -82,7 +94,6 @@ properties: $ref: ./UdonProductId.yaml unityPackages: type: array - description: " " items: $ref: ./LimitedUnityPackage.yaml minItems: 1 @@ -92,7 +103,8 @@ properties: visits: type: integer default: 0 - example: 9988675 + examples: + - 9988675 minimum: 0 required: - authorId diff --git a/openapi/components/schemas/LocalDateTime.yaml b/openapi/components/schemas/LocalDateTime.yaml index e1ddffea..d09ee993 100644 --- a/openapi/components/schemas/LocalDateTime.yaml +++ b/openapi/components/schemas/LocalDateTime.yaml @@ -1,4 +1,5 @@ title: LocalDateTime type: string description: "A date and time of the pattern `M/d/yyyy h:mm:ss tt` (see C Sharp `System.DateTime`)" -example: "12/12/2021 1:23:43 AM" +examples: + - "12/12/2021 1:23:43 AM" diff --git a/openapi/components/schemas/LocalizedString.yaml b/openapi/components/schemas/LocalizedString.yaml index 7d4c36f3..8709961a 100644 --- a/openapi/components/schemas/LocalizedString.yaml +++ b/openapi/components/schemas/LocalizedString.yaml @@ -5,11 +5,13 @@ properties: fallback: type: string description: The text to show when `key` cannot be resolved. - example: carnival + examples: + - carnival key: type: string description: The localization key. - example: SuggestedSearch/Carnival/Name/carnival + examples: + - SuggestedSearch/Carnival/Name/carnival required: - fallback - key diff --git a/openapi/components/schemas/LocationID.yaml b/openapi/components/schemas/LocationID.yaml index 6ef251df..01fb477f 100644 --- a/openapi/components/schemas/LocationID.yaml +++ b/openapi/components/schemas/LocationID.yaml @@ -1,4 +1,5 @@ title: LocationID type: string description: Represents a unique location, consisting of a world identifier and an instance identifier, or "offline" if the user is not on your friends list. -example: "wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd:12345~hidden(usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469)~region(eu)~nonce(27e8414a-59a0-4f3d-af1f-f27557eb49a2)" +examples: + - "wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd:12345~hidden(usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469)~region(eu)~nonce(27e8414a-59a0-4f3d-af1f-f27557eb49a2)" diff --git a/openapi/components/schemas/MIMEType.yaml b/openapi/components/schemas/MIMEType.yaml index 0a2f72bf..bc41f8af 100644 --- a/openapi/components/schemas/MIMEType.yaml +++ b/openapi/components/schemas/MIMEType.yaml @@ -17,4 +17,5 @@ enum: - image/tiff - image/webp default: image/jpeg -example: image/jpeg +examples: + - image/jpeg diff --git a/openapi/components/schemas/ModerationReport.yaml b/openapi/components/schemas/ModerationReport.yaml index 0c832c4d..232e94b3 100644 --- a/openapi/components/schemas/ModerationReport.yaml +++ b/openapi/components/schemas/ModerationReport.yaml @@ -4,21 +4,32 @@ properties: category: type: string description: Valid values are the keys of the object `$.reportOptions[type]` from `GET /config`. Descriptions of these are found at `$.reportCategories[type]`. - example: behavior + examples: + - behavior contentId: type: string - example: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + examples: + - usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 contentName: type: string contentThumbnailImageUrl: + type: + - string + - "null" + created: type: string - nullable: true + format: date-time description: - type: string + type: + - string + - "null" description: The subjective reason for the report - example: iz bulli + examples: + - iz bulli evidenceRequired: - type: boolean + type: + - boolean + - "null" id: $ref: ./ModerationReportID.yaml reason: @@ -29,12 +40,14 @@ properties: type: type: string description: Valid values are the keys of the object `$.reportOptions` from `GET /config`. - example: user + examples: + - user required: - category - contentId - contentName - contentThumbnailImageUrl + - created - description - evidenceRequired - id diff --git a/openapi/components/schemas/ModerationReportID.yaml b/openapi/components/schemas/ModerationReportID.yaml index d73afaef..98960a67 100644 --- a/openapi/components/schemas/ModerationReportID.yaml +++ b/openapi/components/schemas/ModerationReportID.yaml @@ -1,3 +1,4 @@ title: ModerationReportID type: string -example: modReport_a09eb23c-2c62-4ea9-b885-6198f23c5313 +examples: + - modReport_a09eb23c-2c62-4ea9-b885-6198f23c5313 diff --git a/openapi/components/schemas/MutualFriend.yaml b/openapi/components/schemas/MutualFriend.yaml index 48f23da9..d0dc80da 100644 --- a/openapi/components/schemas/MutualFriend.yaml +++ b/openapi/components/schemas/MutualFriend.yaml @@ -2,23 +2,14 @@ title: MutualFriend type: object description: User object received when querying mutual friends properties: - avatarThumbnail: - $ref: ./CurrentAvatarThumbnailImageUrl.yaml bannerColor: - type: string - description: Hex colour without a leading `#`. - example: 3cc92c + $ref: ./Color.yaml bannerType: type: string - example: color - currentAvatarImageUrl: - $ref: ./CurrentAvatarImageUrl.yaml - currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml - currentAvatarThumbnailImageUrl: - $ref: ./CurrentAvatarThumbnailImageUrl.yaml + examples: + - color + bannerUrl: + type: string displayName: type: string iconFrame: @@ -27,22 +18,16 @@ properties: type: string id: $ref: ./UserID.yaml - imageUrl: - type: string nameplateEffect: type: string profileEffect: type: string - profilePicOverride: - type: string status: $ref: ./UserStatus.yaml statusDescription: type: string required: - - currentAvatarImageUrl - displayName - id - - imageUrl - status - statusDescription diff --git a/openapi/components/schemas/Notification.yaml b/openapi/components/schemas/Notification.yaml index 4637ed91..af17bca0 100644 --- a/openapi/components/schemas/Notification.yaml +++ b/openapi/components/schemas/Notification.yaml @@ -1,6 +1,5 @@ title: Notification type: object -description: "" properties: created_at: type: string @@ -9,14 +8,15 @@ properties: type: string description: "**NOTICE:** This is not a JSON object when received from the REST API, but it is when received from the Websocket API. When received from the REST API, this is a json **encoded** object, meaning you have to json-de-encode to get the NotificationDetail object depending on the NotificationType." default: "{}" - example: "OneOf: {}, NotificationDetailBoop, NotificationDetailInvite, NotificationDetailInviteResponse, NotificationDetailRequestInvite, NotificationDetailRequestInviteResponse, NotificationDetailVoteToKick" + examples: + - "OneOf: {}, NotificationDetailBoop, NotificationDetailInvite, NotificationDetailInviteResponse, NotificationDetailRequestInvite, NotificationDetailRequestInviteResponse, NotificationDetailVoteToKick" id: type: string minLength: 1 message: type: string - description: "" - example: This is a generated invite to VRChat Hub + examples: + - This is a generated invite to VRChat Hub receiverUserId: $ref: ./UserID.yaml description: Not included in notification objects received from the REST API @@ -27,9 +27,10 @@ properties: senderUserId: $ref: ./UserID.yaml senderUsername: - type: string + type: + - string + - "null" description: The name of the user who sent the notification. - nullable: true minLength: 1 type: $ref: ./NotificationType.yaml diff --git a/openapi/components/schemas/NotificationDetailGeneric.yaml b/openapi/components/schemas/NotificationDetailGeneric.yaml deleted file mode 100644 index df5ac867..00000000 --- a/openapi/components/schemas/NotificationDetailGeneric.yaml +++ /dev/null @@ -1,4 +0,0 @@ -title: NotificationDetailGeneric -type: object -additionalProperties: - type: string diff --git a/openapi/components/schemas/NotificationID.yaml b/openapi/components/schemas/NotificationID.yaml index bb3ada34..324a5029 100644 --- a/openapi/components/schemas/NotificationID.yaml +++ b/openapi/components/schemas/NotificationID.yaml @@ -1,3 +1,4 @@ title: NotificationID type: string -example: not_00000000-0000-0000-0000-000000000000 +examples: + - not_00000000-0000-0000-0000-000000000000 diff --git a/openapi/components/schemas/NotificationV2.yaml b/openapi/components/schemas/NotificationV2.yaml index 99ce7b4f..d4bab560 100644 --- a/openapi/components/schemas/NotificationV2.yaml +++ b/openapi/components/schemas/NotificationV2.yaml @@ -1,6 +1,5 @@ title: NotificationV2 type: object -description: "" properties: canDelete: type: boolean @@ -10,59 +9,64 @@ properties: type: string format: date-time data: - x-if: - when: jsonschema - then: - oneOf: - - $ref: ./NotificationEmpty.yaml - - $ref: ./NotificationV2DataBadgeEarned.yaml - - $ref: ./NotificationV2DataBoop.yaml - - $ref: ./NotificationV2DataEventAnnouncement.yaml - - $ref: ./NotificationV2DataGroupAnnouncement.yaml - - $ref: ./NotificationV2DataGroupInformative.yaml - - $ref: ./NotificationV2DataGroupTransfer.yaml - else: - $ref: ./NotificationV2DataGeneric.yaml + oneOf: + - $ref: ./NotificationEmpty.yaml + - $ref: ./NotificationV2DataBadgeEarned.yaml + - $ref: ./NotificationV2DataBoop.yaml + - $ref: ./NotificationV2DataEventAnnouncement.yaml + - $ref: ./NotificationV2DataGroupAnnouncement.yaml + - $ref: ./NotificationV2DataGroupInformative.yaml + - $ref: ./NotificationV2DataGroupTransfer.yaml details: $ref: ./NotificationV2DetailsBoop.yaml - displayData: {} + displayData: + $ref: ./Unknown.yaml expiresAt: type: string format: date-time expiryAfterSeen: - type: integer - nullable: true + type: + - integer + - "null" id: type: string ignoreDND: type: boolean imageUrl: - type: string - nullable: true + type: + - string + - "null" isSystem: type: boolean link: - type: string - nullable: true - example: "event:grp_00000000-0000-0000-0000-000000000000,cal_00000000-0000-0000\ - -0000-000000000000" + type: + - string + - "null" + examples: + - "event:grp_00000000-0000-0000-0000-000000000000,cal_00000000-0000-0000\ + -0000-000000000000" linkText: - type: string - nullable: true + type: + - string + - "null" linkTextKey: - type: string - nullable: true + type: + - string + - "null" message: type: string messageKey: - type: string - nullable: true + type: + - string + - "null" receiverUserId: $ref: ./UserID.yaml relatedNotificationsId: - type: string - nullable: true - example: cal_00000000-0000-0000-0000-000000000000 + type: + - string + - "null" + examples: + - cal_00000000-0000-0000-0000-000000000000 requireSeen: type: boolean responses: @@ -72,16 +76,19 @@ properties: seen: type: boolean senderUserId: - $ref: ./UserID.yaml - nullable: true + anyOf: + - $ref: ./UserID.yaml + - type: "null" senderUsername: - type: string - nullable: true + type: + - string + - "null" title: type: string titleKey: - type: string - nullable: true + type: + - string + - "null" type: $ref: ./NotificationV2Type.yaml updatedAt: diff --git a/openapi/components/schemas/NotificationV2Category.yaml b/openapi/components/schemas/NotificationV2Category.yaml index 5a01d9b5..b7724f8c 100644 --- a/openapi/components/schemas/NotificationV2Category.yaml +++ b/openapi/components/schemas/NotificationV2Category.yaml @@ -1,7 +1,8 @@ title: NotificationV2Category type: string -example: > - Event: - value: event - Group: - value: social.group +examples: + - > + Event: + value: event + Group: + value: social.group diff --git a/openapi/components/schemas/NotificationV2DataGeneric.yaml b/openapi/components/schemas/NotificationV2DataGeneric.yaml deleted file mode 100644 index a07dd271..00000000 --- a/openapi/components/schemas/NotificationV2DataGeneric.yaml +++ /dev/null @@ -1,4 +0,0 @@ -title: NotificationV2DataGeneric -type: object -additionalProperties: - type: string diff --git a/openapi/components/schemas/NotificationV2DetailsBoop.yaml b/openapi/components/schemas/NotificationV2DetailsBoop.yaml index c9f5de1b..37790e34 100644 --- a/openapi/components/schemas/NotificationV2DetailsBoop.yaml +++ b/openapi/components/schemas/NotificationV2DetailsBoop.yaml @@ -5,8 +5,9 @@ properties: emojiId: $ref: ../schemas/EmojiID.yaml emojiVersion: - type: integer - nullable: true + type: + - integer + - "null" inventoryItemId: $ref: ../schemas/InventoryItemID.yaml required: diff --git a/openapi/components/schemas/NotificationV2Response.yaml b/openapi/components/schemas/NotificationV2Response.yaml index 3a12a9ad..313e70f1 100644 --- a/openapi/components/schemas/NotificationV2Response.yaml +++ b/openapi/components/schemas/NotificationV2Response.yaml @@ -8,8 +8,9 @@ properties: text: type: string textKey: - type: string - nullable: true + type: + - string + - "null" type: $ref: ./NotificationV2ResponseType.yaml required: diff --git a/openapi/components/schemas/NotificationV2ResponseIcon.yaml b/openapi/components/schemas/NotificationV2ResponseIcon.yaml index 6a918e89..4cbd5c32 100644 --- a/openapi/components/schemas/NotificationV2ResponseIcon.yaml +++ b/openapi/components/schemas/NotificationV2ResponseIcon.yaml @@ -1,9 +1,10 @@ title: NotificationV2ResponseIcon type: string -example: > - Bell: - value: bell - Bell Slash: - value: bell-slash - Check: - value: check +examples: + - > + Bell: + value: bell + Bell Slash: + value: bell-slash + Check: + value: check diff --git a/openapi/components/schemas/NotificationV2ResponseType.yaml b/openapi/components/schemas/NotificationV2ResponseType.yaml index a9491871..3d2d9b62 100644 --- a/openapi/components/schemas/NotificationV2ResponseType.yaml +++ b/openapi/components/schemas/NotificationV2ResponseType.yaml @@ -1,13 +1,14 @@ title: NotificationV2ResponseType type: string -example: > - Accept: - value: accept - Boop: - value: boop - Decline: - value: decline - Delete: - value: delete - Unsubscribe: - value: unsubscribe +examples: + - > + Accept: + value: accept + Boop: + value: boop + Decline: + value: decline + Delete: + value: delete + Unsubscribe: + value: unsubscribe diff --git a/openapi/components/schemas/OAuthRedirectCode.yaml b/openapi/components/schemas/OAuthRedirectCode.yaml index fddd2817..53ca0224 100644 --- a/openapi/components/schemas/OAuthRedirectCode.yaml +++ b/openapi/components/schemas/OAuthRedirectCode.yaml @@ -4,7 +4,8 @@ description: A short-lived code used to hand the current session to an OAuth red properties: code: type: string - example: redirect_00000000-0000-0000-0000-000000000000 + examples: + - redirect_00000000-0000-0000-0000-000000000000 minLength: 1 required: - code diff --git a/openapi/components/schemas/OrderOption.yaml b/openapi/components/schemas/OrderOption.yaml index e2325d25..dd761409 100644 --- a/openapi/components/schemas/OrderOption.yaml +++ b/openapi/components/schemas/OrderOption.yaml @@ -4,4 +4,5 @@ enum: - ascending - descending default: descending -example: descending +examples: + - descending diff --git a/openapi/components/schemas/OrderOptionShort.yaml b/openapi/components/schemas/OrderOptionShort.yaml index 71e8c9b2..21c82ddf 100644 --- a/openapi/components/schemas/OrderOptionShort.yaml +++ b/openapi/components/schemas/OrderOptionShort.yaml @@ -4,4 +4,5 @@ enum: - asc - desc default: desc -example: desc +examples: + - desc diff --git a/openapi/components/schemas/PaginatedCalendarEventList.yaml b/openapi/components/schemas/PaginatedCalendarEventList.yaml index afea965d..f752afce 100644 --- a/openapi/components/schemas/PaginatedCalendarEventList.yaml +++ b/openapi/components/schemas/PaginatedCalendarEventList.yaml @@ -7,7 +7,6 @@ properties: description: Whether there are more results after this page. results: type: array - description: " " items: $ref: ./CalendarEvent.yaml totalCount: diff --git a/openapi/components/schemas/PaginatedGroupAuditLogEntryList.yaml b/openapi/components/schemas/PaginatedGroupAuditLogEntryList.yaml index d2d1a9ab..a4e266eb 100644 --- a/openapi/components/schemas/PaginatedGroupAuditLogEntryList.yaml +++ b/openapi/components/schemas/PaginatedGroupAuditLogEntryList.yaml @@ -6,7 +6,6 @@ properties: description: Whether there are more results after this page. results: type: array - description: " " items: $ref: ./GroupAuditLogEntry.yaml totalCount: diff --git a/openapi/components/schemas/PastDisplayName.yaml b/openapi/components/schemas/PastDisplayName.yaml index ff6f3b9e..b4756280 100644 --- a/openapi/components/schemas/PastDisplayName.yaml +++ b/openapi/components/schemas/PastDisplayName.yaml @@ -4,9 +4,12 @@ properties: displayName: type: string minLength: 1 + reverted: + type: boolean updated_at: type: string format: date-time required: - displayName + - reverted - updated_at diff --git a/openapi/components/schemas/PerformanceLimiterInfo.yaml b/openapi/components/schemas/PerformanceLimiterInfo.yaml index 14348e3e..486e3a74 100644 --- a/openapi/components/schemas/PerformanceLimiterInfo.yaml +++ b/openapi/components/schemas/PerformanceLimiterInfo.yaml @@ -1,9 +1,9 @@ -title: PerformanceLimiterInfo -type: object -description: Info about the performance limits on a platform -properties: - maxSeats: - type: integer - description: Maximum amount of seats. -1 means no limit. -required: - - maxSeats +title: PerformanceLimiterInfo +type: object +description: Info about the performance limits on a platform +properties: + maxSeats: + type: integer + description: Maximum amount of seats. -1 means no limit. +required: + - maxSeats diff --git a/openapi/components/schemas/PerformanceRatings.yaml b/openapi/components/schemas/PerformanceRatings.yaml index 13f2d9ce..51d4b86a 100644 --- a/openapi/components/schemas/PerformanceRatings.yaml +++ b/openapi/components/schemas/PerformanceRatings.yaml @@ -8,4 +8,5 @@ enum: - None - Poor - VeryPoor -example: Excellent +examples: + - Excellent diff --git a/openapi/components/schemas/Permission.yaml b/openapi/components/schemas/Permission.yaml index dfdada0b..ce90fc82 100644 --- a/openapi/components/schemas/Permission.yaml +++ b/openapi/components/schemas/Permission.yaml @@ -1,6 +1,5 @@ title: Permission type: object -description: "" properties: data: type: object @@ -37,7 +36,8 @@ properties: $ref: ./PermissionID.yaml name: type: string - example: permission-invite-photos + examples: + - permission-invite-photos minLength: 1 ownerDisplayName: type: string diff --git a/openapi/components/schemas/PermissionID.yaml b/openapi/components/schemas/PermissionID.yaml index 0212575b..8a4a5899 100644 --- a/openapi/components/schemas/PermissionID.yaml +++ b/openapi/components/schemas/PermissionID.yaml @@ -1,3 +1,4 @@ title: PermissionID type: string -example: prms_804ba021-9f47-4e25-9847-1f42fdb2e6ff +examples: + - prms_804ba021-9f47-4e25-9847-1f42fdb2e6ff diff --git a/openapi/components/schemas/Platform.yaml b/openapi/components/schemas/Platform.yaml index af6390d9..2d585aad 100644 --- a/openapi/components/schemas/Platform.yaml +++ b/openapi/components/schemas/Platform.yaml @@ -1,4 +1,5 @@ title: Platform type: string description: "This is normally `android`, `ios`, `standalonewindows`, `web`, or the empty value ``, but also supposedly can be any random Unity version such as `2019.2.4-801-Release` or `2019.2.2-772-Release` or even `unknownplatform`." -example: standalonewindows +examples: + - standalonewindows diff --git a/openapi/components/schemas/PlatformBuildInfo.yaml b/openapi/components/schemas/PlatformBuildInfo.yaml index 040bb006..0a65c901 100644 --- a/openapi/components/schemas/PlatformBuildInfo.yaml +++ b/openapi/components/schemas/PlatformBuildInfo.yaml @@ -1,12 +1,12 @@ -title: PlatformBuildInfo -type: object -description: Build information for a platform -properties: - minBuildNumber: - type: integer - description: Minimum build number required for the platform - redirectionAddress: - type: string - description: Redirection URL for updating the app -required: - - minBuildNumber +title: PlatformBuildInfo +type: object +description: Build information for a platform +properties: + minBuildNumber: + type: integer + description: Minimum build number required for the platform + redirectionAddress: + type: string + description: Redirection URL for updating the app +required: + - minBuildNumber diff --git a/openapi/components/schemas/PlatformHistoryEntry.yaml b/openapi/components/schemas/PlatformHistoryEntry.yaml new file mode 100644 index 00000000..7985e541 --- /dev/null +++ b/openapi/components/schemas/PlatformHistoryEntry.yaml @@ -0,0 +1,13 @@ +title: PlatformHistoryEntry +type: object +description: A platform the user was recorded on, and when. +properties: + isMobile: + type: boolean + platform: + anyOf: + - $ref: ./Platform.yaml + - type: "null" + recorded: + type: string + format: date-time diff --git a/openapi/components/schemas/PlayerModerationID.yaml b/openapi/components/schemas/PlayerModerationID.yaml index b4ee4edc..ce22ce95 100644 --- a/openapi/components/schemas/PlayerModerationID.yaml +++ b/openapi/components/schemas/PlayerModerationID.yaml @@ -1,3 +1,4 @@ title: PlayerModerationID type: string -example: pmod_25551a8d-6f5d-430a-88d3-9c0ce08b5244 +examples: + - pmod_25551a8d-6f5d-430a-88d3-9c0ce08b5244 diff --git a/openapi/components/schemas/PlayerModerationType.yaml b/openapi/components/schemas/PlayerModerationType.yaml index 56fc8f52..c3252871 100644 --- a/openapi/components/schemas/PlayerModerationType.yaml +++ b/openapi/components/schemas/PlayerModerationType.yaml @@ -11,4 +11,5 @@ enum: - unmute - unmuteChat default: unmute -example: unmute +examples: + - unmute diff --git a/openapi/components/schemas/Print.yaml b/openapi/components/schemas/Print.yaml index 21af79b5..4c13815f 100644 --- a/openapi/components/schemas/Print.yaml +++ b/openapi/components/schemas/Print.yaml @@ -1,42 +1,42 @@ -title: Print -type: object -description: Info about a print -properties: - authorId: - $ref: ./UserID.yaml - authorName: - type: string - createdAt: - type: string - format: date-time - files: - type: object - properties: - fileId: - $ref: ./FileID.yaml - image: - type: string - description: "Link to file, e.g. https://api.vrchat.cloud/api/1/file/file_66fe782d-f2bd-4462-9761-1d766d7b2b26/1/file" - id: - $ref: ./PrintID.yaml - note: - type: string - ownerId: - $ref: ./UserID.yaml - timestamp: - type: string - format: date-time - worldId: - $ref: ./WorldID.yaml - worldName: - type: string -required: - - authorId - - authorName - - createdAt - - files - - id - - note - - timestamp - - worldId - - worldName +title: Print +type: object +description: Info about a print +properties: + authorId: + $ref: ./UserID.yaml + authorName: + type: string + createdAt: + type: string + format: date-time + files: + type: object + properties: + fileId: + $ref: ./FileID.yaml + image: + type: string + description: "Link to file, e.g. https://api.vrchat.cloud/api/1/file/file_66fe782d-f2bd-4462-9761-1d766d7b2b26/1/file" + id: + $ref: ./PrintID.yaml + note: + type: string + ownerId: + $ref: ./UserID.yaml + timestamp: + type: string + format: date-time + worldId: + $ref: ./WorldID.yaml + worldName: + type: string +required: + - authorId + - authorName + - createdAt + - files + - id + - note + - timestamp + - worldId + - worldName diff --git a/openapi/components/schemas/PrintID.yaml b/openapi/components/schemas/PrintID.yaml index 8936436f..63df22c1 100644 --- a/openapi/components/schemas/PrintID.yaml +++ b/openapi/components/schemas/PrintID.yaml @@ -1,3 +1,4 @@ title: PrintID type: string -example: prnt_0a0aa0a0-85ea-42eb-b2f7-4840d7f341fa +examples: + - prnt_0a0aa0a0-85ea-42eb-b2f7-4840d7f341fa diff --git a/openapi/components/schemas/PrivateProfile.yaml b/openapi/components/schemas/PrivateProfile.yaml index 0447a6dc..8f83b87f 100644 --- a/openapi/components/schemas/PrivateProfile.yaml +++ b/openapi/components/schemas/PrivateProfile.yaml @@ -10,8 +10,9 @@ properties: isFriend: type: boolean note: - type: string - nullable: true + type: + - string + - "null" status: $ref: ./UserStatus.yaml statusDescription: diff --git a/openapi/components/schemas/PrivateProfileActivity.yaml b/openapi/components/schemas/PrivateProfileActivity.yaml index 54d5fdcf..7c40de38 100644 --- a/openapi/components/schemas/PrivateProfileActivity.yaml +++ b/openapi/components/schemas/PrivateProfileActivity.yaml @@ -4,11 +4,17 @@ properties: instanceId: $ref: ./InstanceID.yaml last_activity: - type: string - description: Either a date-time or an empty string. + anyOf: + - type: string + format: date-time + - type: string + const: "" last_login: - type: string - description: Either a date-time or an empty string. + anyOf: + - type: string + format: date-time + - type: string + const: "" location: $ref: ./LocationID.yaml platform: diff --git a/openapi/components/schemas/Product.yaml b/openapi/components/schemas/Product.yaml index eb9fcd07..ad56bf6b 100644 --- a/openapi/components/schemas/Product.yaml +++ b/openapi/components/schemas/Product.yaml @@ -23,11 +23,13 @@ properties: id: $ref: ./ProductID.yaml imageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" imageUrl: - type: string - nullable: true + type: + - string + - "null" parentListings: type: array items: @@ -49,8 +51,9 @@ properties: items: $ref: ./Tag.yaml updated: - type: string - nullable: true + type: + - string + - "null" format: date-time useForSubscriberList: type: boolean diff --git a/openapi/components/schemas/ProductID.yaml b/openapi/components/schemas/ProductID.yaml index 7ef37721..8298a4a6 100644 --- a/openapi/components/schemas/ProductID.yaml +++ b/openapi/components/schemas/ProductID.yaml @@ -1,3 +1,4 @@ title: ProductID type: string -example: prod_bfbc2315-247a-44d7-bfea-5237f8d56cb4 +examples: + - prod_bfbc2315-247a-44d7-bfea-5237f8d56cb4 diff --git a/openapi/components/schemas/ProductListing.yaml b/openapi/components/schemas/ProductListing.yaml index d3d6654f..ec315d26 100644 --- a/openapi/components/schemas/ProductListing.yaml +++ b/openapi/components/schemas/ProductListing.yaml @@ -10,8 +10,9 @@ properties: buyerRefundable: type: boolean collabUserDisplayName: - type: string - nullable: true + type: + - string + - "null" collabUserId: $ref: ./UserID.yaml created: @@ -22,19 +23,23 @@ properties: displayName: type: string duration: - type: integer - nullable: true + type: + - integer + - "null" durationType: - type: string - nullable: true + type: + - string + - "null" groupIcon: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" groupId: $ref: ./GroupID.yaml groupName: - type: string - nullable: true + type: + - string + - "null" hasAvatar: type: boolean hasCompanion: @@ -50,11 +55,13 @@ properties: id: $ref: ./ProductID.yaml imageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" imageUrl: - type: string - nullable: true + type: + - string + - "null" listingType: $ref: ./ProductListingType.yaml listingVariants: @@ -114,8 +121,9 @@ properties: vrcPlusDiscountPrice: type: integer whenToExpire: - type: string - nullable: true + type: + - string + - "null" format: date-time required: - active @@ -131,8 +139,6 @@ required: - productType - products - recurrable - - refundable - sellerDisplayName - sellerId - stackable - - storeIds diff --git a/openapi/components/schemas/ProductListingAttribution.yaml b/openapi/components/schemas/ProductListingAttribution.yaml index 901f1049..7991c7f0 100644 --- a/openapi/components/schemas/ProductListingAttribution.yaml +++ b/openapi/components/schemas/ProductListingAttribution.yaml @@ -2,6 +2,8 @@ title: ProductListingAttribution type: object description: Attribution shown alongside a listing. properties: + collaborationId: + type: string creator: $ref: ./ProductListingAttributionCreator.yaml publisher: diff --git a/openapi/components/schemas/ProductListingVariant.yaml b/openapi/components/schemas/ProductListingVariant.yaml index a16a7856..fcdee6cd 100644 --- a/openapi/components/schemas/ProductListingVariant.yaml +++ b/openapi/components/schemas/ProductListingVariant.yaml @@ -5,8 +5,9 @@ properties: type: string format: date-time listingVariantId: - $ref: ./ProductListingVariantID.yaml - nullable: true + anyOf: + - $ref: ./ProductListingVariantID.yaml + - type: "null" nonRefundable: type: boolean quantity: diff --git a/openapi/components/schemas/ProductListingVariantID.yaml b/openapi/components/schemas/ProductListingVariantID.yaml index 33c548d7..4b98ac09 100644 --- a/openapi/components/schemas/ProductListingVariantID.yaml +++ b/openapi/components/schemas/ProductListingVariantID.yaml @@ -1,3 +1,4 @@ title: ProductListingVariantID type: string -example: listvar_e8658b56-1662-436c-935a-afcf6a7d4fed +examples: + - listvar_e8658b56-1662-436c-935a-afcf6a7d4fed diff --git a/openapi/components/schemas/ProductPurchase.yaml b/openapi/components/schemas/ProductPurchase.yaml index 7d9862e5..dac37dc2 100644 --- a/openapi/components/schemas/ProductPurchase.yaml +++ b/openapi/components/schemas/ProductPurchase.yaml @@ -26,8 +26,9 @@ properties: listingId: $ref: ./ProductID.yaml listingImageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" listingSubtitle: type: string listingType: @@ -43,7 +44,8 @@ properties: properties: locationType: type: string - example: undefined + examples: + - undefined worldId: $ref: ./WorldID.yaml worldName: @@ -58,8 +60,9 @@ properties: purchaseDurationType: type: string purchaseEndDate: - type: string - nullable: true + type: + - string + - "null" format: date-time purchaseFee: type: integer @@ -72,12 +75,14 @@ properties: purchaseQuantity: type: integer purchaseStartDate: - type: string - nullable: true + type: + - string + - "null" format: date-time purchaseToken: - type: object - nullable: true + type: + - object + - "null" purchaseType: type: string purchaseUnitPrice: diff --git a/openapi/components/schemas/ProductPurchaseID.yaml b/openapi/components/schemas/ProductPurchaseID.yaml index 59c59b32..b4c066b1 100644 --- a/openapi/components/schemas/ProductPurchaseID.yaml +++ b/openapi/components/schemas/ProductPurchaseID.yaml @@ -1,3 +1,4 @@ title: ProductPurchaseID type: string -example: pur_f0446b91-e0f7-403e-8932-609d5057898c +examples: + - pur_f0446b91-e0f7-403e-8932-609d5057898c diff --git a/openapi/components/schemas/ProductPurchaseProduct.yaml b/openapi/components/schemas/ProductPurchaseProduct.yaml index f0bf8a44..2ab2eb24 100644 --- a/openapi/components/schemas/ProductPurchaseProduct.yaml +++ b/openapi/components/schemas/ProductPurchaseProduct.yaml @@ -6,11 +6,13 @@ properties: id: $ref: ./ProductID.yaml imageId: - $ref: ./FileID.yaml - nullable: true + anyOf: + - $ref: ./FileID.yaml + - type: "null" licenseId: - type: string - nullable: true + type: + - string + - "null" productType: $ref: ./ProductType.yaml required: diff --git a/openapi/components/schemas/ProductPurchaseRecord.yaml b/openapi/components/schemas/ProductPurchaseRecord.yaml index f891b9bb..ca062758 100644 --- a/openapi/components/schemas/ProductPurchaseRecord.yaml +++ b/openapi/components/schemas/ProductPurchaseRecord.yaml @@ -3,33 +3,40 @@ type: object properties: amount: type: integer - example: 399 + examples: + - 399 balance: type: integer - example: 399 + examples: + - 399 date: type: string format: date-time fromUserDisplayName: type: string - example: VRChat + examples: + - VRChat listingDisplayName: type: string - example: Lucky Red Envelope + examples: + - Lucky Red Envelope listingType: $ref: ./ProductListingType.yaml platform: type: string description: Where (first- or third-party) the purchase was made - example: VRChat + examples: + - VRChat purchaseId: $ref: ./ProductPurchaseID.yaml reason: type: integer - example: 3002 + examples: + - 3002 reasonLabel: type: string - example: Promo Credit + examples: + - Promo Credit transactionId: type: integer transactionLineId: diff --git a/openapi/components/schemas/ProfileGroup.yaml b/openapi/components/schemas/ProfileGroup.yaml new file mode 100644 index 00000000..166ae14d --- /dev/null +++ b/openapi/components/schemas/ProfileGroup.yaml @@ -0,0 +1,9 @@ +title: ProfileGroup +type: object +properties: + iconUrl: + type: string + id: + $ref: ./GroupID.yaml + name: + type: string diff --git a/openapi/components/schemas/ProfileGroups.yaml b/openapi/components/schemas/ProfileGroups.yaml new file mode 100644 index 00000000..3f4cf5f0 --- /dev/null +++ b/openapi/components/schemas/ProfileGroups.yaml @@ -0,0 +1,9 @@ +title: ProfileGroups +type: object +properties: + count: + type: integer + list: + type: array + items: + $ref: ./ProfileGroup.yaml diff --git a/openapi/components/schemas/ProfileRepresentedGroup.yaml b/openapi/components/schemas/ProfileRepresentedGroup.yaml index 259972c4..f2c10b9f 100644 --- a/openapi/components/schemas/ProfileRepresentedGroup.yaml +++ b/openapi/components/schemas/ProfileRepresentedGroup.yaml @@ -2,11 +2,13 @@ title: ProfileRepresentedGroup type: object properties: bannerUrl: - type: string - nullable: true + type: + - string + - "null" iconUrl: - type: string - nullable: true + type: + - string + - "null" id: $ref: ./GroupID.yaml name: diff --git a/openapi/components/schemas/Prop.yaml b/openapi/components/schemas/Prop.yaml index 43a7df88..2bf0cf23 100644 --- a/openapi/components/schemas/Prop.yaml +++ b/openapi/components/schemas/Prop.yaml @@ -1,6 +1,5 @@ title: Prop type: object -description: "" properties: _created_at: type: string @@ -34,8 +33,9 @@ properties: thumbnailImageUrl: type: string unityPackageUrl: - type: string - nullable: true + type: + - string + - "null" unityPackages: type: array items: diff --git a/openapi/components/schemas/PropID.yaml b/openapi/components/schemas/PropID.yaml index 3b9b8a28..0f587635 100644 --- a/openapi/components/schemas/PropID.yaml +++ b/openapi/components/schemas/PropID.yaml @@ -1,3 +1,4 @@ title: PropID type: string -example: prop_829ba6f6-b837-49d9-b9a9-056b82103b58 +examples: + - prop_829ba6f6-b837-49d9-b9a9-056b82103b58 diff --git a/openapi/components/schemas/PropUnityPackage.yaml b/openapi/components/schemas/PropUnityPackage.yaml index 191d55e1..5028afff 100644 --- a/openapi/components/schemas/PropUnityPackage.yaml +++ b/openapi/components/schemas/PropUnityPackage.yaml @@ -1,13 +1,14 @@ title: PropUnityPackage type: object -description: "" properties: assetUrl: type: string - example: https://api.vrchat.cloud/api/1/file/file_c991c050-8b43-4046-8182-24d068524ac5/24/file + examples: + - https://api.vrchat.cloud/api/1/file/file_c991c050-8b43-4046-8182-24d068524ac5/24/file assetVersion: type: integer - example: 4 + examples: + - 4 minimum: 0 platform: $ref: ./Platform.yaml @@ -16,7 +17,8 @@ properties: unityVersion: type: string default: 2022.3.22f1 - example: 2022.3.22f1 + examples: + - 2022.3.22f1 minLength: 1 variant: type: string diff --git a/openapi/components/schemas/PublicProfile.yaml b/openapi/components/schemas/PublicProfile.yaml index c88cec16..c1e8bc89 100644 --- a/openapi/components/schemas/PublicProfile.yaml +++ b/openapi/components/schemas/PublicProfile.yaml @@ -5,6 +5,14 @@ properties: $ref: ./AgeVerificationStatus.yaml ageVerified: $ref: ./AgeVerified.yaml + backgroundGradientBottom: + $ref: ./Color.yaml + backgroundGradientTop: + $ref: ./Color.yaml + backgroundTemplateId: + type: string + backgroundTextureId: + type: string backgroundType: type: string badges: @@ -12,21 +20,43 @@ properties: items: $ref: ./Badge.yaml bannerColor: + $ref: ./Color.yaml + bannerCustomUrl: type: string bannerType: type: string + bannerUrl: + type: string bio: type: string bioLinks: type: array items: type: string + currentAvatar: + $ref: ./AvatarID.yaml + currentAvatarAuthorName: + type: string + currentAvatarImageUrl: + $ref: ./CurrentAvatarImageUrl.yaml + currentAvatarName: + type: string + currentAvatarTags: + type: array + items: + $ref: ./Tag.yaml + currentAvatarThumbnailImageUrl: + $ref: ./CurrentAvatarThumbnailImageUrl.yaml displayName: type: string + groups: + $ref: ./ProfileGroups.yaml hasVrcPlus: type: boolean iconFrame: type: string + iconType: + type: string iconUrl: type: string id: @@ -43,12 +73,40 @@ properties: type: string pronouns: type: string + publicWorlds: + type: array + items: + $ref: ./LimitedWorld.yaml representedGroup: - $ref: ./ProfileRepresentedGroup.yaml - nullable: true + anyOf: + - $ref: ./ProfileRepresentedGroup.yaml + - type: "null" + status: + $ref: ./UserStatus.yaml + statusDescription: + type: string + themeButtonColor: + $ref: ./Color.yaml + themeIconColor: + $ref: ./Color.yaml themeId: type: string + themeSubtextColor: + $ref: ./Color.yaml + themes: + type: array + items: + $ref: ./Unknown.yaml + totalPublicWorldsCount: + type: integer trustTags: type: array items: $ref: ./Tag.yaml + userIcon: + type: string + worldFavoriteLists: + type: array + description: The owner's public world favorite groups. + items: + $ref: ./WorldFavoriteList.yaml diff --git a/openapi/components/schemas/Region.yaml b/openapi/components/schemas/Region.yaml index 23ed8d19..41dccd8d 100644 --- a/openapi/components/schemas/Region.yaml +++ b/openapi/components/schemas/Region.yaml @@ -10,4 +10,5 @@ enum: - usw - usx default: us -example: eu +examples: + - eu diff --git a/openapi/components/schemas/ReleaseStatus.yaml b/openapi/components/schemas/ReleaseStatus.yaml index fbe65f0a..f9a6f314 100644 --- a/openapi/components/schemas/ReleaseStatus.yaml +++ b/openapi/components/schemas/ReleaseStatus.yaml @@ -6,4 +6,5 @@ enum: - private - public default: public -example: public +examples: + - public diff --git a/openapi/components/schemas/RepresentedGroup.yaml b/openapi/components/schemas/RepresentedGroup.yaml index 350516df..602463ce 100644 --- a/openapi/components/schemas/RepresentedGroup.yaml +++ b/openapi/components/schemas/RepresentedGroup.yaml @@ -2,11 +2,13 @@ title: RepresentedGroup type: object properties: bannerId: - type: string - nullable: true + type: + - string + - "null" bannerUrl: - type: string - nullable: true + type: + - string + - "null" description: type: string discriminator: @@ -14,11 +16,13 @@ properties: groupId: $ref: ./GroupID.yaml iconId: - type: string - nullable: true + type: + - string + - "null" iconUrl: - type: string - nullable: true + type: + - string + - "null" isRepresenting: type: boolean memberCount: @@ -27,8 +31,10 @@ properties: $ref: ./GroupUserVisibility.yaml name: type: string - nameplateId: {} - nameplateUrl: {} + nameplateId: + $ref: ./Unknown.yaml + nameplateUrl: + $ref: ./Unknown.yaml ownerId: $ref: ./UserID.yaml privacy: diff --git a/openapi/components/schemas/RouteNotImplemented.yaml b/openapi/components/schemas/RouteNotImplemented.yaml index 43f8af9b..39f02029 100644 --- a/openapi/components/schemas/RouteNotImplemented.yaml +++ b/openapi/components/schemas/RouteNotImplemented.yaml @@ -7,12 +7,10 @@ description: >- properties: error: type: string - enum: - - The endpoint you're looking for is not implemented by our system. + const: The endpoint you're looking for is not implemented by our system. status_code: type: integer - enum: - - 404 + const: 404 required: - error - status_code diff --git a/openapi/components/schemas/SentNotification.yaml b/openapi/components/schemas/SentNotification.yaml index 2f660d59..2312bbb5 100644 --- a/openapi/components/schemas/SentNotification.yaml +++ b/openapi/components/schemas/SentNotification.yaml @@ -1,31 +1,25 @@ title: SentNotification type: object -description: "" properties: created_at: type: string format: date-time details: - x-if: - when: jsonschema - then: - oneOf: - - $ref: ./NotificationEmpty.yaml - - $ref: ./NotificationDetailBoop.yaml - - $ref: ./NotificationDetailInvite.yaml - - $ref: ./NotificationDetailInviteResponse.yaml - - $ref: ./NotificationDetailRequestInvite.yaml - - $ref: ./NotificationDetailRequestInviteResponse.yaml - - $ref: ./NotificationDetailVoteToKick.yaml - else: - $ref: ./NotificationDetailGeneric.yaml + oneOf: + - $ref: ./NotificationEmpty.yaml + - $ref: ./NotificationDetailBoop.yaml + - $ref: ./NotificationDetailInvite.yaml + - $ref: ./NotificationDetailInviteResponse.yaml + - $ref: ./NotificationDetailRequestInvite.yaml + - $ref: ./NotificationDetailRequestInviteResponse.yaml + - $ref: ./NotificationDetailVoteToKick.yaml id: type: string minLength: 1 message: type: string - description: "" - example: This is a generated invite to VRChat Hub + examples: + - This is a generated invite to VRChat Hub receiverUserId: $ref: ./UserID.yaml senderUserId: diff --git a/openapi/components/schemas/SortOption.yaml b/openapi/components/schemas/SortOption.yaml index ad9adcc6..d39351eb 100644 --- a/openapi/components/schemas/SortOption.yaml +++ b/openapi/components/schemas/SortOption.yaml @@ -20,4 +20,5 @@ enum: - trust - updated default: popularity -example: popularity +examples: + - popularity diff --git a/openapi/components/schemas/SortOptionProductPurchase.yaml b/openapi/components/schemas/SortOptionProductPurchase.yaml index 14953a04..a5505f75 100644 --- a/openapi/components/schemas/SortOptionProductPurchase.yaml +++ b/openapi/components/schemas/SortOptionProductPurchase.yaml @@ -1,6 +1,9 @@ title: SortOptionProductPurchase type: string enum: + - expireDate + - name - purchaseDate default: purchaseDate -example: purchaseDate +examples: + - purchaseDate diff --git a/openapi/components/schemas/SsoProvider.yaml b/openapi/components/schemas/SsoProvider.yaml index 7fbd589f..9a0d999c 100644 --- a/openapi/components/schemas/SsoProvider.yaml +++ b/openapi/components/schemas/SsoProvider.yaml @@ -6,4 +6,5 @@ description: >- enum: - canny - furality -example: canny +examples: + - canny diff --git a/openapi/components/schemas/StoreContext.yaml b/openapi/components/schemas/StoreContext.yaml index 47d9f011..c48bfae6 100644 --- a/openapi/components/schemas/StoreContext.yaml +++ b/openapi/components/schemas/StoreContext.yaml @@ -4,8 +4,9 @@ properties: id: type: string imageUrl: - type: string - nullable: true + type: + - string + - "null" name: type: string required: diff --git a/openapi/components/schemas/StoreID.yaml b/openapi/components/schemas/StoreID.yaml index a7ff8c48..91ab0816 100644 --- a/openapi/components/schemas/StoreID.yaml +++ b/openapi/components/schemas/StoreID.yaml @@ -1,3 +1,4 @@ title: StoreID type: string -example: esto_713b247d-2b5d-41a0-bba3-50db28dc1498 +examples: + - esto_713b247d-2b5d-41a0-bba3-50db28dc1498 diff --git a/openapi/components/schemas/StoreShelf.yaml b/openapi/components/schemas/StoreShelf.yaml index 05ad68b4..1bed4cfd 100644 --- a/openapi/components/schemas/StoreShelf.yaml +++ b/openapi/components/schemas/StoreShelf.yaml @@ -17,12 +17,20 @@ properties: $ref: ./ProductListing.yaml shelfBackgroundImageId: $ref: ./FileID.yaml + shelfClientBannerImageId: + $ref: ./FileID.yaml shelfDescription: type: string shelfIconImageId: $ref: ./FileID.yaml shelfLayout: type: string + shelfMobileHeroBannerImageId: + $ref: ./FileID.yaml + shelfMobileLogoImageId: + $ref: ./FileID.yaml + shelfMobileSecondaryBannerImageId: + $ref: ./FileID.yaml shelfTabBackgroundImageId: $ref: ./FileID.yaml shelfTitle: diff --git a/openapi/components/schemas/StoreShelfID.yaml b/openapi/components/schemas/StoreShelfID.yaml index ceeb668a..2432e80d 100644 --- a/openapi/components/schemas/StoreShelfID.yaml +++ b/openapi/components/schemas/StoreShelfID.yaml @@ -1,3 +1,4 @@ title: StoreShelfID type: string -example: ess_964dd7aa-f881-4ba1-adf7-261e906b9189 +examples: + - ess_964dd7aa-f881-4ba1-adf7-261e906b9189 diff --git a/openapi/components/schemas/Subscription.yaml b/openapi/components/schemas/Subscription.yaml index e441380b..fb27654c 100644 --- a/openapi/components/schemas/Subscription.yaml +++ b/openapi/components/schemas/Subscription.yaml @@ -1,6 +1,5 @@ title: Subscription type: object -description: "" properties: amount: type: number @@ -10,13 +9,15 @@ properties: bulkSize: type: integer description: How many subscriptions a gifted bundle grants. - example: 5 + examples: + - 5 description: type: string discountPercentage: type: integer description: Discount applied to a gifted bundle. - example: 10 + examples: + - 10 googlePlanId: type: string googleProductId: @@ -30,7 +31,8 @@ properties: minLength: 1 period: $ref: ./SubscriptionPeriod.yaml - periodAmount: {} + periodAmount: + $ref: ./Unknown.yaml picoSku: type: string minLength: 1 @@ -46,10 +48,10 @@ required: - period - steamItemId - tier -example: - id: vrchatplus-yearly - description: VRChat Plus (Yearly) - amount: 9999 - period: year - steamItemId: "5000" - tier: 5 +examples: + - id: vrchatplus-yearly + description: VRChat Plus (Yearly) + amount: 9999 + period: year + steamItemId: "5000" + tier: 5 diff --git a/openapi/components/schemas/TiliaKyc.yaml b/openapi/components/schemas/TiliaKyc.yaml index c00f3c72..d575920e 100644 --- a/openapi/components/schemas/TiliaKyc.yaml +++ b/openapi/components/schemas/TiliaKyc.yaml @@ -4,15 +4,18 @@ properties: account_id: type: string description: Tilia account identifier. - example: acct_2YYRz9C5xbJWrhI5RLWPnwDLMyq + examples: + - acct_2YYRz9C5xbJWrhI5RLWPnwDLMyq kyc_id: type: string description: KYC verification identifier. - example: kyc_2tDKpjafhPTG729ceA2oIcsQlWA + examples: + - kyc_2tDKpjafhPTG729ceA2oIcsQlWA kyc_requirements: type: string description: Requirement state reported by Tilia. - example: NONE + examples: + - NONE match_checks: type: array description: Match checks returned by Tilia. @@ -21,7 +24,8 @@ properties: pii_level: type: string description: PII verification level. - example: FULL + examples: + - FULL rules: type: array description: Additional rules returned by Tilia. @@ -30,7 +34,8 @@ properties: state: type: string description: Overall KYC state. - example: ACCEPT + examples: + - ACCEPT tilia_retry_rule_code: type: string description: Retry rule code returned by Tilia, if any. diff --git a/openapi/components/schemas/TiliaStatus.yaml b/openapi/components/schemas/TiliaStatus.yaml index d82b9ab1..0e514ef0 100644 --- a/openapi/components/schemas/TiliaStatus.yaml +++ b/openapi/components/schemas/TiliaStatus.yaml @@ -1,6 +1,5 @@ title: TiliaStatus type: object -description: "" properties: economyOnline: type: boolean diff --git a/openapi/components/schemas/TiliaTOS.yaml b/openapi/components/schemas/TiliaTOS.yaml index 0cedaadc..40a65026 100644 --- a/openapi/components/schemas/TiliaTOS.yaml +++ b/openapi/components/schemas/TiliaTOS.yaml @@ -1,6 +1,5 @@ title: TiliaTOS type: object -description: "" properties: signed_tos: type: boolean diff --git a/openapi/components/schemas/Transaction.yaml b/openapi/components/schemas/Transaction.yaml index 4205596b..de11de66 100644 --- a/openapi/components/schemas/Transaction.yaml +++ b/openapi/components/schemas/Transaction.yaml @@ -1,22 +1,17 @@ title: Transaction type: object -description: "" properties: agreement: - x-if: - when: jsonschema - then: - oneOf: - - type: string - - $ref: ./TransactionAgreement.yaml - else: - $ref: ./TransactionAgreement.yaml + oneOf: + - type: string + - $ref: ./TransactionAgreement.yaml created_at: type: string format: date-time error: - type: string - nullable: true + type: + - string + - "null" id: $ref: ./TransactionID.yaml isGift: diff --git a/openapi/components/schemas/TransactionID.yaml b/openapi/components/schemas/TransactionID.yaml index 5d968b1e..dc9212a5 100644 --- a/openapi/components/schemas/TransactionID.yaml +++ b/openapi/components/schemas/TransactionID.yaml @@ -1,3 +1,4 @@ title: TransactionID type: string -example: txn_e5c72948-e735-4880-8245-24b2a41198b0 +examples: + - txn_e5c72948-e735-4880-8245-24b2a41198b0 diff --git a/openapi/components/schemas/TransactionSteamInfo.yaml b/openapi/components/schemas/TransactionSteamInfo.yaml index 65382f10..946aa6c0 100644 --- a/openapi/components/schemas/TransactionSteamInfo.yaml +++ b/openapi/components/schemas/TransactionSteamInfo.yaml @@ -1,6 +1,5 @@ title: TransactionSteamInfo type: object -description: "" properties: orderId: type: string diff --git a/openapi/components/schemas/TransactionSteamWalletInfo.yaml b/openapi/components/schemas/TransactionSteamWalletInfo.yaml index 7d924be2..43010972 100644 --- a/openapi/components/schemas/TransactionSteamWalletInfo.yaml +++ b/openapi/components/schemas/TransactionSteamWalletInfo.yaml @@ -1,30 +1,32 @@ title: TransactionSteamWalletInfo type: object -description: "" properties: country: type: string default: US - example: SE + examples: + - SE minLength: 2 currency: type: string default: USD - example: EUR + examples: + - EUR minLength: 3 state: type: string status: type: string - example: Trusted + examples: + - Trusted minLength: 1 required: - country - currency - state - status -example: - country: SE - currency: EUR - state: "" - status: Trusted +examples: + - country: SE + currency: EUR + state: "" + status: Trusted diff --git a/openapi/components/schemas/TutorialKey.yaml b/openapi/components/schemas/TutorialKey.yaml index 43e95274..9a9482a9 100644 --- a/openapi/components/schemas/TutorialKey.yaml +++ b/openapi/components/schemas/TutorialKey.yaml @@ -1,5 +1,6 @@ title: TutorialKey type: string -description: "The ID of a tutorial, in the format `{platform}:{tutorial}:{version}`. `undefined:undefined:v1` is used as a null-ish or sentinel value." +description: "The ID of a tutorial. A platform tutorial is `{platform}:{store}:v1`, taken from the `X-Platform` and `X-Store` headers, with `undefined` for a header the request left out. Other tutorials take a longer form, such as `platform-agnostic:custom:onboarding-tutorial-world:v1`." default: undefined:undefined:v1 -example: standalonewindows:steam:v1 +examples: + - standalonewindows:steam:v1 diff --git a/openapi/components/schemas/UdonProductId.yaml b/openapi/components/schemas/UdonProductId.yaml index 037a0503..0e6a2984 100644 --- a/openapi/components/schemas/UdonProductId.yaml +++ b/openapi/components/schemas/UdonProductId.yaml @@ -1,4 +1,5 @@ title: UdonProductId type: string description: A unique ID of a Udon Product -example: prod_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 +examples: + - prod_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 diff --git a/openapi/components/schemas/UnavailableWorld.yaml b/openapi/components/schemas/UnavailableWorld.yaml new file mode 100644 index 00000000..73035404 --- /dev/null +++ b/openapi/components/schemas/UnavailableWorld.yaml @@ -0,0 +1,35 @@ +title: UnavailableWorld +type: object +description: "Stands in for a world the API will not describe. `name` and `authorName` are `???`, `imageUrl` is empty, and the counts are `0`." +properties: + authorName: + type: string + examples: + - ??? + capacity: + type: integer + id: + $ref: ./WorldID.yaml + imageUrl: + type: string + isSecure: + type: boolean + name: + type: string + examples: + - ??? + occupants: + type: integer + thumbnailImageUrl: + type: string + examples: + - https://assets.vrchat.com/default/unavailable-world.png +required: + - authorName + - capacity + - id + - imageUrl + - isSecure + - name + - occupants + - thumbnailImageUrl diff --git a/openapi/components/schemas/UnityPackage.yaml b/openapi/components/schemas/UnityPackage.yaml index 42f5f627..0671f565 100644 --- a/openapi/components/schemas/UnityPackage.yaml +++ b/openapi/components/schemas/UnityPackage.yaml @@ -1,58 +1,72 @@ title: UnityPackage type: object -description: "" properties: assetUrl: - type: string - nullable: true - example: https://api.vrchat.cloud/api/1/file/file_cd0caa7b-69ba-4715-8dfe-7d667a9d2537/65/file + type: + - string + - "null" + examples: + - https://api.vrchat.cloud/api/1/file/file_cd0caa7b-69ba-4715-8dfe-7d667a9d2537/65/file assetUrlObject: type: object - example: {} + examples: + - {} assetVersion: type: integer - example: 4 + examples: + - 4 minimum: 0 created_at: - type: string - example: "2020-09-10T06:13:27.777Z" + type: + - string + - "null" + examples: + - "2020-09-10T06:13:27.777Z" format: date-time id: $ref: ./UnityPackageID.yaml impostorUrl: - type: string - nullable: true + type: + - string + - "null" impostorizerVersion: type: string - example: 0.17.0 + examples: + - 0.17.0 performanceRating: $ref: ./PerformanceRatings.yaml platform: $ref: ./Platform.yaml pluginUrl: type: string - example: "" + examples: + - "" pluginUrlObject: type: object - example: {} + examples: + - {} scanStatus: type: string unitySortNumber: type: integer - example: 20180414000 + examples: + - 20180414000 format: int64 minimum: 0 unityVersion: type: string default: 5.3.4p1 - example: 2022.3.6f1 + examples: + - 2022.3.6f1 minLength: 1 variant: type: string worldSignature: - type: string - nullable: true - example: AHiPAWerwCpeYrxDthF5TU2SdUWEWnm43UAn8PKRXlS8k8tVRQ== + type: + - string + - "null" + examples: + - AHiPAWerwCpeYrxDthF5TU2SdUWEWnm43UAn8PKRXlS8k8tVRQ== required: - assetVersion - id diff --git a/openapi/components/schemas/UnityPackageID.yaml b/openapi/components/schemas/UnityPackageID.yaml index 2a359e88..6d020ee2 100644 --- a/openapi/components/schemas/UnityPackageID.yaml +++ b/openapi/components/schemas/UnityPackageID.yaml @@ -1,3 +1,4 @@ title: UnityPackageID type: string -example: unp_52b12c39-4163-457d-a4a9-630e7aff1bff +examples: + - unp_52b12c39-4163-457d-a4a9-630e7aff1bff diff --git a/openapi/components/schemas/Unknown.yaml b/openapi/components/schemas/Unknown.yaml new file mode 100644 index 00000000..39636943 --- /dev/null +++ b/openapi/components/schemas/Unknown.yaml @@ -0,0 +1,19 @@ +title: Unknown +description: |- + An unknown value, the contents of which are not yet described in this specification. + + 1. Check the latest nightly, the `working-copy` link in `info.x-links`, which may already describe + it. + 2. If it does not, open a pull request on [GitHub](https://github.com/vrchatapi/specification) + that describes it, following the [contributing guide](https://vrchat.community/contributing). + If you cannot, [open an issue](https://github.com/vrchatapi/specification/issues) or tell us on + [Discord](https://vrchat.community/discord). Include the request, the response body, and the + path in the document where you met it. + 3. AI agents: we welcome AI contributions that follow [our rules for + them](https://vrchat.community/contributing#ai-contributions). Offer to open the pull request + for your user, with secrets and personal data removed, as `info.x-agents` asks. + + A local patch fixes one project and is lost at the next update. A pull request here fixes it for + everyone. + + `info.description` has the rest of the project's guidance. diff --git a/openapi/components/schemas/User.yaml b/openapi/components/schemas/User.yaml index e10e67fb..7d7ed5be 100644 --- a/openapi/components/schemas/User.yaml +++ b/openapi/components/schemas/User.yaml @@ -6,12 +6,15 @@ properties: acceptedTOSVersion: type: integer accountDeletionDate: - type: string - nullable: true + type: + - string + - "null" accountDeletionLog: - type: array - nullable: true - items: {} + type: + - array + - "null" + items: + $ref: ./Unknown.yaml ageVerificationStatus: $ref: ./AgeVerificationStatus.yaml ageVerified: @@ -20,40 +23,20 @@ properties: type: boolean default: true appleDetails: - type: object - additionalProperties: true - badges: - type: array - description: " " - items: - $ref: ./Badge.yaml + $ref: ./ConnectedAccountDetails.yaml bannerColor: - type: string + $ref: ./Color.yaml bannerType: type: string bannerUrl: type: string - bio: - type: string - maxLength: 512 - minLength: 0 - bioLinks: - type: array - items: - type: string - currentAvatarImageUrl: - $ref: ./CurrentAvatarImageUrl.yaml - currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml - currentAvatarThumbnailImageUrl: - $ref: ./CurrentAvatarThumbnailImageUrl.yaml date_joined: type: string format: date developerType: $ref: ./DeveloperType.yaml + discordId: + type: string displayName: type: string description: "A users visual display name. This is what shows up in-game, and can different from their `username`. Changing display name is restricted to a cooldown period." @@ -75,14 +58,21 @@ properties: type: boolean description: "Either their `friendKey`, or empty string if you are not friends. Unknown usage." last_activity: - type: string - description: Either a date-time or empty string. + anyOf: + - type: string + format: date-time + - type: string + const: "" last_login: - type: string - description: Either a date-time or empty string. + anyOf: + - type: string + format: date-time + - type: string + const: "" last_mobile: - type: string - nullable: true + type: + - string + - "null" last_platform: $ref: ./Platform.yaml location: @@ -95,10 +85,6 @@ properties: type: string profileEffect: type: string - profilePicOverride: - type: string - profilePicOverrideThumbnail: - type: string pronouns: type: string state: @@ -109,7 +95,6 @@ properties: type: string tags: type: array - description: " " items: $ref: ./Tag.yaml travelingToInstance: @@ -118,19 +103,12 @@ properties: type: string travelingToWorld: type: string - userIcon: - type: string worldId: $ref: ./WorldID.yaml required: - ageVerificationStatus - ageVerified - allowAvatarCopying - - bio - - bioLinks - - currentAvatarImageUrl - - currentAvatarTags - - currentAvatarThumbnailImageUrl - date_joined - developerType - displayName @@ -140,11 +118,8 @@ required: - last_activity - last_login - last_platform - - profilePicOverride - - profilePicOverrideThumbnail - pronouns - state - status - statusDescription - tags - - userIcon diff --git a/openapi/components/schemas/UserClientConfig.yaml b/openapi/components/schemas/UserClientConfig.yaml new file mode 100644 index 00000000..09b661f0 --- /dev/null +++ b/openapi/components/schemas/UserClientConfig.yaml @@ -0,0 +1,10 @@ +title: UserClientConfig +type: object +properties: + accessReduceDecorAnim: + type: boolean + configString: + type: string +required: + - accessReduceDecorAnim + - configString diff --git a/openapi/components/schemas/UserCosmetic.yaml b/openapi/components/schemas/UserCosmetic.yaml new file mode 100644 index 00000000..4b76f5b1 --- /dev/null +++ b/openapi/components/schemas/UserCosmetic.yaml @@ -0,0 +1,24 @@ +title: UserCosmetic +type: object +description: A cosmetic a user holds, without the template's presentation fields. +properties: + acquiredOn: + type: string + format: date-time + acquisition: + type: string + id: + $ref: ./InventoryItemID.yaml + itemType: + $ref: ./InventoryItemType.yaml + templateId: + $ref: ./InventoryTemplateID.yaml + userAttributes: + $ref: ./InventoryUserAttributes.yaml +required: + - acquiredOn + - acquisition + - id + - itemType + - templateId + - userAttributes diff --git a/openapi/components/schemas/UserID.yaml b/openapi/components/schemas/UserID.yaml index de5564c3..2205b371 100644 --- a/openapi/components/schemas/UserID.yaml +++ b/openapi/components/schemas/UserID.yaml @@ -1,4 +1,5 @@ title: UserID type: string description: "A users unique ID, usually in the form of `usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469`. Legacy players can have old IDs in the form of `8JoV9XEdpo`. The ID can never be changed." -example: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 +examples: + - usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 diff --git a/openapi/components/schemas/UserNote.yaml b/openapi/components/schemas/UserNote.yaml index d82e2201..676719a1 100644 --- a/openapi/components/schemas/UserNote.yaml +++ b/openapi/components/schemas/UserNote.yaml @@ -12,20 +12,9 @@ properties: type: object properties: id: - $ref: ./UserNoteID.yaml - currentAvatarTags: - type: array - items: - $ref: ./Tag.yaml - currentAvatarThumbnailImageUrl: - $ref: ./CurrentAvatarThumbnailImageUrl.yaml + $ref: ./UserID.yaml displayName: type: string - profilePicOverride: - type: string - nullable: true - userIcon: - type: string targetUserId: $ref: ./UserID.yaml userId: diff --git a/openapi/components/schemas/UserNoteID.yaml b/openapi/components/schemas/UserNoteID.yaml index 6c137827..36721c73 100644 --- a/openapi/components/schemas/UserNoteID.yaml +++ b/openapi/components/schemas/UserNoteID.yaml @@ -1,3 +1,4 @@ title: UserNoteID type: string -example: unt_e9074848-d107-4019-b4aa-bbd19e67660d +examples: + - unt_e9074848-d107-4019-b4aa-bbd19e67660d diff --git a/openapi/components/schemas/UserSubscription.yaml b/openapi/components/schemas/UserSubscription.yaml index 4f2a954c..37b8366f 100644 --- a/openapi/components/schemas/UserSubscription.yaml +++ b/openapi/components/schemas/UserSubscription.yaml @@ -1,25 +1,27 @@ title: UserSubscription type: object -description: "" properties: active: type: boolean default: true amount: type: number - example: 9999 + examples: + - 9999 created_at: type: string format: date-time description: type: string - example: VRChat Plus (Yearly) + examples: + - VRChat Plus (Yearly) expires: type: string format: date-time id: type: string - example: vrchatplus-yearly + examples: + - vrchatplus-yearly minLength: 1 isBulkGift: type: boolean @@ -39,16 +41,19 @@ properties: $ref: ./TransactionStatus.yaml steamItemId: type: string - example: "5000" + examples: + - "5000" minLength: 1 store: type: string description: Which "Store" it came from. Right now only Stores are "Steam" and "Admin". - example: Steam + examples: + - Steam minLength: 1 tier: type: integer - example: 5 + examples: + - 5 transactionId: $ref: ./TransactionID.yaml updated_at: diff --git a/openapi/components/schemas/World.yaml b/openapi/components/schemas/World.yaml index 69baa478..23456219 100644 --- a/openapi/components/schemas/World.yaml +++ b/openapi/components/schemas/World.yaml @@ -1,6 +1,5 @@ title: World type: object -description: "" properties: authorId: $ref: ./UserID.yaml @@ -9,7 +8,8 @@ properties: minLength: 1 capacity: type: integer - example: 8 + examples: + - 8 created_at: type: string format: date-time @@ -20,11 +20,13 @@ properties: minLength: 0 disabledPropAbilities: type: array - items: {} + items: + $ref: ./Unknown.yaml favorites: type: integer default: 0 - example: 12024 + examples: + - 12024 minimum: 0 featured: type: boolean @@ -32,7 +34,8 @@ properties: heat: type: integer default: 0 - example: 5 + examples: + - 5 minimum: 0 id: $ref: ./WorldID.yaml @@ -48,12 +51,16 @@ properties: A fixed triple of instance id, occupant count, and the share of occupants per language code. OpenAPI 3.0 cannot type the positions individually, so the members are only bounded by length. - items: {} + items: + $ref: ./Unknown.yaml maxItems: 3 minItems: 3 + isHypeTrainEligible: + type: boolean labsPublicationDate: type: string - example: none + examples: + - none minLength: 1 name: type: string @@ -64,7 +71,8 @@ properties: type: integer description: Will always be `0` when unauthenticated. default: 0 - example: 47 + examples: + - 47 minimum: 0 organization: type: string @@ -73,40 +81,46 @@ properties: popularity: type: integer default: 0 - example: 8 + examples: + - 8 minimum: 0 previewYoutubeId: - type: string - nullable: true + type: + - string + - "null" privateOccupants: type: integer description: Will always be `0` when unauthenticated. default: 0 - example: 1 + examples: + - 1 minimum: 0 publicOccupants: type: integer description: Will always be `0` when unauthenticated. default: 0 - example: 46 + examples: + - 46 minimum: 0 publicationDate: type: string - example: none + examples: + - none minLength: 1 recommendedCapacity: type: integer - example: 4 + examples: + - 4 releaseStatus: $ref: ./ReleaseStatus.yaml slimInstances: type: array - items: {} + items: + $ref: ./Unknown.yaml storeId: $ref: ./StoreID.yaml tags: type: array - description: " " items: $ref: ./Tag.yaml thumbnailImageUrl: @@ -131,12 +145,14 @@ properties: version: type: integer default: 0 - example: 68 + examples: + - 68 minimum: 0 visits: type: integer default: 0 - example: 9988675 + examples: + - 9988675 minimum: 0 required: - authorId diff --git a/openapi/components/schemas/WorldFavoriteList.yaml b/openapi/components/schemas/WorldFavoriteList.yaml new file mode 100644 index 00000000..ffadd29a --- /dev/null +++ b/openapi/components/schemas/WorldFavoriteList.yaml @@ -0,0 +1,21 @@ +title: WorldFavoriteList +type: object +description: A world favorite group as a public profile lists it, with a sample of its worlds' thumbnails. +properties: + count: + type: integer + minimum: 0 + id: + $ref: ./FavoriteGroupID.yaml + name: + type: string + minLength: 1 + thumbnails: + type: array + items: + type: string +required: + - count + - id + - name + - thumbnails diff --git a/openapi/components/schemas/WorldID.yaml b/openapi/components/schemas/WorldID.yaml index 3a9e47f2..e32789aa 100644 --- a/openapi/components/schemas/WorldID.yaml +++ b/openapi/components/schemas/WorldID.yaml @@ -1,4 +1,5 @@ title: WorldID type: string description: WorldID be "offline" on User profiles if you are not friends with that user. -example: wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd +examples: + - wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd diff --git a/openapi/components/schemas/_index.yaml b/openapi/components/schemas/_index.yaml index 41423318..dccdc0b0 100644 --- a/openapi/components/schemas/_index.yaml +++ b/openapi/components/schemas/_index.yaml @@ -8,3 +8,5 @@ NotificationDetailRequestInviteResponse: $ref: ./NotificationDetailRequestInviteResponse.yaml NotificationDetailVoteToKick: $ref: ./NotificationDetailVoteToKick.yaml +Unknown: + $ref: ./Unknown.yaml diff --git a/openapi/components/tags.yaml b/openapi/components/tags.yaml index 4f79af90..0d9fdce4 100644 --- a/openapi/components/tags.yaml +++ b/openapi/components/tags.yaml @@ -1,62 +1,102 @@ - name: authentication description: $ref: ./paths/authentication.yaml#/info/description + kind: nav + summary: Authentication - name: avatars description: $ref: ./paths/avatars.yaml#/info/description + kind: nav + summary: Avatars - name: calendar description: $ref: ./paths/calendar.yaml#/info/description + kind: nav + summary: Calendar - name: economy description: $ref: ./paths/economy.yaml#/info/description + kind: nav + summary: Economy - name: favorites description: $ref: ./paths/favorites.yaml#/info/description + kind: nav + summary: Favorites - name: files description: $ref: ./paths/files.yaml#/info/description + kind: nav + summary: Files - name: friends description: $ref: ./paths/friends.yaml#/info/description + kind: nav + summary: Friends - name: groups description: $ref: ./paths/groups.yaml#/info/description + kind: nav + summary: Groups - name: inventory description: $ref: ./paths/inventory.yaml#/info/description + kind: nav + summary: Inventory - name: invite description: $ref: ./paths/invite.yaml#/info/description + kind: nav + summary: Invite - name: instances description: $ref: ./paths/instances.yaml#/info/description + kind: nav + summary: Instances - name: jams description: $ref: ./paths/jams.yaml#/info/description + kind: nav + summary: Jams - name: miscellaneous description: $ref: ./paths/miscellaneous.yaml#/info/description + kind: nav + summary: Miscellaneous - name: notifications description: $ref: ./paths/notifications.yaml#/info/description + kind: nav + summary: Notifications - name: playermoderation description: $ref: ./paths/playermoderation.yaml#/info/description + kind: nav + summary: Player Moderation - name: prints description: $ref: ./paths/prints.yaml#/info/description + kind: nav + summary: Prints - name: props description: $ref: ./paths/props.yaml#/info/description + kind: nav + summary: Props - name: users description: $ref: ./paths/users.yaml#/info/description + kind: nav + summary: Users - name: worlds description: $ref: ./paths/worlds.yaml#/info/description + kind: nav + summary: Worlds - name: deprecated description: >- Routes VRChat no longer serves: every call answers the generic "not implemented" 404. They stay described, and the test suite keeps calling them, so a route that comes back online shows up. + kind: badge + summary: Deprecated diff --git a/openapi/description.md b/openapi/description.md new file mode 100644 index 00000000..67a01f77 --- /dev/null +++ b/openapi/description.md @@ -0,0 +1,18 @@ +This specification is maintained by the [VRChat.community](https://vrchat.community) project. **VRChat staff do not provide API support.** Use the API only as VRChat's [Terms of Service](https://hello.vrchat.com/legal), [Community Guidelines](https://hello.vrchat.com/community-guidelines) and [Creator Guidelines](https://hello.vrchat.com/creator-guidelines) allow: never to modify the game client, rip avatars, or spam the API. + +_AI agents: read [`info.x-agents`](https://github.com/vrchatapi/specification/blob/main/openapi/agents.md) before using this specification. We welcome contributions that follow [our rules](https://vrchat.community/contributing#ai-contributions)._ + +Prefer the SDKs over this specification: [JavaScript](https://vrchat.community/javascript), [Dart](https://vrchat.community/dart), [Rust](https://vrchat.community/rust), [C#](https://vrchat.community/dotnet), [Python](https://vrchat.community/python) and [Java](https://vrchat.community/java). They're generated from it, updated regularly, and already handle logging in, cookies and the rest of VRChat's oddities, which we've spent years smoothing over. Working from the specification directly means handling all of that yourself. + +Every request must identify its application in the `User-Agent` header, as `/ `. On a 429, back off rather than retrying. + +**Something wrong or missing?** + +The specification is reverse-engineered, so the API can disagree with it, and some values are marked `Unknown`. When you find one: + +- Open a [pull request](https://github.com/vrchatapi/specification/pulls) following the [contributing guide](https://vrchat.community/contributing). +- Failing that, open an [issue](https://github.com/vrchatapi/specification/issues) or tell us on [Discord](https://vrchat.community/discord). +- Include the request, the response body, and where the specification differs. +- Send it upstream rather than patching around it. Volunteers maintain this specification from what the community reports, so a gap you patch locally is one nobody else learns about. + +Consider pinning to the OpenAPI version your tools support. Every release publishes the specification as OpenAPI 3.2, 3.1 and 3.0, in JSON and YAML, and `info.x-links` links them, the [latest release](https://github.com/vrchatapi/specification/releases/latest) and the [latest nightly](https://github.com/vrchatapi/specification/releases/tag/nightly). diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index f2273700..7d582a00 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1,16 +1,14 @@ -openapi: 3.0.3 +openapi: 3.2.1 info: - title: VRChat API Documentation - version: 1.20.9 + title: VRChat API + version: 1.22.0 contact: - name: Unofficial VRChat API Documentation Project - url: "https://github.com/VRChatAPI" - email: vrchatapi.lpv0t@aries.fyi + name: VRChat API Community + url: "https://vrchat.community" termsOfService: "https://vrchat.com/legal/" license: url: "https://github.com/vrchatapi/specification/blob/master/LICENSE" name: MIT - description: "![VRChat API Banner](https://vrchatapi.github.io/assets/img/api_banner_1500x400.png)\n\n# Welcome to the VRChat API\n\nBefore we begin, we would like to state this is a **COMMUNITY DRIVEN PROJECT**.\nThis means that everything you read on here was written by the community itself and is **not** officially supported by VRChat.\nThe documentation is provided \"AS IS\", and any action you take towards VRChat is completely your own responsibility.\n\nThe documentation and additional libraries SHALL ONLY be used for applications interacting with VRChat's API in accordance\nwith their [Terms of Service](https://hello.vrchat.com/legal) and [Community Guidelines](https://hello.vrchat.com/community-guidelines), and MUST NOT be used for modifying the client, \"avatar ripping\", or other illegal activities.\nMalicious usage or spamming the API may result in account termination.\nCertain parts of the API are also more sensitive than others, for example moderation, so please tread extra carefully and read the warnings when present.\n\n![Tupper Policy on API](https://i.imgur.com/yLlW7Ok.png)\n\nFinally, use of the API using applications other than the approved methods (website, VRChat application, Unity SDK) is not officially supported.\nVRChat provides no guarantee or support for external applications using the API. Access to API endpoints may break **at any time, without notice**.\nTherefore, please **do not ping** VRChat Staff in the VRChat Discord if you are having API problems, as they do not provide API support.\nWe will make a best effort in keeping this documentation and associated language libraries up to date, but things might be outdated or missing.\nIf you find that something is no longer valid, please contact us on Discord or [create an issue](https://github.com/vrchatapi/specification/issues) and tell us so we can fix it.\n\n# Getting Started\n\nThe VRChat API can be used to programmatically retrieve or update information regarding your profile, friends, avatars, worlds and more.\nThe API consists of two parts, \"Photon\" which is only used in-game, and the \"Web API\" which is used by both the game and the website.\nThis documentation focuses only on the Web API.\n\nThe API is designed around the REST ideology, providing semi-simple and usually predictable URIs to access and modify objects.\nRequests support standard HTTP methods like GET, PUT, POST, and DELETE and standard status codes.\nResponse bodies are always UTF-8 encoded JSON objects, unless explicitly documented otherwise.\n\n
\n \U0001F6D1 Warning! Do not touch Photon!
\n Photon is only used by the in-game client and should not be touched. Doing so may result in permanent account termination.\n
\n\n
\n ℹ️ Authentication
\n Read Authentication for how to log in.\n
\n\n# Using the API\n\nFor simply exploring what the API can do it is strongly recommended to download [Insomnia](https://insomnia.rest/download), a free and open-source\nAPI client that's great for sending requests to the API in an orderly fashion.\nInsomnia allows you to send data in the format that's required for VRChat's API.\nIt is also possible to try out the API in your browser, by first logging in at [vrchat.com/home](https://vrchat.com/home/) and then going to\n[vrchat.com/api/1/auth/user](https://vrchat.com/api/1/auth/user), but the information will be much harder to work with.\n\nFor more permanent operation such as software development it is instead recommended to use one of the existing language SDKs.\nThis community project maintains API libraries in several languages, which allows you to interact with the API with simple function calls\nrather than having to implement the HTTP protocol yourself. Most of these libraries are automatically generated from the API specification,\nsometimes with additional helpful wrapper code to make usage easier. This allows them to be almost automatically updated and expanded upon\nas soon as a new feature is introduced in the specification itself. The libraries can be found on [GitHub](https://github.com/vrchatapi) or following:\n\n* [NodeJS (JavaScript)](https://www.npmjs.com/package/vrchat)\n* [Dart](https://pub.dev/packages/vrchat_dart)\n* [Rust](https://crates.io/crates/vrchatapi)\n* [C#](https://github.com/vrchatapi/vrchatapi-csharp)\n* [Python](https://github.com/vrchatapi/vrchatapi-python)\n\n# Pagination\n\nMost endpoints enforce pagination, meaning they will only return 10 entries by default, and never more than 100.
\nUsing both the limit and offset parameters allows you to easily paginate through a large number of objects.\n\n| Query Parameter | Type | Description |\n| ----------|--|------- |\n| `n` | integer | The number of objects to return. This value often defaults to 10. Highest limit is always 100.|\n| `offset` | integer | A zero-based offset from the default object sorting.|\n\nIf a request returns fewer objects than the `limit` parameter, there are no more items available to return.\n\n# Contribution\n\nDo you want to get involved in the documentation effort? Do you want to help improve one of the language API libraries?\nThis project is an [OPEN Open Source Project](https://openopensource.org)! This means that individuals making significant and valuable contributions are given\ncommit-access to the project. It also means we are very open and welcoming of new people making contributions, unlike some more guarded open-source projects.\n\n[![Discord](https://img.shields.io/static/v1?label=vrchatapi&message=discord&color=blueviolet&style=for-the-badge)](https://discord.gg/qjZE9C9fkB)" servers: - url: "https://api.vrchat.cloud/api/1" paths: diff --git a/package.json b/package.json index 8a55ee9d..c72614e9 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ "node": ">=22" }, "scripts": { - "lint-spectral": "bun spectral openapi/openapi.yaml", - "lint-spectral-ci": "bun spectral -i openapi/openapi.yaml", + "lint-openapi": "redocly lint openapi/openapi.yaml --max-problems 1000", + "lint-openapi-ci": "pnpm -s run lint-openapi --format github-actions", "lint-eslint": "eslint .", "lint-eslint-ci": "pnpm -s run lint-eslint -f @jamesacarr/eslint-formatter-github-actions", "lint-arazzo": "redocly lint test/arazzo.yaml", @@ -23,34 +23,29 @@ "bundle": "redocly bundle", "test": "sh test/run.sh", "test:coverage": "redocly coverage test/.out/har --api dist/openapi-internal.json", - "test:drift": "redocly drift test/.out/har --api dist/openapi-test.yaml" + "test:drift": "redocly drift test/.out/har --api dist/openapi-test.yaml --server https://api.vrchat.cloud/api/1 --rules schema-consistency,undocumented-endpoint", + "test:versions": "redocly lint dist/openapi-3.1.json dist/openapi-internal+3.1.json dist/openapi-3.0.json dist/openapi-internal+3.0.json --extends minimal", + "test:downlevel": "pnpm --filter redocly-plugin-downlevel run test && pnpm --filter redocly-plugin-downlevel run build" }, "devDependencies": { "@actions/artifact": "5.0.2", "@actions/core": "^1.11.1", - "@apidevtools/json-schema-ref-parser": "^15.1.2", + "@apidevtools/json-schema-ref-parser": "^15.5.2", "@ariesclark/eslint-config": "^3.1.1", - "@eslint-react/eslint-plugin": "^2.3.9", + "@cspell/eslint-plugin": "^10.3.3", + "@eslint-react/eslint-plugin": "^2.13.0", "@jamesacarr/eslint-formatter-github-actions": "^0.2.0", - "@redocly/cli": "^2.46.0", - "@redocly/openapi-core": "^2.41.2", - "@stoplight/spectral-cli": "^6.15.0", - "@stoplight/spectral-core": "^1.20.0", - "@stoplight/spectral-formats": "^1.8.2", - "@stoplight/spectral-formatters": "^1.5.0", - "@stoplight/spectral-functions": "^1.10.1", - "@stoplight/spectral-parsers": "^1.0.5", - "@stoplight/spectral-rulesets": "^1.22.0", - "@types/bun": "^1.3.3", - "@types/node": "^24.10.1", + "@redocly/cli": "^2.54.3", + "@redocly/openapi-core": "^2.54.3", + "@types/bun": "^1.4.2", + "@types/node": "^24.13.6", "@types/pluralize": "^0.0.33", "change-case": "^5.4.4", - "cspell": "^9.3.2", - "cspell-lib": "^9.3.2", - "eslint": "^9.39.1", + "cspell": "^9.8.0", + "eslint": "^9.39.5", "httpexec": "^0.0.2", "pluralize": "^8.0.0", - "semver": "^7.7.3", + "semver": "^7.8.5", "totp-generator": "^2.0.1", "typescript": "^6.0.3" } diff --git a/packages/redocly-plugin-downlevel/LICENSE b/packages/redocly-plugin-downlevel/LICENSE new file mode 100644 index 00000000..fc48a14e --- /dev/null +++ b/packages/redocly-plugin-downlevel/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021 Owners of GitHub organisation "vrchatapi" and individual contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/redocly-plugin-downlevel/README.md b/packages/redocly-plugin-downlevel/README.md new file mode 100644 index 00000000..07a017ba --- /dev/null +++ b/packages/redocly-plugin-downlevel/README.md @@ -0,0 +1,144 @@ +# redocly-plugin-downlevel + +A [Redocly](https://redocly.com/docs/cli/) plugin that rewrites an OpenAPI 3.x description as an earlier 3.x release, for tools that cannot read the version it is written in: code generators, gateways, validators pinned to 3.0. + +It lowers one release at a time, 3.2.1 → 3.2.0 → 3.1.2 → 3.1.1 → 3.1.0 → 3.0.4 → 3.0.3 → 3.0.2 → 3.0.1 → 3.0.0, and fails the bundle, pointing at the file and line, wherever the target release cannot say what the description says. + +## Install + +```sh +npm install --save-dev redocly-plugin-downlevel +``` + +It needs `@redocly/cli` (or `@redocly/openapi-core`) 2.53.3 or later, and Node.js 22 or later. + +## Use + +```yaml +# redocly.yaml +plugins: + - redocly-plugin-downlevel + +apis: + legacy: + root: openapi.yaml + output: dist/openapi-3.0.yaml + decorators: + downlevel/openapi: + version: "3.0" +``` + +```sh +redocly bundle legacy +``` + +| option | | | +| --- | --- | --- | +| `version` | required | The release to write, such as `"3.0.3"`, or a minor version such as `"3.0"`, which means its latest release. Quote it: YAML reads an unquoted `3.0` as the number 3. | +| `loosenUnions` | default `false` | Replace every `oneOf` and `anyOf` with one schema that accepts everything its members accept. For readers that cannot take unions at all; see [Loosening unions](#loosening-unions). | + +The decorator runs once bundling has finished, so every `$ref` it meets is internal to the bundle. Put it on the APIs that need the older version and leave the others on the source. + +## What happens to a construct + +Each layer does one of three things with a construct the release below it lacks: + +- **rewrite** it into the form the lower release uses, when that form means the same: `type: [string, "null"]` becomes `type: string` with `nullable: true`. Where the lower release has no field for it, the form is the extension its readers take the same thing from: the [OAI extension registry](https://spec.openapis.org/registry/extension/index.html)'s `x-oai-*` and `x-jsonschema-*` entries, and extensions the wider ecosystem reads, such as `x-displayName`. Every extension a reader uses is written, and one the description already carries is kept. +- **drop** it, when it is an annotation or hint whose absence changes nothing a reader validates: `info.summary`, `servers[].name`, a discriminator's `defaultMapping`. +- **report** it, when the lower release cannot say it, no extension carries it, and any rewrite would change what the description accepts or means: `prefixItems`, `in: querystring`, a `oneOf` that must admit `null`. A report is an error, so the bundle is not written. A construct written as an extension keeps its meaning for readers of that extension; a validator that knows none of them accepts more than the source does. + +A layer runs all its checks first, so every problem in a release is reported at once, then its rewrites. + +### 3.2 → 3.1 + +| construct | done | +| --- | --- | +| Tag `summary` | written as the tag's `x-displayName` | +| Tag `parent` | written as `x-tagGroups`: one group per top-level tag, holding it and every tag beneath it, since a renderer leaves out any tag no group names | +| Tag `kind: badge` | written as an `x-badges` entry on each operation carrying the tag, which stays out of `x-tagGroups` | +| Response `summary` | written as `x-oai-summary` and `x-summary` | +| `$self`, `servers[].name`, Security Scheme `deprecated` | written as `x-oai-$self`, `x-oai-name`, `x-oai-deprecated` | +| any other Tag `kind`, Security Scheme `oauth2MetadataUrl`, Discriminator `defaultMapping`, Media Type `description` | dropped | +| Example `dataValue` / `serializedValue` | written as `value`; `serializedValue` also as `x-oai-serializedValue` | +| Path Item `query`, `additionalOperations` | written as `x-oai-additionalOperations`, `query` under `QUERY` | +| Media Type `itemSchema`, `prefixEncoding`, `itemEncoding`; Encoding `encoding`, `itemEncoding` | written as their `x-oai-*` extensions | +| OAuth `deviceAuthorization` and its `deviceAuthorizationUrl` | written as `x-oai-deviceAuthorization` and `x-oai-deviceAuthorizationUrl` | +| XML `nodeType` | written as `attribute` / `wrapped`; `text`, `cdata`, and `none` on a scalar are reported | +| `components.mediaTypes` and Media Type `$ref`s | inlined | +| a Security Requirement naming its scheme by URI | the component name, when the URI points into this document's components; otherwise reported | +| the 3.2 schema dialect in `jsonSchemaDialect` or `$schema` | the 3.1 base dialect | +| `style: deepObject` | `explode: true` written out, the only combination 3.1 defines | +| `example` / `examples` beside a Parameter's or Header's `content` | moved into its Media Type Object | +| `allowReserved: false` beyond `in: query` | dropped | +| a Response without `description` | `description: ""` | +| `in: querystring`; `style: cookie`; `allowReserved: true` beyond `in: query`; Encoding `prefixEncoding`; `encoding` outside a request body; `schema` on a sequential media type; an array `schema` for `multipart/form-data`; a non-ASCII XML `namespace` | reported | + +### 3.1 → 3.0 + +| construct | done | +| --- | --- | +| `type: [X, "null"]` | `type: X`, `nullable: true` | +| `type` naming several types | `anyOf` with one member per type | +| a `null` member of `oneOf` / `anyOf` | `nullable` on one other member, so `null` still matches exactly one; a reference gets `nullable: true` beside its `$ref` (see [Nullable references](#nullable-references)); reported for a `oneOf` where another member already takes `null` | +| numeric `exclusiveMinimum` / `exclusiveMaximum` | the limit in `minimum` / `maximum`, the flag `true`; the tighter bound where both are given | +| schema `examples` | `example: examples[0]`, and the list as `x-jsonschema-examples` | +| `const` | `enum: [value]` | +| `contentEncoding`, `contentMediaType`, `contentSchema` | written as their `x-jsonschema-*` extensions; `base64` and `application/octet-stream` also as `format: byte` and `format: binary` | +| boolean schemas | `{}` and `{not: {}}` | +| keywords beside a schema `$ref` that constrain it | the reference moved into `allOf` | +| `type: array` without `items`, empty `required`, empty `enum` | `items: {}`, removed, `not: {}` | +| an untyped multipart part | `type: string`, `format: binary` | +| `components.pathItems` | inlined | +| `license.identifier`, Schema `$anchor` | written as `x-oai-license-identifier`, `x-jsonschema-$anchor` | +| `contains`, `minContains`, `maxContains`, `if`/`then`/`else`, `dependentSchemas`, `patternProperties`, `propertyNames`, `unevaluatedProperties` | written as their `x-jsonschema-*` extensions, once the schemas inside them are lowered | +| `webhooks` | written as `x-webhooks` | +| `jsonSchemaDialect`, `info.summary`, `$schema`, `$id`, `$comment` and the other identifiers, a `nullable` 3.1 ignores | dropped | +| an empty path item whose template has no path parameter | dropped | +| no `paths` | `paths: {}` | +| `prefixItems`, `unevaluatedItems`, `dependentRequired`, `$dynamicRef`, `$defs` and the other keywords 3.0 has no extension for; `mutualTLS`; an operation without `responses`; a `default` that does not match `type`; `readOnly` with `writeOnly`; a `$ref` fragment that is not a JSON Pointer; roles for a scheme other than OAuth 2 or OpenID Connect; a `requestBody` on GET, HEAD or DELETE; a link into `webhooks`; a relative metadata URL; `style` / `explode` / `allowReserved` in multipart | reported | + +### Patch releases + +Patch releases add no fields, but some changed what a description means. Where the earlier release can be told the later meaning, the layer writes it out; where it cannot, it reports. + +| layer | done | +| --- | --- | +| 3.2.1 → 3.2.0 | names the 3.2 dialect, which 3.2.0 would take as 3.1's; reports `prefixEncoding`/`itemEncoding` without an array or `itemSchema`, and array `multipart/form-data` schemas | +| 3.1.1 → 3.1.0 | writes `encoding.contentType: application/json` for object properties of form bodies; reports relative metadata URLs and XML namespaces with a fragment | +| 3.0.4 → 3.0.3 | the same, plus `application/octet-stream` for `format: byte` multipart parts; reports `spaceDelimited`/`pipeDelimited` objects | +| 3.1.2 → 3.1.1, 3.0.3 → 3.0.2, 3.0.2 → 3.0.1, 3.0.1 → 3.0.0 | the version only | + +Some patch releases changed how a value is serialized on the wire, correcting what the earlier text got wrong: percent-encoding of header values (3.1.2), `label` style with `explode: false` and the meaning of `allowEmptyValue` (3.0.4, 3.1.1). A description has no field in which to pin those, so they are not carried. + +## Loosening unions + +With `loosenUnions`, each `oneOf` and `anyOf` becomes one schema that accepts everything any member accepts: + +1. A `null` member makes the result nullable. One member left is the result; a reference stays a reference. +2. Members that each allow only listed values, by `enum` or `const`, become one `enum`, as openapi-generator's `SIMPLIFY_ONEOF_ANYOF_ENUM` rule reads them: a single value's `title` and `description` go to `x-enum-descriptions` and its `deprecated` to `x-enum-deprecated`. +3. Other members of one type merge, each with what it reaches through `allOf` folded in and its own declaration of a property winning over its parts'. An object carries every member's properties and requires only what every member requires; an array loosens its `items`; a keyword survives when every member gives it the same value, and `enum` becomes the union of the members' values. +4. Members of different types leave `{}`. + +The union's own `title` and `description` carry over, so a code generator names the merged object after the union. + +## Nullable references + +3.1 writes a nullable reference as `anyOf: [{$ref: X}, {type: "null"}]`. 3.0 has only `nullable`, which widens a `type` written beside it, and a reference has none. The plugin writes `$ref: X` with `nullable: true` beside it. + +The 3.0 text says keywords beside a `$ref` are ignored, so by the letter this pair accepts no `null`. openapi-generator reads it as a nullable reference, and writes the same pair itself when it simplifies that `anyOf` ([`ModelUtils.java`](https://github.com/OpenAPITools/openapi-generator/blob/v7.25.0/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java#L2597-L2625), on by default). It is the form 3.0 descriptions have used for nullable references in practice. + +## Limits + +- Redocly resolves a `$ref` inside `example` as a reference in every version, so a literal example object holding `$ref` never reaches the plugin. +- Redocly 2.53.3 and 2.54.2 cannot read a 3.2 description whose `deviceAuthorization` flow has scopes: `@redocly/openapi-core` types `DeviceAuthorization.scopes` as `mapOf('string')`, which throws `Unknown type name found: string`. +- The output is only as valid as the input. Linting the result at the version it declares (`redocly lint --extends minimal`) is the check that nothing slipped through. + +## Tests + +`pnpm test` runs the unit tests beside each layer and the fixture tests, which downlevel every sample description in `fixtures/` to every earlier release, with and without `loosenUnions`, snapshot each result, and fail if any output has a lint error its source did not. + +The fixtures are the OpenAPI Initiative's own examples, vendored with attribution; see `fixtures/*/NOTICE`. `scripts/vendor-fixtures.sh` refreshes them from pinned commits. + +## License + +MIT. The fixtures keep their own licenses: Apache 2.0 for `fixtures/oai`, CC BY 4.0 for `fixtures/learn`. diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/3.1/non-oauth-scopes.yaml b/packages/redocly-plugin-downlevel/fixtures/learn/3.1/non-oauth-scopes.yaml new file mode 100644 index 00000000..ac9fc8de --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/3.1/non-oauth-scopes.yaml @@ -0,0 +1,18 @@ +openapi: 3.1.0 +info: + title: Non-oAuth Scopes example + version: 1.0.0 +paths: + /users: + get: + security: + - bearerAuth: + - read:users + - public +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: jwt + description: 'note: non-oauth scopes are not defined at the securityScheme level' diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/3.1/tictactoe.yaml b/packages/redocly-plugin-downlevel/fixtures/learn/3.1/tictactoe.yaml new file mode 100644 index 00000000..ebf13b7e --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/3.1/tictactoe.yaml @@ -0,0 +1,236 @@ +openapi: 3.1.0 +info: + title: Tic Tac Toe + description: | + This API allows writing down marks on a Tic Tac Toe board + and requesting the state of the board or of individual squares. + version: 1.0.0 +tags: + - name: Gameplay +paths: + # Whole board operations + /board: + get: + summary: Get the whole board + description: Retrieves the current state of the board and the winner. + tags: + - Gameplay + operationId: get-board + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/status' + security: + - defaultApiKey: [] + - app2AppOauth: + - board:read + + # Single square operations + /board/{row}/{column}: + parameters: + - $ref: '#/components/parameters/rowParam' + - $ref: '#/components/parameters/columnParam' + get: + summary: Get a single board square + description: Retrieves the requested square. + tags: + - Gameplay + operationId: get-square + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/mark' + links: + markSquare: + description: Operation to use if the mark value returned indicates the square is empty + operationId: put-square + parameters: + row: $request.path.row + column: $request.path.column + "400": + description: The provided parameters are incorrect + content: + text/html: + schema: + $ref: '#/components/schemas/errorMessage' + example: Illegal coordinates + security: + - bearerHttpAuthentication: [] + - user2AppOauth: + - board:read + put: + summary: Set a single board square + description: Places a mark on the board and retrieves the whole board and the winner (if any). + tags: + - Gameplay + operationId: put-square + parameters: + - name: progressUrl + in: header + description: Progress URL that should be called if asynchronous response is returned + required: false + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/mark' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/status" + "202": + description: Mark operation has not completed. Use callback to check for progress + headers: + Location: + description: Callback URL + schema: + type: string + "400": + description: The provided parameters are incorrect + content: + text/html: + schema: + $ref: '#/components/schemas/errorMessage' + examples: + illegalCoordinates: + value: Illegal coordinates. + notEmpty: + value: Square is not empty. + invalidMark: + value: Invalid Mark (X or O). + security: + - bearerHttpAuthentication: [] + - user2AppOauth: + - board:write + callbacks: + statusCallback: + '{$request.header.progressUrl}': + post: + summary: Status of mark operation + description: Provides the status of the mark operation + operationId: markOperationCallback + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/status" + responses: + "200": + description: Mark operation status received +components: + parameters: + rowParam: + description: Board row (vertical coordinate) + name: row + in: path + required: true + schema: + $ref: '#/components/schemas/coordinate' + columnParam: + description: Board column (horizontal coordinate) + name: column + in: path + required: true + schema: + $ref: '#/components/schemas/coordinate' + schemas: + errorMessage: + type: string + maxLength: 256 + description: A text message describing an error + coordinate: + type: integer + minimum: 1 + maximum: 3 + example: 1 + mark: + type: string + enum: + - . + - X + - O + description: Possible values for a board square. `.` means empty square. + example: . + board: + type: array + maxItems: 3 + minItems: 3 + items: + type: array + maxItems: 3 + minItems: 3 + items: + $ref: '#/components/schemas/mark' + winner: + type: string + enum: + - . + - X + - O + description: Winner of the game. `.` means nobody has won yet. + example: . + status: + type: object + properties: + winner: + $ref: '#/components/schemas/winner' + board: + $ref: '#/components/schemas/board' + securitySchemes: + defaultApiKey: + description: API key provided in console + type: apiKey + name: api-key + in: header + basicHttpAuthentication: + description: Basic HTTP Authentication + type: http + scheme: Basic + bearerHttpAuthentication: + description: Bearer token using a JWT + type: http + scheme: Bearer + bearerFormat: JWT + app2AppOauth: + type: oauth2 + flows: + clientCredentials: + tokenUrl: https://learn.openapis.org/oauth/2.0/token + scopes: + # Only reading the board allow with delegated access + board:read: Read the board + user2AppOauth: + type: oauth2 + flows: + authorizationCode: + authorizationUrl: https://learn.openapis.org/oauth/2.0/auth + tokenUrl: https://learn.openapis.org/oauth/2.0/token + scopes: + # Reads and writes permitted via authorization code flow + board:read: Read the board + board:write: Write to the board +webhooks: + markStatus: + post: + summary: Status of mark operation + description: Provides the status of the mark operation on completion + operationId: markOperationWebhook + responses: + "200": + description: Mark operation has completed successfully + content: + application/json: + schema: + $ref: "#/components/schemas/status" diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/3.1/webhook-example.yaml b/packages/redocly-plugin-downlevel/fixtures/learn/3.1/webhook-example.yaml new file mode 100644 index 00000000..4c08cf9e --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/3.1/webhook-example.yaml @@ -0,0 +1,34 @@ +openapi: 3.1.0 +info: + title: Webhook Example + version: 1.0.0 +# Since OAS 3.1.0 the paths element isn't necessary. Now a valid OpenAPI Document can describe only paths, webhooks, or even only reusable components +webhooks: + # Each webhook needs a name + newPet: + # This is a Path Item Object, the only difference is that the request is initiated by the API provider + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + responses: + '200': + description: Return a 200 status to indicate that the data was received successfully +components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/3.2/3.2-query-example.yaml b/packages/redocly-plugin-downlevel/fixtures/learn/3.2/3.2-query-example.yaml new file mode 100644 index 00000000..50c93ff4 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/3.2/3.2-query-example.yaml @@ -0,0 +1,88 @@ +openapi: 3.2.0 +info: + title: Flight API + version: 1.0.0 + + # The QUERY method is intended for safe, idempotent requests that still need a + # request body, which makes it a good fit for flight search filters like dates, + # cabin class, passenger count, and nonstop preferences. In practice, this is + # clearer than forcing a long GET URL or misusing POST for a read-only search operation. + +paths: + /flights/search: + query: + summary: Search flights with complex criteria + description: > + Uses the HTTP QUERY method to perform a safe, idempotent flight search + with filters that are too complex for a URL query string. + operationId: searchFlights + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + origin: + type: string + example: ATL + destination: + type: string + example: LHR + departureDate: + type: string + format: date + example: 2026-06-15 + returnDate: + type: string + format: date + example: 2026-06-25 + passengers: + type: integer + minimum: 1 + example: 2 + cabinClass: + type: string + enum: [economy, premium-economy, business, first] + example: business + nonStopOnly: + type: boolean + example: true + required: + - origin + - destination + - departureDate + responses: + '200': + description: Matching flights + content: + application/json: + schema: + type: object + properties: + flights: + type: array + items: + type: object + properties: + flightNumber: + type: string + example: DL30 + origin: + type: string + example: ATL + destination: + type: string + example: LHR + departureTime: + type: string + format: date-time + example: 2026-06-15T22:30:00Z + arrivalTime: + type: string + format: date-time + example: 2026-06-16T10:15:00Z + price: + type: number + format: float + example: 1249.99 diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/3.2/3.2-tags-example.yaml b/packages/redocly-plugin-downlevel/fixtures/learn/3.2/3.2-tags-example.yaml new file mode 100644 index 00000000..6ec7bc92 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/3.2/3.2-tags-example.yaml @@ -0,0 +1,57 @@ +openapi: 3.2.0 +info: + title: Flight API + version: 1.0.0 + +# This example shows that OpenAPI 3.2’s enhanced tag object can express hierarchical +# navigation, UI intent, and documentation links directly in the spec: top‑level **flights** tag +# groups related **international** and **domestic** child tags via `parent`, `kind` distinguishes how tags +# should be treated in tooling (e.g., `nav` for navigation, `badge` to visually highlight **delays**), +# and `externalDocs` attaches rich, out‑of‑band documentation to a specific tag so clients and documentation +# portals can surface deep links for particular functional areas. + +tags: + - name: flights + summary: Flights + description: Core flight operations + kind: nav + - name: international + summary: International + description: Flights that cross country borders + parent: flights + kind: nav + - name: domestic + summary: Domestic + description: Flights within a single country + parent: flights + kind: nav + - name: delays + summary: Delays + description: Information about flight delays + kind: badge + externalDocs: + description: Delay compensation policies + url: https://docs.example.com/delay-policies + +paths: + /flights: + get: + tags: + - flights + summary: List all flights + /flights/international: + get: + tags: + - international + summary: List international flights + /flights/domestic: + get: + tags: + - domestic + summary: List domestic flights + /flights/delayed: + get: + tags: + - delays + summary: Get delayed flights + diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/LICENSE b/packages/redocly-plugin-downlevel/fixtures/learn/LICENSE new file mode 100644 index 00000000..dc8853a7 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/LICENSE @@ -0,0 +1,393 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public licenses. +Notwithstanding, Creative Commons may elect to apply one of its public +licenses to material it publishes and in those instances will be +considered the "Licensor." Except for the limited purpose of indicating +that material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the public +licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/packages/redocly-plugin-downlevel/fixtures/learn/NOTICE b/packages/redocly-plugin-downlevel/fixtures/learn/NOTICE new file mode 100644 index 00000000..82fff233 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/learn/NOTICE @@ -0,0 +1,11 @@ +The files in this directory are copied, unmodified, from the examples of "OpenAPI Documentation" by the OpenAPI Initiative: + + https://learn.openapis.org/examples/ + https://github.com/OAI/learn.openapis.org + +Licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0); see LICENSE in this directory, or https://creativecommons.org/licenses/by/4.0/. + + 3.1/ examples/v3.1 at bbb743ed3b7c5ed76b6e6ba9b302af38f3956c44 + 3.2/ examples/v3.2 at bbb743ed3b7c5ed76b6e6ba9b302af38f3956c44 + +scripts/vendor-fixtures.sh reproduces them. diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.0/api-with-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/api-with-examples.yaml new file mode 100644 index 00000000..18726a54 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/api-with-examples.yaml @@ -0,0 +1,170 @@ +openapi: "3.0.0" +info: + title: Simple API overview + version: 2.0.0 +paths: + /: + get: + operationId: listVersionsv2 + summary: List API versions + responses: + '200': + description: |- + 200 response + content: + application/json: + examples: + foo: + value: + { + "versions": [ + { + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "id": "v2.0", + "links": [ + { + "href": "http://127.0.0.1:8774/v2/", + "rel": "self" + } + ] + }, + { + "status": "EXPERIMENTAL", + "updated": "2013-07-23T11:33:21Z", + "id": "v3.0", + "links": [ + { + "href": "http://127.0.0.1:8774/v3/", + "rel": "self" + } + ] + } + ] + } + '300': + description: |- + 300 response + content: + application/json: + examples: + foo: + value: | + { + "versions": [ + { + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "id": "v2.0", + "links": [ + { + "href": "http://127.0.0.1:8774/v2/", + "rel": "self" + } + ] + }, + { + "status": "EXPERIMENTAL", + "updated": "2013-07-23T11:33:21Z", + "id": "v3.0", + "links": [ + { + "href": "http://127.0.0.1:8774/v3/", + "rel": "self" + } + ] + } + ] + } + /v2: + get: + operationId: getVersionDetailsv2 + summary: Show API version details + responses: + '200': + description: |- + 200 response + content: + application/json: + examples: + foo: + value: + { + "version": { + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute+xml;version=2" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute+json;version=2" + } + ], + "id": "v2.0", + "links": [ + { + "href": "http://127.0.0.1:8774/v2/", + "rel": "self" + }, + { + "href": "http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf", + "type": "application/pdf", + "rel": "describedby" + }, + { + "href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl", + "type": "application/vnd.sun.wadl+xml", + "rel": "describedby" + }, + { + "href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl", + "type": "application/vnd.sun.wadl+xml", + "rel": "describedby" + } + ] + } + } + '203': + description: |- + 203 response + content: + application/json: + examples: + foo: + value: + { + "version": { + "status": "CURRENT", + "updated": "2011-01-21T11:33:21Z", + "media-types": [ + { + "base": "application/xml", + "type": "application/vnd.openstack.compute+xml;version=2" + }, + { + "base": "application/json", + "type": "application/vnd.openstack.compute+json;version=2" + } + ], + "id": "v2.0", + "links": [ + { + "href": "http://23.253.228.211:8774/v2/", + "rel": "self" + }, + { + "href": "http://docs.openstack.org/api/openstack-compute/2/os-compute-devguide-2.pdf", + "type": "application/pdf", + "rel": "describedby" + }, + { + "href": "http://docs.openstack.org/api/openstack-compute/2/wadl/os-compute-2.wadl", + "type": "application/vnd.sun.wadl+xml", + "rel": "describedby" + } + ] + } + } diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.0/callback-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/callback-example.yaml new file mode 100644 index 00000000..262b8df5 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/callback-example.yaml @@ -0,0 +1,61 @@ +openapi: 3.0.0 +info: + title: Callback Example + version: 1.0.0 +paths: + /streams: + post: + description: subscribes a client to receive out-of-band data + parameters: + - name: callbackUrl + in: query + required: true + description: | + the location where data will be sent. Must be network accessible + by the source server + schema: + type: string + format: uri + example: https://tonys-server.com + responses: + '201': + description: subscription successfully created + content: + application/json: + schema: + description: subscription information + required: + - subscriptionId + properties: + subscriptionId: + description: this unique identifier allows management of the subscription + type: string + example: 2531329f-fb09-4ef7-887e-84e648214436 + callbacks: + # the name `onData` is a convenience locator + onData: + # when data is sent, it will be sent to the `callbackUrl` provided + # when making the subscription PLUS the suffix `/data` + '{$request.query.callbackUrl}/data': + post: + requestBody: + description: subscription payload + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + format: date-time + userData: + type: string + responses: + '202': + description: | + Your server implementation should return this HTTP status code + if the data was received successfully + '204': + description: | + Your server should return this HTTP status code if no longer interested + in further updates diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.0/link-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/link-example.yaml new file mode 100644 index 00000000..5837d705 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/link-example.yaml @@ -0,0 +1,203 @@ +openapi: 3.0.0 +info: + title: Link Example + version: 1.0.0 +paths: + /2.0/users/{username}: + get: + operationId: getUserByName + parameters: + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: The User + content: + application/json: + schema: + $ref: '#/components/schemas/user' + links: + userRepositories: + $ref: '#/components/links/UserRepositories' + /2.0/repositories/{username}: + get: + operationId: getRepositoriesByOwner + parameters: + - name: username + in: path + required: true + schema: + type: string + responses: + '200': + description: repositories owned by the supplied user + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/repository' + links: + userRepository: + $ref: '#/components/links/UserRepository' + /2.0/repositories/{username}/{slug}: + get: + operationId: getRepository + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + responses: + '200': + description: The repository + content: + application/json: + schema: + $ref: '#/components/schemas/repository' + links: + repositoryPullRequests: + $ref: '#/components/links/RepositoryPullRequests' + /2.0/repositories/{username}/{slug}/pullrequests: + get: + operationId: getPullRequestsByRepository + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: state + in: query + schema: + type: string + enum: + - open + - merged + - declined + responses: + '200': + description: an array of pull request objects + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/pullrequest' + /2.0/repositories/{username}/{slug}/pullrequests/{pid}: + get: + operationId: getPullRequestsById + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: pid + in: path + required: true + schema: + type: string + responses: + '200': + description: a pull request object + content: + application/json: + schema: + $ref: '#/components/schemas/pullrequest' + links: + pullRequestMerge: + $ref: '#/components/links/PullRequestMerge' + /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge: + post: + operationId: mergePullRequest + parameters: + - name: username + in: path + required: true + schema: + type: string + - name: slug + in: path + required: true + schema: + type: string + - name: pid + in: path + required: true + schema: + type: string + responses: + '204': + description: the PR was successfully merged +components: + links: + UserRepositories: + # returns array of '#/components/schemas/repository' + operationId: getRepositoriesByOwner + parameters: + username: $response.body#/username + UserRepository: + # returns '#/components/schemas/repository' + operationId: getRepository + parameters: + username: $response.body#/owner/username + slug: $response.body#/slug + RepositoryPullRequests: + # returns '#/components/schemas/pullrequest' + operationId: getPullRequestsByRepository + parameters: + username: $response.body#/owner/username + slug: $response.body#/slug + PullRequestMerge: + # executes /2.0/repositories/{username}/{slug}/pullrequests/{pid}/merge + operationId: mergePullRequest + parameters: + username: $response.body#/author/username + slug: $response.body#/repository/slug + pid: $response.body#/id + schemas: + user: + type: object + properties: + username: + type: string + uuid: + type: string + repository: + type: object + properties: + slug: + type: string + owner: + $ref: '#/components/schemas/user' + pullrequest: + type: object + properties: + id: + type: integer + title: + type: string + repository: + $ref: '#/components/schemas/repository' + author: + $ref: '#/components/schemas/user' diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.0/petstore-expanded.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/petstore-expanded.yaml new file mode 100644 index 00000000..7e5bff0e --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/petstore-expanded.yaml @@ -0,0 +1,158 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification + termsOfService: http://swagger.io/terms/ + contact: + name: Swagger API Team + email: apiteam@swagger.io + url: http://swagger.io + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html +servers: + - url: https://petstore.swagger.io/v2 +paths: + /pets: + get: + description: | + Returns all pets from the system that the user has access to + Nam sed condimentum est. Maecenas tempor sagittis sapien, nec rhoncus sem sagittis sit amet. Aenean at gravida augue, ac iaculis sem. Curabitur odio lorem, ornare eget elementum nec, cursus id lectus. Duis mi turpis, pulvinar ac eros ac, tincidunt varius justo. In hac habitasse platea dictumst. Integer at adipiscing ante, a sagittis ligula. Aenean pharetra tempor ante molestie imperdiet. Vivamus id aliquam diam. Cras quis velit non tortor eleifend sagittis. Praesent at enim pharetra urna volutpat venenatis eget eget mauris. In eleifend fermentum facilisis. Praesent enim enim, gravida ac sodales sed, placerat id erat. Suspendisse lacus dolor, consectetur non augue vel, vehicula interdum libero. Morbi euismod sagittis libero sed lacinia. + + Sed tempus felis lobortis leo pulvinar rutrum. Nam mattis velit nisl, eu condimentum ligula luctus nec. Phasellus semper velit eget aliquet faucibus. In a mattis elit. Phasellus vel urna viverra, condimentum lorem id, rhoncus nibh. Ut pellentesque posuere elementum. Sed a varius odio. Morbi rhoncus ligula libero, vel eleifend nunc tristique vitae. Fusce et sem dui. Aenean nec scelerisque tortor. Fusce malesuada accumsan magna vel tempus. Quisque mollis felis eu dolor tristique, sit amet auctor felis gravida. Sed libero lorem, molestie sed nisl in, accumsan tempor nisi. Fusce sollicitudin massa ut lacinia mattis. Sed vel eleifend lorem. Pellentesque vitae felis pretium, pulvinar elit eu, euismod sapien. + operationId: findPets + parameters: + - name: tags + in: query + description: tags to filter by + required: false + style: form + schema: + type: array + items: + type: string + - name: limit + in: query + description: maximum number of results to return + required: false + schema: + type: integer + format: int32 + responses: + '200': + description: pet response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + post: + description: Creates a new pet in the store. Duplicates are allowed + operationId: addPet + requestBody: + description: Pet to add to the store + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/NewPet' + responses: + '200': + description: pet response + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + /pets/{id}: + get: + description: Returns a user based on a single ID, if the user does not have access to the pet + operationId: find pet by id + parameters: + - name: id + in: path + description: ID of pet to fetch + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: pet response + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' + delete: + description: deletes a single pet based on the ID supplied + operationId: deletePet + parameters: + - name: id + in: path + description: ID of pet to delete + required: true + schema: + type: integer + format: int64 + responses: + '204': + description: pet deleted + default: + description: unexpected error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' +components: + schemas: + Pet: + allOf: + - $ref: '#/components/schemas/NewPet' + - type: object + required: + - id + properties: + id: + type: integer + format: int64 + + NewPet: + type: object + required: + - name + properties: + name: + type: string + tag: + type: string + + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.0/petstore.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/petstore.yaml new file mode 100644 index 00000000..7ed987ff --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/petstore.yaml @@ -0,0 +1,119 @@ +openapi: "3.0.0" +info: + version: 1.0.0 + title: Swagger Petstore + license: + name: MIT +servers: + - url: http://petstore.swagger.io/v1 +paths: + /pets: + get: + summary: List all pets + operationId: listPets + tags: + - pets + parameters: + - name: limit + in: query + description: How many items to return at one time (max 100) + required: false + schema: + type: integer + maximum: 100 + format: int32 + responses: + '200': + description: A paged array of pets + headers: + x-next: + description: A link to the next page of responses + schema: + type: string + content: + application/json: + schema: + $ref: "#/components/schemas/Pets" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + post: + summary: Create a pet + operationId: createPets + tags: + - pets + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + required: true + responses: + '201': + description: Null response + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" + /pets/{petId}: + get: + summary: Info for a specific pet + operationId: showPetById + tags: + - pets + parameters: + - name: petId + in: path + required: true + description: The id of the pet to retrieve + schema: + type: string + responses: + '200': + description: Expected response to a valid request + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + default: + description: unexpected error + content: + application/json: + schema: + $ref: "#/components/schemas/Error" +components: + schemas: + Pet: + type: object + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + Pets: + type: array + maxItems: 100 + items: + $ref: "#/components/schemas/Pet" + Error: + type: object + required: + - code + - message + properties: + code: + type: integer + format: int32 + message: + type: string diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.0/uspto.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/uspto.yaml new file mode 100644 index 00000000..d3011520 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.0/uspto.yaml @@ -0,0 +1,210 @@ +openapi: 3.0.1 +servers: + - url: '{scheme}://developer.uspto.gov/ds-api' + variables: + scheme: + description: 'The Data Set API is accessible via https and http' + enum: + - 'https' + - 'http' + default: 'https' +info: + description: >- + The Data Set API (DSAPI) allows the public users to discover and search + USPTO exported data sets. This is a generic API that allows USPTO users to + make any CSV based data files searchable through API. With the help of GET + call, it returns the list of data fields that are searchable. With the help + of POST call, data can be fetched based on the filters on the field names. + Please note that POST call is used to search the actual data. The reason for + the POST call is that it allows users to specify any complex search criteria + without worry about the GET size limitations as well as encoding of the + input parameters. + version: 1.0.0 + title: USPTO Data Set API + contact: + name: Open Data Portal + url: 'https://developer.uspto.gov' + email: developer@uspto.gov +tags: + - name: metadata + description: Find out about the data sets + - name: search + description: Search a data set +paths: + /: + get: + tags: + - metadata + operationId: list-data-sets + summary: List available data sets + responses: + '200': + description: Returns a list of data sets + content: + application/json: + schema: + $ref: '#/components/schemas/dataSetList' + example: + { + "total": 2, + "apis": [ + { + "apiKey": "oa_citations", + "apiVersionNumber": "v1", + "apiUrl": "https://developer.uspto.gov/ds-api/oa_citations/v1/fields", + "apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/oa_citations.json" + }, + { + "apiKey": "cancer_moonshot", + "apiVersionNumber": "v1", + "apiUrl": "https://developer.uspto.gov/ds-api/cancer_moonshot/v1/fields", + "apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/cancer_moonshot.json" + } + ] + } + /{dataset}/{version}/fields: + get: + tags: + - metadata + summary: >- + Provides the general information about the API and the list of fields + that can be used to query the dataset. + description: >- + This GET API returns the list of all the searchable field names that are + in the oa_citations. Please see the 'fields' attribute which returns an + array of field names. Each field or a combination of fields can be + searched using the syntax options shown below. + operationId: list-searchable-fields + parameters: + - name: dataset + in: path + description: 'Name of the dataset.' + required: true + example: "oa_citations" + schema: + type: string + - name: version + in: path + description: Version of the dataset. + required: true + example: "v1" + schema: + type: string + responses: + '200': + description: >- + The dataset API for the given version is found and it is accessible + to consume. + content: + application/json: + schema: + type: string + '404': + description: >- + The combination of dataset name and version is not found in the + system or it is not published yet to be consumed by public. + content: + application/json: + schema: + type: string + /{dataset}/{version}/records: + post: + tags: + - search + summary: >- + Provides search capability for the data set with the given search + criteria. + description: >- + This API is based on Solr/Lucene Search. The data is indexed using + SOLR. This GET API returns the list of all the searchable field names + that are in the Solr Index. Please see the 'fields' attribute which + returns an array of field names. Each field or a combination of fields + can be searched using the Solr/Lucene Syntax. Please refer + https://lucene.apache.org/core/3_6_2/queryparsersyntax.html#Overview for + the query syntax. List of field names that are searchable can be + determined using above GET api. + operationId: perform-search + parameters: + - name: version + in: path + description: Version of the dataset. + required: true + schema: + type: string + default: v1 + - name: dataset + in: path + description: 'Name of the dataset. In this case, the default value is oa_citations' + required: true + schema: + type: string + default: oa_citations + responses: + '200': + description: successful operation + content: + application/json: + schema: + type: array + items: + type: object + additionalProperties: + type: object + '404': + description: No matching record found for the given criteria. + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + criteria: + description: >- + Uses Lucene Query Syntax in the format of + propertyName:value, propertyName:[num1 TO num2] and date + range format: propertyName:[yyyyMMdd TO yyyyMMdd]. In the + response please see the 'docs' element which has the list of + record objects. Each record structure would consist of all + the fields and their corresponding values. + type: string + default: '*:*' + start: + description: Starting record number. Default value is 0. + type: integer + default: 0 + rows: + description: >- + Specify number of rows to be returned. If you run the search + with default values, in the response you will see 'numFound' + attribute which will tell the number of records available in + the dataset. + type: integer + default: 100 + required: + - criteria +components: + schemas: + dataSetList: + type: object + properties: + total: + type: integer + apis: + type: array + items: + type: object + properties: + apiKey: + type: string + description: To be used as a dataset parameter value + apiVersionNumber: + type: string + description: To be used as a version parameter value + apiUrl: + type: string + format: uriref + description: "The URL describing the dataset's fields" + apiDocumentationUrl: + type: string + format: uriref + description: A URL to the API console for each API diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/callback-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/callback-object-examples.yaml new file mode 100644 index 00000000..795627eb --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/callback-object-examples.yaml @@ -0,0 +1,32 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + callbacks: + myCallback: + '{$request.query.queryUrl}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + transactionCallback: + 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + schemas: + SomePayload: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/comp_pathitems.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/comp_pathitems.yaml new file mode 100644 index 00000000..502ca1fc --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/comp_pathitems.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + pathItems: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/components-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/components-object-example.yaml new file mode 100644 index 00000000..9ef0c176 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/components-object-example.yaml @@ -0,0 +1,71 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + schemas: + GeneralError: + type: object + properties: + code: + type: integer + format: int32 + message: + type: string + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + parameters: + skipParam: + name: skip + in: query + description: number of items to skip + required: true + schema: + type: integer + format: int32 + limitParam: + name: limit + in: query + description: max records to return + required: true + schema: + type: integer + format: int32 + responses: + NotFound: + description: Entity not found. + IllegalInput: + description: Illegal input for operation. + GeneralError: + description: General Error + content: + application/json: + schema: + $ref: '#/components/schemas/GeneralError' + securitySchemes: + api_key: + type: apiKey + name: api-key + in: header + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: https://example.org/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/example-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/example-object-examples.yaml new file mode 100644 index 00000000..16022e2b --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/example-object-examples.yaml @@ -0,0 +1,69 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + examples: + zip-example: {} + confirmation-success: {} + schemas: + SuccessResponse: {} + Address: {} + requestBodies: + with-example: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Address' + examples: + foo: + summary: A foo example + value: + foo: bar + bar: + summary: A bar example + value: + bar: baz + application/xml: + examples: + xmlExample: + summary: This is an example in XML + externalValue: https://example.org/examples/address-example.xml + text/plain: + examples: + textExample: + summary: This is a text example + externalValue: https://foo.bar/examples/address-example.txt + parameters: + with-example: + name: zipCode + in: query + schema: + type: string + format: zip-code + examples: + zip-example: + $ref: '#/components/examples/zip-example' + responses: + '200': + description: your car appointment has been booked + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + examples: + confirmation-success: + $ref: '#/components/examples/confirmation-success' + application/x-www-form-urlencoded: + schema: + type: object + properties: + jsonValue: + type: string + encoding: + jsonValue: + contentType: application/json + examples: + jsonFormValue: + description: 'The JSON string "json" as a form value' + value: jsonValue=%22json%22 diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/header-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/header-object-examples.yaml new file mode 100644 index 00000000..389eefc4 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/header-object-examples.yaml @@ -0,0 +1,25 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + deprecated: false + schema: + type: integer + ETag: + required: true + content: + text/plain: + schema: + type: string + pattern: ^" + Reference: + $ref: '#/components/headers/ETag' + Style: + schema: + type: array + style: simple + explode: true diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/info-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/info-object-example.yaml new file mode 100644 index 00000000..2c32cd9c --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/info-object-example.yaml @@ -0,0 +1,19 @@ +# including External Documentation Object Example +openapi: 3.1.0 +info: + title: Example Pet Store App + summary: A pet store manager. + description: This is an example server for a pet store. + termsOfService: https://example.com/terms/ + contact: + name: API Support + url: https://www.example.com/support + email: support@example.com + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.1 +externalDocs: + description: Find more info here + url: https://example.com +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/info_summary.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/info_summary.yaml new file mode 100644 index 00000000..30d224af --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/info_summary.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + summary: My lovely API + version: 1.0.0 +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/json_schema_dialect.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/json_schema_dialect.yaml new file mode 100644 index 00000000..ae0ed863 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/json_schema_dialect.yaml @@ -0,0 +1,15 @@ +openapi: 3.1.0 +info: + summary: Testing jsonSchemaDialect + title: My API + version: 1.0.0 + license: + name: Apache 2.0 + identifier: Apache-2.0 +jsonSchemaDialect: https://spec.openapis.org/oas/3.1/dialect/WORK-IN-PROGRESS +components: + schemas: + WithDollarSchema: + $id: "locked-metaschema" + $schema: https://spec.openapis.org/oas/3.1/dialect/WORK-IN-PROGRESS +paths: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/license_identifier.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/license_identifier.yaml new file mode 100644 index 00000000..fbdba5ef --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/license_identifier.yaml @@ -0,0 +1,9 @@ +openapi: 3.1.0 +info: + title: API + summary: My lovely API + version: 1.0.0 + license: + name: Apache + identifier: Apache-2.0 +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/link-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/link-object-examples.yaml new file mode 100644 index 00000000..b7d8e737 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/link-object-examples.yaml @@ -0,0 +1,66 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /users/{id}: + parameters: + - name: id + in: path + required: true + description: the user identifier, as userId + schema: + type: string + get: + responses: + '200': + description: the user being returned + content: + application/json: + schema: + type: object + properties: + uuid: # the unique user id + type: string + format: uuid + links: + address: + # the target link operationId + operationId: getUserAddress + parameters: + # get the `id` field from the request path parameter named `id` + userid: $request.path.id + address2: + operationId: getUserAddressByUUID + parameters: + # get the `uuid` field from the `uuid` field in the response body + userUuid: $response.body#/uuid + UserRepositories: + # returns array of '#/components/schemas/repository' + operationRef: '#/paths/~12.0~1repositories~1%7Busername%7D/get' + parameters: + username: $response.body#/username + UserRepositories2: + # returns array of '#/components/schemas/repository' + operationRef: https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1%7Busername%7D/get + parameters: + username: $response.body#/username + withBody: + operationId: queryUserWithBody + requestBody: + userId: $request.path.id + # the path item of the linked operation + /users/{userid}/address: + parameters: + - name: userid + in: path + required: true + description: the user identifier, as userId + schema: + type: string + # linked operation + get: + operationId: getUserAddress + responses: + '200': + description: the user's address \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/media-type-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/media-type-examples.yaml new file mode 100644 index 00000000..924555af --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/media-type-examples.yaml @@ -0,0 +1,123 @@ +# including Encoding Object examples +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + examples: + frog-example: {} + schemas: + Address: {} + Pet: {} +paths: + /something: + put: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + examples: + cat: + summary: An example of a cat + value: + name: Fluffy + petType: Cat + color: White + gender: male + breed: Persian + dog: + summary: An example of a dog with a cat's name + value: + name: Puma + petType: Dog + color: Black + gender: Female + breed: Mixed + frog: + $ref: '#/components/examples/frog-example' + application/xml: + schema: + type: object + properties: + foo: + type: string + xml: + namespace: https://example.com + prefix: example + name: Foo + bar: + type: array + items: + type: number + xml: + wrapped: true + attr: + type: string + xml: + attribute: true + application/x-www-form-urlencoded: + schema: + type: object + properties: + id: + type: string + format: uuid + address: + # complex types are stringified to support RFC 1866 + type: object + properties: {} + icon: + # The default with "contentEncoding" is application/octet-stream, + # so we need to set image media type(s) in the Encoding Object. + type: string + contentEncoding: base64url + encoding: + icon: + contentType: image/png, image/jpeg + multipart/form-data: + schema: + type: object + properties: + id: + # default is `text/plain` + type: string + format: uuid + addresses: + # default based on the `items` subschema would be + # `application/json`, but we want these address objects + # serialized as `application/xml` instead + description: addresses in XML format + type: array + items: + $ref: '#/components/schemas/Address' + profileImage: + # default is application/octet-stream, but we can declare + # a more specific image type or types + type: string + format: binary + forCoverage: + type: string + forCoverage2: + type: string + encoding: + addresses: + # require XML Content-Type in utf-8 encoding + # This is applied to each address part corresponding + # to each address in he array + contentType: application/xml; charset=utf-8 + profileImage: + # only accept png or jpeg + contentType: image/png, image/jpeg + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + schema: + type: integer + forCoverage: + style: form + explode: false + allowReserved: true + forCoverage2: + style: spaceDelimited + explode: true diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/mega.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/mega.yaml new file mode 100644 index 00000000..dafae399 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/mega.yaml @@ -0,0 +1,61 @@ +openapi: 3.1.0 +info: + summary: My API's summary + title: My API + version: 1.0.0 + license: + name: Apache 2.0 + identifier: Apache-2.0 +paths: + /: + get: + parameters: [] + /{pathTest}: {} +webhooks: + myWebhook: + $ref: '#/components/pathItems/myPathItem' + description: Overriding description +components: + securitySchemes: + mtls: + type: mutualTLS + schemas: + Foo: + type: object + properties: + type: + const: foo + pathItems: + myPathItem: + post: + requestBody: + required: true + content: + 'application/json': + schema: + externalDocs: + description: More docs! + url: https://example.com/elsewhere.html + type: object + properties: + type: + type: string + int: + type: integer + exclusiveMaximum: 100 + exclusiveMinimum: 0 + none: + type: 'null' + arr: + type: array + $comment: Array without items keyword + either: + type: ['string','null'] + discriminator: + propertyName: type + mapping: + foo: Foo + x-extension: true + anyOf: + - $ref: "#/components/schemas/Foo" + myArbitraryKeyword: true diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_comp.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_comp.yaml new file mode 100644 index 00000000..4553689a --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_comp.yaml @@ -0,0 +1,5 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_hooks.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_hooks.yaml new file mode 100644 index 00000000..e67b2889 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_hooks.yaml @@ -0,0 +1,5 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +webhooks: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_paths.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_paths.yaml new file mode 100644 index 00000000..016e8679 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/minimal_paths.yaml @@ -0,0 +1,5 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/non-oauth-scopes.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/non-oauth-scopes.yaml new file mode 100644 index 00000000..e757452f --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/non-oauth-scopes.yaml @@ -0,0 +1,19 @@ +openapi: 3.1.0 +info: + title: Non-oAuth Scopes example + version: 1.0.0 +paths: + /users: + get: + security: + - bearerAuth: + - 'read:users' + - 'public' +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: jwt + description: 'note: non-oauth scopes are not defined at the securityScheme level' + diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/operation-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/operation-object-example.yaml new file mode 100644 index 00000000..9a5c76d0 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/operation-object-example.yaml @@ -0,0 +1,47 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /pets/{id}: + put: + tags: + - pet + summary: Updates a pet in the store with form data + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: string + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + required: + - status + responses: + '200': + description: Pet updated. + content: + application/json: {} + application/xml: {} + '405': + description: Method Not Allowed + content: + application/json: {} + application/xml: {} + security: + - petstore_auth: + - write:pets + - read:pets \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/parameter-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/parameter-object-examples.yaml new file mode 100644 index 00000000..30c7b290 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/parameter-object-examples.yaml @@ -0,0 +1,61 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /user/{username}: + parameters: + - name: token + in: header + description: token to be passed as a header + required: true + explode: false + schema: + type: array + items: + type: integer + format: int64 + style: simple + - name: usernames + in: path + description: usernames to fetch + required: true + explode: false + schema: + type: array + - name: id + in: query + description: IDs of the object to fetch + required: false + schema: + type: array + items: + type: string + style: form + explode: true + - in: query + name: freeForm + schema: + type: object + additionalProperties: + type: integer + style: form + - in: query + name: coordinates + content: + application/json: + schema: + type: object + required: + - lat + - long + properties: + lat: + type: number + long: + type: number + - in: cookie + name: my_cookie1 + style: form + explode: false + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/parameter-object-query-allowReserved.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/parameter-object-query-allowReserved.yaml new file mode 100644 index 00000000..26f89ab7 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/parameter-object-query-allowReserved.yaml @@ -0,0 +1,11 @@ +openapi: 3.1.0 +info: + title: "allowReserved only permitted with in: query" + version: 1.0.0 +components: + parameters: + my_query: + name: my_query + in: query + allowReserved: true + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path-item-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path-item-object-example.yaml new file mode 100644 index 00000000..777f4e5d --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path-item-object-example.yaml @@ -0,0 +1,39 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + schemas: + Pet: {} + ErrorModel: {} +paths: + /pets/{id}: + get: + description: Returns pets based on ID + summary: Find pets by ID + operationId: getPetsById + responses: + '200': + description: pet response + content: + '*/*': + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + default: + description: error payload + content: + text/html: + schema: + $ref: '#/components/schemas/ErrorModel' + parameters: + - name: id + in: path + description: ID of pet to use + required: true + schema: + type: array + items: + type: string + style: simple diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_item_servers_parameters.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_item_servers_parameters.yaml new file mode 100644 index 00000000..25b63395 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_item_servers_parameters.yaml @@ -0,0 +1,114 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /things: + summary: Lots of things + servers: + - url: https://things.example.com + get: + summary: Get a list of things + externalDocs: + description: Find more info here + url: https://example.com + parameters: + - $ref: '#/components/parameters/biscuit' + summary: The maximum number of things to return + description: The maximum number of things to return + responses: + default: + description: A list of things + servers: + - url: https://things.example.com + post: + deprecated: false + requestBody: + $ref: '#/components/requestBodies/ThingRequestBody' + responses: + '201': + $ref: '#/components/responses/ThingResponse' + callbacks: + myCallback: + '{$request.query.queryUrl}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + transactionCallback: + $ref: '#/components/callbacks/transactionCallback' + patch: {} + delete: {} + head: {} + options: {} + trace: {} +components: + callbacks: + transactionCallback: + 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + examples: + ThingExample: + summary: A thing + description: A thing + value: + id: 1 + name: Thing + links: + ThingLink: + description: A link to a thing + operationId: getThing + parameters: + thingId: '$response.body#/id' + server: + url: https://things.example.com + ThingyLink: + $ref: '#/components/links/ThingLink' + parameters: + limit: + name: limit + in: query + required: false + allowEmptyValue: false + allowReserved: false + deprecated: true + description: The maximum number of list items to return + schema: + type: integer + minimum: 0 + biscuit: + name: biscuit + in: cookie + style: form + schema: + type: string + requestBodies: + ThingRequestBody: + content: + application/json: + schema: + type: object + responses: + ThingResponse: + description: A thing + content: + application/json: + schema: + type: object + schemas: + SomePayload: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_no_response.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_no_response.yaml new file mode 100644 index 00000000..334608f1 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_no_response.yaml @@ -0,0 +1,7 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /: + get: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_var_empty_pathitem.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_var_empty_pathitem.yaml new file mode 100644 index 00000000..ba92742f --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/path_var_empty_pathitem.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /{var}: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/paths-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/paths-object-example.yaml new file mode 100644 index 00000000..82fb2e4f --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/paths-object-example.yaml @@ -0,0 +1,20 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + schemas: + pet: {} +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + responses: + '200': + description: A list of pets. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/pet' diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/request-body-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/request-body-examples.yaml new file mode 100644 index 00000000..4a11c440 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/request-body-examples.yaml @@ -0,0 +1,37 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + schemas: + User: {} +paths: + /something: + put: + requestBody: + description: user to add to the system + content: + application/json: + schema: + $ref: '#/components/schemas/User' + examples: + user: + summary: User example + externalValue: https://foo.bar/examples/user-example.json + application/xml: + schema: + $ref: '#/components/schemas/User' + examples: + user: + summary: User example in XML + externalValue: https://foo.bar/examples/user-example.xml + text/plain: + examples: + user: + summary: User example in plain text + externalValue: https://foo.bar/examples/user-example.txt + '*/*': + examples: + user: + summary: User example in other format + externalValue: https://foo.bar/examples/user-example.whatever diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/response-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/response-object-examples.yaml new file mode 100644 index 00000000..f2348d7c --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/response-object-examples.yaml @@ -0,0 +1,44 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +components: + responses: + complex-object-array: + description: A complex object array response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/VeryComplexType' + simple-string: + description: A simple string response + content: + text/plain: + schema: + type: string + plain-text-with-headers: + description: A simple string response + content: + text/plain: + schema: + type: string + example: 'whoa!' + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + schema: + type: integer + X-Rate-Limit-Remaining: + description: The number of remaining requests in the current period + schema: + type: integer + X-Rate-Limit-Reset: + description: The number of seconds left in the current period + schema: + type: integer + no-return-value: + description: object created + schemas: + VeryComplexType: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/schema-object-deprecated-example-keyword.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/schema-object-deprecated-example-keyword.yaml new file mode 100644 index 00000000..92fcbb41 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/schema-object-deprecated-example-keyword.yaml @@ -0,0 +1,17 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: + /user: + parameters: + - in: query + name: example + schema: + # Allow an arbitrary JSON object to keep + # the example simple + type: object + # DEPRECATED: don't use example keyword inside Schema Object + example: + numbers: [1, 2] + flag: null diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/schema.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/schema.yaml new file mode 100644 index 00000000..e192529a --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/schema.yaml @@ -0,0 +1,55 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} +components: + schemas: + model: + type: object + properties: + one: + description: type array + type: + - integer + - string + two: + description: type 'null' + type: "null" + three: + description: type array including 'null' + type: + - string + - "null" + four: + description: array with no items + type: array + five: + description: singular example + type: string + examples: + - exampleValue + six: + description: exclusiveMinimum true + exclusiveMinimum: 10 + seven: + description: exclusiveMinimum false + minimum: 10 + eight: + description: exclusiveMaximum true + exclusiveMaximum: 20 + nine: + description: exclusiveMaximum false + maximum: 20 + ten: + description: nullable string + type: + - string + - "null" + eleven: + description: x-nullable string + type: + - string + - "null" + twelve: + description: file/binary diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/security-scheme-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/security-scheme-object-examples.yaml new file mode 100644 index 00000000..0b0e9900 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/security-scheme-object-examples.yaml @@ -0,0 +1,59 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +security: + - basic: [] + - apiKey: [] + - JWT-bearer: [] + - mutualTLS: [] + - OAuth2: + - write:pets + - read:pets +components: + securitySchemes: + basic: + type: http + scheme: basic + apiKey: + type: apiKey + name: api-key + in: header + JWT-bearer: + type: http + scheme: bearer + bearerFormat: JWT + mutualTLS: + type: mutualTLS + description: Cert must be signed by example.com CA + OAuth2: + type: oauth2 + flows: + implicit: + authorizationUrl: https://example.com/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + authorizationCode: + authorizationUrl: https://example.com/api/oauth/dialog + refreshUrl: https://example.com/api/oauth/refresh + tokenUrl: https://example.com/api/oauth/token + scopes: + write:pets: modify pets in your account + read:pets: read your pets + password: + tokenUrl: https://example.com/api/oauth/token + scopes: + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + clientCredentials: + tokenUrl: https://example.com/api/oauth/token + scopes: + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + OpenIdConnect: + type: openIdConnect + openIdConnectUrl: https://example.com/api/oauth/openid + external: + $ref: 'https://example.com/api/openapi.json#/components/externalDocs/ThingExternalDocs' \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/servers.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/servers.yaml new file mode 100644 index 00000000..ca68a88b --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/servers.yaml @@ -0,0 +1,25 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} +servers: + - url: /v1 + description: Run locally. + - url: https://production.com/v1 + description: Run on production server. + - url: https://{username}.gigantic-server.com:{port}/{basePath} + description: The production API server + variables: + username: + # note! no enum here means it is an open value + default: demo + description: A user-specific subdomain. Use `demo` for a free sandbox environment. + port: + enum: + - '8443' + - '443' + default: '8443' + basePath: + # open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2` + default: v2 \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/specification-extensions.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/specification-extensions.yaml new file mode 100644 index 00000000..3d63a5f1 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/specification-extensions.yaml @@ -0,0 +1,6 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} +x-tensions: specification extensions are prefixed with `x-` diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/style-defaults.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/style-defaults.yaml new file mode 100644 index 00000000..c3942bdc --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/style-defaults.yaml @@ -0,0 +1,102 @@ +openapi: 3.1.0 +info: + title: various permutations of parameter objects, with non-required values left to their defaults + version: 1.0.0 +components: + parameters: + encoding_object_defaults: + name: encoding_object_defaults + in: path + content: + encoding_object_defaults: # media type name + encoding: + no_styles: # property name + x-comment: "style, explode and allowReserved are not present, so contentType is used; no defaults expected as default contentType cannot be determined by the schema" + style_form: + x-comment: "expecting defaults: explode=true, allowReserved=false" + style: form + style_spaceDelimited: + x-comment: "expecting defaults: explode=false, allowReserved=false" + style: spaceDelimited + explode: + x-comment: "expecting defaults: style=form, allowReserved=false" + explode: false + allowReserved: + x-comment: "expecting default: style=form, explode=true" + allowReserved: true + path_media_type: + x-comment: "expecting defaults: deprecated=false" + name: path_media-type + in: path + required: true + content: + text/*: + schema: {} + path_simple: + x-comment: "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false" + name: path_simple + in: path + required: true + schema: {} + path_matrix: + x-comment: "expecting defaults: deprecated=false, explode=false, allowReserved=false" + name: path_matrix + in: path + required: true + style: matrix + schema: {} + path_label: + x-comment: "expecting defaults: deprecated=false, explode=false, allowReserved=false" + name: path_label + in: path + required: true + style: label + schema: {} + query_media_type: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false" + name: query_media_type + in: query + content: + text/*: + schema: {} + query_form: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, style=form, explode=true, allowReserved=false" + name: query_form + in: query + schema: {} + query_spaceDelimited: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false" + name: query_spaceDelimited + in: query + style: spaceDelimited + schema: {} + query_pipeDelimited: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false" + name: query_pipeDelimited + in: query + style: pipeDelimited + schema: {} + query_deepObject: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, allowReserved=false" + name: query_deepObject + in: query + style: deepObject + schema: {} + header: + x-comment: "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false" + name: header + in: path + required: true + schema: {} + cookie_media_type: + x-comment: "expecting defaults: required=false, deprecated=false" + name: cookie_media_type + in: cookie + content: + text/*: + schema: {} + cookie_form: + x-comment: "expecting defaults: required=false, deprecated=false, style=form, explode=true, allowReserved=false" + name: cookie_form + in: cookie + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/tag-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/tag-object-example.yaml new file mode 100644 index 00000000..aba0c7d7 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/tag-object-example.yaml @@ -0,0 +1,15 @@ +openapi: 3.1.0 +info: + title: API + version: 1.0.0 +paths: {} +tags: + + - name: pet + description: Pets operations + + - name: external + description: Operations available to external consumers + externalDocs: + description: Find more info here + url: https://example.com diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/valid_schema_types.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/valid_schema_types.yaml new file mode 100644 index 00000000..c2459ed3 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/valid_schema_types.yaml @@ -0,0 +1,13 @@ +openapi: 3.1.1 + +# this example shows that top-level schemaObjects MAY be booleans + +info: + title: API + version: 1.0.0 +components: + schemas: + anything_boolean: true + nothing_boolean: false + anything_object: {} + nothing_object: { not: {} } diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.1/webhook-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/webhook-example.yaml new file mode 100644 index 00000000..44fc73aa --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.1/webhook-example.yaml @@ -0,0 +1,34 @@ +openapi: 3.1.0 +info: + title: Webhook Example + version: 1.0.0 +# Since OAS 3.1.0 the paths element isn't necessary. Now a valid OpenAPI Document can describe only paths, webhooks, or even only reusable components +webhooks: + # Each webhook needs a name + newPet: + # This is a Path Item Object, the only difference is that the request is initiated by the API provider + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + "200": + description: Return a 200 status to indicate that the data was received successfully + +components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/callback-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/callback-object-examples.yaml new file mode 100644 index 00000000..c7aac253 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/callback-object-examples.yaml @@ -0,0 +1,32 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + callbacks: + myCallback: + '{$request.query.queryUrl}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + transactionCallback: + 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + schemas: + SomePayload: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/comp_pathitems.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/comp_pathitems.yaml new file mode 100644 index 00000000..5178c1f5 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/comp_pathitems.yaml @@ -0,0 +1,6 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + pathItems: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/components-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/components-object-example.yaml new file mode 100644 index 00000000..33a56e60 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/components-object-example.yaml @@ -0,0 +1,71 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + schemas: + GeneralError: + type: object + properties: + code: + type: integer + format: int32 + message: + type: string + Category: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + Tag: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + parameters: + skipParam: + name: skip + in: query + description: number of items to skip + required: true + schema: + type: integer + format: int32 + limitParam: + name: limit + in: query + description: max records to return + required: true + schema: + type: integer + format: int32 + responses: + NotFound: + description: Entity not found. + IllegalInput: + description: Illegal input for operation. + GeneralError: + description: General Error + content: + application/json: + schema: + $ref: '#/components/schemas/GeneralError' + securitySchemes: + api_key: + type: apiKey + name: api-key + in: header + petstore_auth: + type: oauth2 + flows: + implicit: + authorizationUrl: https://example.org/api/oauth/dialog + scopes: + write:pets: modify pets in your account + read:pets: read your pets \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/example-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/example-object-examples.yaml new file mode 100644 index 00000000..56953682 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/example-object-examples.yaml @@ -0,0 +1,70 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + examples: + zip-example: {} + confirmation-success: {} + schemas: + SuccessResponse: {} + Address: {} + requestBodies: + with-example: + content: + 'application/json': + schema: + $ref: '#/components/schemas/Address' + examples: + foo: + summary: A foo example + value: + foo: bar + bar: + summary: A bar example + value: + bar: baz + application/xml: + examples: + xmlExample: + summary: This is an example in XML + externalValue: https://example.org/examples/address-example.xml + text/plain: + examples: + textExample: + summary: This is a text example + externalValue: https://foo.bar/examples/address-example.txt + parameters: + with-example: + name: zipCode + in: query + schema: + type: string + format: zip-code + examples: + zip-example: + $ref: '#/components/examples/zip-example' + responses: + '200': + description: your car appointment has been booked + content: + application/json: + schema: + $ref: '#/components/schemas/SuccessResponse' + examples: + confirmation-success: + $ref: '#/components/examples/confirmation-success' + application/x-www-form-urlencoded: + schema: + type: object + properties: + jsonValue: + type: string + encoding: + jsonValue: + contentType: application/json + examples: + jsonFormValue: + description: 'The JSON string "json" as a form value' + dataValue: json + serializedValue: jsonValue=%22json%22 diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/header-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/header-object-examples.yaml new file mode 100644 index 00000000..756cee23 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/header-object-examples.yaml @@ -0,0 +1,25 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + deprecated: false + schema: + type: integer + ETag: + required: true + content: + text/plain: + schema: + type: string + pattern: ^" + Reference: + $ref: '#/components/headers/ETag' + Style: + schema: + type: array + style: simple + explode: true diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/info-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/info-object-example.yaml new file mode 100644 index 00000000..1d36bef0 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/info-object-example.yaml @@ -0,0 +1,20 @@ +# including External Documentation Object Example +openapi: 3.2.0 +$self: https://example.com/openapi +info: + title: Example Pet Store App + summary: A pet store manager. + description: This is an example server for a pet store. + termsOfService: https://example.com/terms/ + contact: + name: API Support + url: https://www.example.com/support + email: support@example.com + license: + name: Apache 2.0 + url: https://www.apache.org/licenses/LICENSE-2.0.html + version: 1.0.1 +externalDocs: + description: Find more info here + url: https://example.com +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/info_summary.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/info_summary.yaml new file mode 100644 index 00000000..6697751d --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/info_summary.yaml @@ -0,0 +1,6 @@ +openapi: 3.2.0 +info: + title: API + summary: My lovely API + version: 1.0.0 +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/json_schema_dialect.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/json_schema_dialect.yaml new file mode 100644 index 00000000..fa054c9b --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/json_schema_dialect.yaml @@ -0,0 +1,15 @@ +openapi: 3.2.0 +info: + summary: Testing jsonSchemaDialect + title: My API + version: 1.0.0 + license: + name: Apache 2.0 + identifier: Apache-2.0 +jsonSchemaDialect: https://spec.openapis.org/oas/3.2/dialect/WORK-IN-PROGRESS +components: + schemas: + WithDollarSchema: + $id: "locked-metaschema" + $schema: https://spec.openapis.org/oas/3.2/dialect/WORK-IN-PROGRESS +paths: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/license_identifier.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/license_identifier.yaml new file mode 100644 index 00000000..20d5e436 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/license_identifier.yaml @@ -0,0 +1,9 @@ +openapi: 3.2.0 +info: + title: API + summary: My lovely API + version: 1.0.0 + license: + name: Apache + identifier: Apache-2.0 +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/link-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/link-object-examples.yaml new file mode 100644 index 00000000..9d471f0a --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/link-object-examples.yaml @@ -0,0 +1,66 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /users/{id}: + parameters: + - name: id + in: path + required: true + description: the user identifier, as userId + schema: + type: string + get: + responses: + '200': + description: the user being returned + content: + application/json: + schema: + type: object + properties: + uuid: # the unique user id + type: string + format: uuid + links: + address: + # the target link operationId + operationId: getUserAddress + parameters: + # get the `id` field from the request path parameter named `id` + userid: $request.path.id + address2: + operationId: getUserAddressByUUID + parameters: + # get the `uuid` field from the `uuid` field in the response body + userUuid: $response.body#/uuid + UserRepositories: + # returns array of '#/components/schemas/repository' + operationRef: '#/paths/~12.0~1repositories~1%7Busername%7D/get' + parameters: + username: $response.body#/username + UserRepositories2: + # returns array of '#/components/schemas/repository' + operationRef: https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1%7Busername%7D/get + parameters: + username: $response.body#/username + withBody: + operationId: queryUserWithBody + requestBody: + userId: $request.path.id + # the path item of the linked operation + /users/{userid}/address: + parameters: + - name: userid + in: path + required: true + description: the user identifier, as userId + schema: + type: string + # linked operation + get: + operationId: getUserAddress + responses: + '200': + description: the user's address \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/media-type-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/media-type-examples.yaml new file mode 100644 index 00000000..c4b47190 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/media-type-examples.yaml @@ -0,0 +1,178 @@ +# including Encoding Object examples +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + examples: + frog-example: {} + schemas: + Address: {} + Pet: {} + mediaTypes: + StreamingPets: + description: | + Streaming sequence of JSON pet representations, + suitable for use with any of the streaming JSON + media types. + itemSchema: + $ref: '#/components/schemas/Pet' +paths: + /something: + put: + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/Pet' + examples: + cat: + summary: An example of a cat + value: + name: Fluffy + petType: Cat + color: White + gender: male + breed: Persian + dog: + summary: An example of a dog with a cat's name + value: + name: Puma + petType: Dog + color: Black + gender: Female + breed: Mixed + frog: + $ref: '#/components/examples/frog-example' + application/jsonl: + $ref: '#/components/mediaTypes/StreamingPets' + application/x-ndjson: + $ref: '#/components/mediaTypes/StreamingPets' + application/xml: + schema: + type: object + properties: + foo: + type: string + xml: + namespace: https://example.com + prefix: example + name: Foo + bar: + type: array + items: + type: number + xml: + wrapped: true + attr: + type: string + xml: + attribute: true + elementNode: + $ref: "#/components/schemas/Pet" + xml: + nodeType: element + attributeNode: + type: string + xml: + nodeType: attribute + textNode: + type: string + xml: + nodeType: text + cdataNode: + type: string + xml: + nodeType: cdata + noneNode: + type: object + xml: + nodeType: none + application/x-www-form-urlencoded: + schema: + type: object + properties: + id: + type: string + format: uuid + address: + # complex types are stringified to support RFC 1866 + type: object + properties: {} + icon: + # The default with "contentEncoding" is application/octet-stream, + # so we need to set image media type(s) in the Encoding Object. + type: string + contentEncoding: base64url + encoding: + icon: + contentType: image/png, image/jpeg + multipart/form-data: + schema: + type: object + properties: + id: + # default is `text/plain` + type: string + format: uuid + addresses: + # default based on the `items` subschema would be + # `application/json`, but we want these address objects + # serialized as `application/xml` instead + description: addresses in XML format + type: array + items: + $ref: '#/components/schemas/Address' + profileImage: + # default is application/octet-stream, but we can declare + # a more specific image type or types + type: string + format: binary + forCoverage: + type: string + forCoverage2: + type: string + nested1: + type: object + nested2: + type: array + encoding: + addresses: + # require XML Content-Type in utf-8 encoding + # This is applied to each address part corresponding + # to each address in he array + contentType: application/xml; charset=utf-8 + profileImage: + # only accept png or jpeg + contentType: image/png, image/jpeg + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + schema: + type: integer + forCoverage: + style: form + explode: false + allowReserved: true + forCoverage2: + style: spaceDelimited + explode: true + nested1: + contentType: multipart/form-data + encoding: + inner: {} + nested2: + contentType: multipart/mixed + prefixEncoding: + - {} + itemEncoding: {} + multipart/related: + schema: + type: array + itemEncoding: + contentType: text/plain + prefixEncoding: + - headers: + Content-Location: + schema: + type: string diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/mega.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/mega.yaml new file mode 100644 index 00000000..8304fbe1 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/mega.yaml @@ -0,0 +1,62 @@ +openapi: 3.2.0 +info: + summary: My API's summary + title: My API + version: 1.0.0 + license: + name: Apache 2.0 + identifier: Apache-2.0 +paths: + /: + get: + parameters: [] + /{pathTest}: {} +webhooks: + myWebhook: + $ref: '#/components/pathItems/myPathItem' + description: Overriding description +components: + securitySchemes: + mtls: + type: mutualTLS + schemas: + Foo: + type: object + properties: + type: + const: foo + pathItems: + myPathItem: + post: + requestBody: + required: true + content: + 'application/json': + schema: + externalDocs: + description: More docs! + url: https://example.com/elsewhere.html + type: object + properties: + type: + type: string + int: + type: integer + exclusiveMaximum: 100 + exclusiveMinimum: 0 + none: + type: 'null' + arr: + type: array + $comment: Array without items keyword + either: + type: ['string','null'] + discriminator: + propertyName: type + mapping: + foo: Foo + defaultMapping: Bar + x-extension: true + anyOf: + - $ref: "#/components/schemas/Foo" + myArbitraryKeyword: true diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_comp.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_comp.yaml new file mode 100644 index 00000000..8f81f7e0 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_comp.yaml @@ -0,0 +1,5 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_hooks.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_hooks.yaml new file mode 100644 index 00000000..0e44257a --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_hooks.yaml @@ -0,0 +1,5 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +webhooks: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_paths.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_paths.yaml new file mode 100644 index 00000000..c332bba1 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/minimal_paths.yaml @@ -0,0 +1,5 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/non-oauth-scopes.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/non-oauth-scopes.yaml new file mode 100644 index 00000000..45506616 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/non-oauth-scopes.yaml @@ -0,0 +1,19 @@ +openapi: 3.2.0 +info: + title: Non-oAuth Scopes example + version: 1.0.0 +paths: + /users: + get: + security: + - bearerAuth: + - 'read:users' + - 'public' +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + bearerFormat: jwt + description: 'note: non-oauth scopes are not defined at the securityScheme level' + diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/operation-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/operation-object-example.yaml new file mode 100644 index 00000000..1e5bac29 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/operation-object-example.yaml @@ -0,0 +1,47 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /pets/{id}: + put: + tags: + - pet + summary: Updates a pet in the store with form data + operationId: updatePetWithForm + parameters: + - name: petId + in: path + description: ID of pet that needs to be updated + required: true + schema: + type: string + requestBody: + content: + application/x-www-form-urlencoded: + schema: + type: object + properties: + name: + description: Updated name of the pet + type: string + status: + description: Updated status of the pet + type: string + required: + - status + responses: + '200': + description: Pet updated. + content: + application/json: {} + application/xml: {} + '405': + description: Method Not Allowed + content: + application/json: {} + application/xml: {} + security: + - petstore_auth: + - write:pets + - read:pets \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-cookie-form-allowReserved.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-cookie-form-allowReserved.yaml new file mode 100644 index 00000000..ce5c5f58 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-cookie-form-allowReserved.yaml @@ -0,0 +1,18 @@ +openapi: 3.2.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + parameters: + style_form: + name: my_form_cookie + in: cookie + # default style is form, therefore allowReserved is allowed + allowReserved: true + schema: {} + style_cookie: + name: my_cookie_cookie + in: cookie + style: cookie + # no percent decoding for style=cookie, therefore allowReserved is not allowed + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-examples.yaml new file mode 100644 index 00000000..51e91736 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-examples.yaml @@ -0,0 +1,79 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /user/{username}: + parameters: + - name: token + in: header + description: token to be passed as a header + required: true + explode: false + schema: + type: array + items: + type: integer + format: int64 + style: simple + - name: usernames + in: path + description: usernames to fetch + required: true + explode: false + schema: + type: array + - name: id + in: query + description: IDs of the object to fetch + required: false + schema: + type: array + items: + type: string + style: form + explode: true + - in: query + name: freeForm + schema: + type: object + additionalProperties: + type: integer + style: form + - in: query + name: coordinates + content: + application/json: + schema: + type: object + required: + - lat + - long + properties: + lat: + type: number + long: + type: number + - in: cookie + name: my_cookie1 + style: form + explode: false + schema: {} + - in: cookie + name: my_cookie2 + style: cookie + explode: true + schema: {} + /user: + parameters: + - in: querystring + name: json + content: + application/json: + schema: + # Allow an arbitrary JSON object to keep + # the example simple + type: object + example: + numbers: [1, 2] + flag: null diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-path-allowReserved.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-path-allowReserved.yaml new file mode 100644 index 00000000..5d394d90 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-path-allowReserved.yaml @@ -0,0 +1,12 @@ +openapi: 3.2.0 +info: + title: api + version: 1.0.0 +components: + parameters: + path: + name: my-path + in: path + required: true + allowReserved: false + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-query-allowReserved.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-query-allowReserved.yaml new file mode 100644 index 00000000..237ece10 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/parameter-object-query-allowReserved.yaml @@ -0,0 +1,11 @@ +openapi: 3.2.0 +info: + title: allowReserved only permitted with in and style values that percent-encode + version: 1.0.0 +components: + parameters: + my_query: + name: my_query + in: query + allowReserved: true + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path-item-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path-item-object-example.yaml new file mode 100644 index 00000000..d3b73c2a --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path-item-object-example.yaml @@ -0,0 +1,78 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + schemas: + Pet: {} + ErrorModel: {} +paths: + /pets/{id}: + get: + description: Returns pets based on ID + summary: Find pets by ID + operationId: getPetsById + responses: + '200': + description: pet response + content: + '*/*': + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + default: + description: error payload + content: + text/html: + schema: + $ref: '#/components/schemas/ErrorModel' + query: + description: Returns pets based on ID + summary: Find pets by ID + operationId: queryPetsById + responses: + '200': + description: pet response + content: + '*/*': + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + default: + description: error payload + content: + text/html: + schema: + $ref: '#/components/schemas/ErrorModel' + parameters: + - name: id + in: path + description: ID of pet to use + required: true + schema: + type: array + items: + type: string + style: simple + additionalOperations: + COPY: + description: Copies pet information based on ID + summary: Copies pets by ID + operationId: copyPetsById + responses: + '200': + description: pet response + content: + '*/*': + schema: + type: array + items: + $ref: '#/components/schemas/Pet' + default: + description: error payload + content: + text/html: + schema: + $ref: '#/components/schemas/ErrorModel' \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_item_servers_parameters.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_item_servers_parameters.yaml new file mode 100644 index 00000000..d3c28d75 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_item_servers_parameters.yaml @@ -0,0 +1,114 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /things: + summary: Lots of things + servers: + - url: https://things.example.com + get: + summary: Get a list of things + externalDocs: + description: Find more info here + url: https://example.com + parameters: + - $ref: '#/components/parameters/biscuit' + summary: The maximum number of things to return + description: The maximum number of things to return + responses: + default: + description: A list of things + servers: + - url: https://things.example.com + post: + deprecated: false + requestBody: + $ref: '#/components/requestBodies/ThingRequestBody' + responses: + '201': + $ref: '#/components/responses/ThingResponse' + callbacks: + myCallback: + '{$request.query.queryUrl}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + transactionCallback: + $ref: '#/components/callbacks/transactionCallback' + patch: {} + delete: {} + head: {} + options: {} + trace: {} +components: + callbacks: + transactionCallback: + 'http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}': + post: + requestBody: + description: Callback payload + content: + application/json: + schema: + $ref: '#/components/schemas/SomePayload' + responses: + '200': + description: callback successfully processed + examples: + ThingExample: + summary: A thing + description: A thing + value: + id: 1 + name: Thing + links: + ThingLink: + description: A link to a thing + operationId: getThing + parameters: + thingId: '$response.body#/id' + server: + url: https://things.example.com + ThingyLink: + $ref: '#/components/links/ThingLink' + parameters: + limit: + name: limit + in: query + required: false + allowEmptyValue: false + allowReserved: false + deprecated: true + description: The maximum number of list items to return + schema: + type: integer + minimum: 0 + biscuit: + name: biscuit + in: cookie + style: form + schema: + type: string + requestBodies: + ThingRequestBody: + content: + application/json: + schema: + type: object + responses: + ThingResponse: + description: A thing + content: + application/json: + schema: + type: object + schemas: + SomePayload: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_no_response.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_no_response.yaml new file mode 100644 index 00000000..e4876799 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_no_response.yaml @@ -0,0 +1,7 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /: + get: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_var_empty_pathitem.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_var_empty_pathitem.yaml new file mode 100644 index 00000000..e79b7cd4 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/path_var_empty_pathitem.yaml @@ -0,0 +1,6 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /{var}: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/paths-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/paths-object-example.yaml new file mode 100644 index 00000000..e084b161 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/paths-object-example.yaml @@ -0,0 +1,20 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + schemas: + pet: {} +paths: + /pets: + get: + description: Returns all pets from the system that the user has access to + responses: + '200': + description: A list of pets. + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/pet' diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/request-body-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/request-body-examples.yaml new file mode 100644 index 00000000..eac0fa91 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/request-body-examples.yaml @@ -0,0 +1,37 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + schemas: + User: {} +paths: + /something: + put: + requestBody: + description: user to add to the system + content: + application/json: + schema: + $ref: '#/components/schemas/User' + examples: + user: + summary: User example + externalValue: https://foo.bar/examples/user-example.json + application/xml: + schema: + $ref: '#/components/schemas/User' + examples: + user: + summary: User example in XML + externalValue: https://foo.bar/examples/user-example.xml + text/plain: + examples: + user: + summary: User example in plain text + externalValue: https://foo.bar/examples/user-example.txt + '*/*': + examples: + user: + summary: User example in other format + externalValue: https://foo.bar/examples/user-example.whatever diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/response-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/response-object-examples.yaml new file mode 100644 index 00000000..c206ca76 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/response-object-examples.yaml @@ -0,0 +1,45 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +components: + responses: + complex-object-array: + summary: Complex object array + description: A complex object array response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/VeryComplexType' + simple-string: + description: A simple string response + content: + text/plain: + schema: + type: string + plain-text-with-headers: + description: A simple string response + content: + text/plain: + schema: + type: string + example: 'whoa!' + headers: + X-Rate-Limit-Limit: + description: The number of allowed requests in the current period + schema: + type: integer + X-Rate-Limit-Remaining: + description: The number of remaining requests in the current period + schema: + type: integer + X-Rate-Limit-Reset: + description: The number of seconds left in the current period + schema: + type: integer + no-return-value: + description: object created + schemas: + VeryComplexType: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/schema-object-deprecated-example-keyword.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/schema-object-deprecated-example-keyword.yaml new file mode 100644 index 00000000..969e66f2 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/schema-object-deprecated-example-keyword.yaml @@ -0,0 +1,17 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: + /user: + parameters: + - in: query + name: example + schema: + # Allow an arbitrary JSON object to keep + # the example simple + type: object + # DEPRECATED: don't use example keyword inside Schema Object + example: + numbers: [1, 2] + flag: null diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/schema.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/schema.yaml new file mode 100644 index 00000000..a6d72b99 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/schema.yaml @@ -0,0 +1,55 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: {} +components: + schemas: + model: + type: object + properties: + one: + description: type array + type: + - integer + - string + two: + description: type 'null' + type: "null" + three: + description: type array including 'null' + type: + - string + - "null" + four: + description: array with no items + type: array + five: + description: singular example + type: string + examples: + - exampleValue + six: + description: exclusiveMinimum true + exclusiveMinimum: 10 + seven: + description: exclusiveMinimum false + minimum: 10 + eight: + description: exclusiveMaximum true + exclusiveMaximum: 20 + nine: + description: exclusiveMaximum false + maximum: 20 + ten: + description: nullable string + type: + - string + - "null" + eleven: + description: x-nullable string + type: + - string + - "null" + twelve: + description: file/binary diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/security-scheme-object-examples.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/security-scheme-object-examples.yaml new file mode 100644 index 00000000..d3472d5a --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/security-scheme-object-examples.yaml @@ -0,0 +1,69 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +security: + - basic: [] + - apiKey: [] + - JWT-bearer: [] + - mutualTLS: [] + - OAuth2: + - write:pets + - read:pets +components: + securitySchemes: + basic: + type: http + scheme: basic + apiKey: + type: apiKey + name: api-key + in: header + JWT-bearer: + type: http + scheme: bearer + bearerFormat: JWT + mutualTLS: + type: mutualTLS + description: Cert must be signed by example.com CA + OAuth2: + type: oauth2 + oauth2MetadataUrl: https://example.com/api/oauth/metadata + flows: + authorizationCode: + authorizationUrl: https://example.com/api/oauth/dialog + refreshUrl: https://example.com/api/oauth/refresh + tokenUrl: https://example.com/api/oauth/token + scopes: + write:pets: modify pets in your account + read:pets: read your pets + password: + tokenUrl: https://example.com/api/oauth/token + scopes: + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + clientCredentials: + tokenUrl: https://example.com/api/oauth/token + scopes: + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + deviceAuthorization: + deviceAuthorizationUrl: https://example.com/api/oauth/device + tokenUrl: https://example.com/api/oauth/token + scopes: + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + OAuth2Old: + deprecated: true + type: oauth2 + flows: + implicit: + authorizationUrl: https://example.com/api/oauth/dialog + scopes: + read:pets: read your pets + refreshUrl: https://example.com/api/oauth/refresh + OpenIdConnect: + type: openIdConnect + openIdConnectUrl: https://example.com/api/oauth/openid + external: + $ref: 'https://example.com/api/openapi.json#/components/externalDocs/ThingExternalDocs' \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/servers.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/servers.yaml new file mode 100644 index 00000000..07992113 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/servers.yaml @@ -0,0 +1,26 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: {} +servers: + - url: /v1 + description: Run locally. + name: local + - url: https://production.com/v1 + description: Run on production server. + - url: https://{username}.gigantic-server.com:{port}/{basePath} + description: The production API server + variables: + username: + # note! no enum here means it is an open value + default: demo + description: A user-specific subdomain. Use `demo` for a free sandbox environment. + port: + enum: + - '8443' + - '443' + default: '8443' + basePath: + # open meaning there is the opportunity to use special base paths as assigned by the provider, default is `v2` + default: v2 \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/specification-extensions.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/specification-extensions.yaml new file mode 100644 index 00000000..8148462f --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/specification-extensions.yaml @@ -0,0 +1,6 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: {} +x-tensions: specification extensions are prefixed with `x-` \ No newline at end of file diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/style-defaults.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/style-defaults.yaml new file mode 100644 index 00000000..823eac7d --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/style-defaults.yaml @@ -0,0 +1,105 @@ +openapi: 3.2.0 +info: + title: various permutations of parameter objects, with non-required values left to their defaults + version: 1.0.0 +components: + mediaTypes: + encoding_object_defaults: # media type name + encoding: + no_styles: # property name + x-comment: "style, explode and allowReserved are not present, so contentType is used; no defaults expected as default contentType cannot be determined by the schema" + style_form: + x-comment: "expecting defaults: explode=true, allowReserved=false" + style: form + style_spaceDelimited: + x-comment: "expecting defaults: explode=false, allowReserved=false" + style: spaceDelimited + explode: + x-comment: "expecting defaults: style=form, allowReserved=false" + explode: false + allowReserved: + x-comment: "expecting default: style=form, explode=true" + allowReserved: true + parameters: + path_media_type: + x-comment: "expecting defaults: deprecated=false" + name: path_media-type + in: path + required: true + content: + text/*: + schema: {} + path_simple: + x-comment: "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false" + name: path_simple + in: path + required: true + schema: {} + path_matrix: + x-comment: "expecting defaults: deprecated=false, explode=false, allowReserved=false" + name: path_matrix + in: path + required: true + style: matrix + schema: {} + path_label: + x-comment: "expecting defaults: deprecated=false, explode=false, allowReserved=false" + name: path_label + in: path + required: true + style: label + schema: {} + query_media_type: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false" + name: query_media_type + in: query + content: + text/*: + schema: {} + query_form: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, style=form, explode=true, allowReserved=false" + name: query_form + in: query + schema: {} + query_spaceDelimited: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false" + name: query_spaceDelimited + in: query + style: spaceDelimited + schema: {} + query_pipeDelimited: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false" + name: query_pipeDelimited + in: query + style: pipeDelimited + schema: {} + query_deepObject: + x-comment: "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, allowReserved=false" + name: query_deepObject + in: query + style: deepObject + schema: {} + header: + x-comment: "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false" + name: header + in: path + required: true + schema: {} + cookie_media_type: + x-comment: "expecting defaults: required=false, deprecated=false" + name: cookie_media_type + in: cookie + content: + text/*: + schema: {} + cookie_form: + x-comment: "expecting defaults: required=false, deprecated=false, style=form, explode=true, allowReserved=false" + name: cookie_form + in: cookie + schema: {} + cookie_cookie: + x-comment: "expecting defaults: required=false, deprecated=false, explode=true" + name: cookie_cookie + in: cookie + style: cookie + schema: {} diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/tag-object-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/tag-object-example.yaml new file mode 100644 index 00000000..6e740c8d --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/tag-object-example.yaml @@ -0,0 +1,25 @@ +openapi: 3.2.0 +info: + title: API + version: 1.0.0 +paths: {} +tags: + + - name: account-updates + summary: Account Updates + description: Account update operations + kind: nav + + - name: partner + summary: Partner + description: Operations available to the partners network + parent: external + kind: audience + + - name: external + summary: External + description: Operations available to external consumers + kind: audience + externalDocs: + description: Find more info here + url: https://example.com diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/valid_schema_types.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/valid_schema_types.yaml new file mode 100644 index 00000000..43e7cdc7 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/valid_schema_types.yaml @@ -0,0 +1,14 @@ +openapi: 3.2.1 + +# this example shows that top-level schemaObjects MAY be booleans + +info: + title: API + version: 1.0.0 +components: + schemas: + anything_boolean: true + nothing_boolean: false + anything_object: {} + nothing_object: { not: {} } + diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/3.2/webhook-example.yaml b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/webhook-example.yaml new file mode 100644 index 00000000..c0b505ac --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/3.2/webhook-example.yaml @@ -0,0 +1,35 @@ +openapi: 3.2.0 +info: + title: Webhook Example + version: 1.0.0 +# Since OAS 3.1.0 the paths element isn't necessary. Now a valid OpenAPI Document can describe only paths, webhooks, or even only reusable components +webhooks: + # Each webhook needs a name + newPet: + # This is a Path Item Object, the only difference is that the request is initiated by the API provider + post: + requestBody: + description: Information about a new pet in the system + content: + application/json: + schema: + $ref: "#/components/schemas/Pet" + responses: + "200": + description: Return a 200 status to indicate that the data was received successfully + +components: + schemas: + Pet: + required: + - id + - name + properties: + id: + type: integer + format: int64 + name: + type: string + tag: + type: string + diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/LICENSE b/packages/redocly-plugin-downlevel/fixtures/oai/LICENSE new file mode 100644 index 00000000..23b34fdf --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright The Linux Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/redocly-plugin-downlevel/fixtures/oai/NOTICE b/packages/redocly-plugin-downlevel/fixtures/oai/NOTICE new file mode 100644 index 00000000..f9508ea0 --- /dev/null +++ b/packages/redocly-plugin-downlevel/fixtures/oai/NOTICE @@ -0,0 +1,11 @@ +The files in this directory are copied, unmodified, from the OpenAPI Specification repository: + + https://github.com/OAI/OpenAPI-Specification + +The OpenAPI Specification is a community-driven open specification within the OpenAPI Initiative, a Linux Foundation Collaborative Project. Licensed under the Apache License, Version 2.0; see LICENSE in this directory. + + 3.0/ _archive_/schemas/v3.0/pass at 4c4ae377d28cc9f0eb3ed598fcf3c89512ff8fa3 (main) + 3.1/ tests/schema/pass at 6c6c327036987ad18352478b5eba54be10e4865f (v3.1-dev) + 3.2/ tests/schema/pass at bb95c80a93c42749ed79b11a4bb4a5f4cf8eafc0 (v3.2-dev) + +scripts/vendor-fixtures.sh reproduces them. diff --git a/packages/redocly-plugin-downlevel/package.json b/packages/redocly-plugin-downlevel/package.json new file mode 100644 index 00000000..b6b2ddd7 --- /dev/null +++ b/packages/redocly-plugin-downlevel/package.json @@ -0,0 +1,48 @@ +{ + "name": "redocly-plugin-downlevel", + "type": "module", + "version": "0.1.0", + "description": "Redocly plugin that rewrites an OpenAPI 3.x description as an earlier 3.x release, one release at a time.", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/vrchatapi/specification.git", + "directory": "packages/redocly-plugin-downlevel" + }, + "keywords": [ + "redocly", + "redocly-plugin", + "openapi", + "openapi-3.2", + "openapi-3.1", + "openapi-3.0", + "downlevel", + "convert" + ], + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "files": [ + "dist" + ], + "engines": { + "node": ">=22" + }, + "scripts": { + "build": "tsc -p tsconfig.build.json", + "test": "bun test", + "prepack": "pnpm run build" + }, + "peerDependencies": { + "@redocly/openapi-core": "^2.53.3" + }, + "devDependencies": { + "@redocly/openapi-core": "^2.54.3", + "@types/bun": "^1.4.2", + "@types/node": "^24.13.6", + "typescript": "^6.0.3" + } +} diff --git a/packages/redocly-plugin-downlevel/scripts/vendor-fixtures.sh b/packages/redocly-plugin-downlevel/scripts/vendor-fixtures.sh new file mode 100755 index 00000000..c3cd70ac --- /dev/null +++ b/packages/redocly-plugin-downlevel/scripts/vendor-fixtures.sh @@ -0,0 +1,33 @@ +#!/bin/sh +set -eu + +cd "$(dirname "$0")/.." + +vendor() { + repository=$1 + commit=$2 + source=$3 + destination=$4 + + checkout=$(mktemp -d) + git clone --quiet --filter=blob:none --no-checkout "https://github.com/$repository.git" "$checkout" + git -C "$checkout" fetch --quiet origin "$commit" + + mkdir -p "$destination" + git -C "$checkout" ls-tree --name-only "$commit" -- "$source/" | while read -r file; do + case "$file" in + *.yaml) git -C "$checkout" show "$commit:$file" > "$destination/$(basename "$file")" ;; + esac + done + git -C "$checkout" show "$commit:LICENSE" > "$(dirname "$destination")/LICENSE" + + rm -rf "$checkout" +} + +rm -rf fixtures/oai fixtures/learn + +vendor OAI/OpenAPI-Specification 4c4ae377d28cc9f0eb3ed598fcf3c89512ff8fa3 _archive_/schemas/v3.0/pass fixtures/oai/3.0 +vendor OAI/OpenAPI-Specification 6c6c327036987ad18352478b5eba54be10e4865f tests/schema/pass fixtures/oai/3.1 +vendor OAI/OpenAPI-Specification bb95c80a93c42749ed79b11a4bb4a5f4cf8eafc0 tests/schema/pass fixtures/oai/3.2 +vendor OAI/learn.openapis.org bbb743ed3b7c5ed76b6e6ba9b302af38f3956c44 examples/v3.1 fixtures/learn/3.1 +vendor OAI/learn.openapis.org bbb743ed3b7c5ed76b6e6ba9b302af38f3956c44 examples/v3.2 fixtures/learn/3.2 diff --git a/packages/redocly-plugin-downlevel/src/3.0.1/index.ts b/packages/redocly-plugin-downlevel/src/3.0.1/index.ts new file mode 100644 index 00000000..7396bcc9 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.1/index.ts @@ -0,0 +1,15 @@ +import { Oas3Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; + +/** + * https://spec.openapis.org/oas/v3.0.0.html + */ +export const layer: Layer = { + version: "3.0.1", + writes: "3.0.0", + types: Oas3Types, + specVersion: "oas3_0", + checks: [], + transforms: [] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.0.2/index.ts b/packages/redocly-plugin-downlevel/src/3.0.2/index.ts new file mode 100644 index 00000000..21d31706 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.2/index.ts @@ -0,0 +1,15 @@ +import { Oas3Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; + +/** + * https://spec.openapis.org/oas/v3.0.1.html + */ +export const layer: Layer = { + version: "3.0.2", + writes: "3.0.1", + types: Oas3Types, + specVersion: "oas3_0", + checks: [], + transforms: [] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.0.3/index.ts b/packages/redocly-plugin-downlevel/src/3.0.3/index.ts new file mode 100644 index 00000000..57b0b542 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.3/index.ts @@ -0,0 +1,15 @@ +import { Oas3Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; + +/** + * https://spec.openapis.org/oas/v3.0.2.html + */ +export const layer: Layer = { + version: "3.0.3", + writes: "3.0.2", + types: Oas3Types, + specVersion: "oas3_0", + checks: [], + transforms: [] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.0.4/downlevel.test.ts b/packages/redocly-plugin-downlevel/src/3.0.4/downlevel.test.ts new file mode 100644 index 00000000..9f9b70ec --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.4/downlevel.test.ts @@ -0,0 +1,55 @@ +import { describe, expect, test } from "bun:test"; + +import { layer } from "../fixture.ts"; + +const from304 = layer("3.0.4", "3.0.3"); + +const ok = { 200: { description: "ok" } }; + +describe("3.0.4", () => { + test("spells out the encodings 3.0.3 defaulted differently", async () => { + const { document } = await from304({ + paths: { + "/a": { + post: { + requestBody: { + content: { + "application/x-www-form-urlencoded": { schema: { type: "object", properties: { filter: { type: "object" } } } }, + "multipart/form-data": { schema: { type: "object", properties: { key: { type: "string", format: "byte" } } } } + } + }, + responses: ok + } + } + } + }); + expect(document.paths?.["/a"]).toStrictEqual({ + post: { + requestBody: { + content: { + "application/x-www-form-urlencoded": { + schema: { type: "object", properties: { filter: { type: "object" } } }, + encoding: { filter: { contentType: "application/json" } } + }, + "multipart/form-data": { + schema: { type: "object", properties: { key: { type: "string", format: "byte" } } }, + encoding: { key: { contentType: "application/octet-stream" } } + } + } + }, + responses: ok + } + }); + }); + + test("reports what 3.0.3 reads differently or forbids", async () => { + const { problems } = await from304({ + info: { title: "fixture", version: "1", termsOfService: "terms" }, + paths: { "/a": { get: { parameters: [{ name: "f", in: "query", style: "pipeDelimited", schema: { type: "object" } }], responses: ok } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/info/termsOfService", message: "OpenAPI 3.0.3 resolves a relative URL against a different base." }, + { severity: "error", pointer: "#/paths/~1a/get/parameters/0/style", message: "OpenAPI 3.0.3 allows `style: pipeDelimited` only for arrays." } + ]); + }); +}); diff --git a/packages/redocly-plugin-downlevel/src/3.0.4/index.ts b/packages/redocly-plugin-downlevel/src/3.0.4/index.ts new file mode 100644 index 00000000..9f4dce5a --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.4/index.ts @@ -0,0 +1,20 @@ +import { Oas3Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; +import { pinFormEncoding } from "../transforms/pin-form-encoding.ts"; +import { reportNamespaceFragments } from "../transforms/report-namespace-fragments.ts"; +import { reportRelativeUrls } from "../transforms/report-relative-urls.ts"; +import { pinByteEncoding } from "./pin-byte-encoding.ts"; +import { reportDelimitedObjects } from "./report-delimited-objects.ts"; + +/** + * https://spec.openapis.org/oas/v3.0.3.html + */ +export const layer: Layer = { + version: "3.0.4", + writes: "3.0.3", + types: Oas3Types, + specVersion: "oas3_0", + checks: [reportRelativeUrls, reportNamespaceFragments, reportDelimitedObjects], + transforms: [pinFormEncoding, pinByteEncoding] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.0.4/pin-byte-encoding.ts b/packages/redocly-plugin-downlevel/src/3.0.4/pin-byte-encoding.ts new file mode 100644 index 00000000..b3654fd0 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.4/pin-byte-encoding.ts @@ -0,0 +1,24 @@ +import type { Node, Transform } from "../layer.ts"; + +/** + * 3.0.4 sends a `format: byte` multipart part as `application/octet-stream`; + * 3.0.3's table said `text/plain`. Writing the `contentType` out keeps the later + * reading. + * + * https://spec.openapis.org/oas/v3.0.4#encoding-object + */ +export const pinByteEncoding: Transform = () => ({ + MediaType: { + leave: (node, { key }) => { + if (!String(key).startsWith("multipart/")) return; + + const properties = (node.schema as Node | undefined)?.properties as Record | undefined; + for (const [name, property] of Object.entries(properties ?? {})) { + if (property.format !== "byte") continue; + + const encoding = (node.encoding ??= {}) as Record; + encoding[name] ??= { contentType: "application/octet-stream" }; + } + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.0.4/report-delimited-objects.ts b/packages/redocly-plugin-downlevel/src/3.0.4/report-delimited-objects.ts new file mode 100644 index 00000000..5a4d53ef --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.0.4/report-delimited-objects.ts @@ -0,0 +1,17 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.0.4 lets `spaceDelimited` and `pipeDelimited` serialize objects; 3.0.3's + * style table allows them for arrays only. + * + * https://spec.openapis.org/oas/v3.0.4#style-values + */ +export const reportDelimitedObjects: Transform = ({ version }) => ({ + Parameter: { + enter: (parameter, { report, location }) => { + const style = parameter.style; + if ((style === "spaceDelimited" || style === "pipeDelimited") && (parameter.schema as Record | undefined)?.type === "object") + report({ message: `OpenAPI ${version} allows \`style: ${style}\` only for arrays.`, location: location.child("style") }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/downlevel.test.ts b/packages/redocly-plugin-downlevel/src/3.1.0/downlevel.test.ts new file mode 100644 index 00000000..289d883a --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/downlevel.test.ts @@ -0,0 +1,656 @@ +import { describe, expect, test } from "bun:test"; + +import { layer, reference } from "../fixture.ts"; + +const from31 = layer("3.1.0", "3.0.4"); +const loosening = layer("3.1.0", "3.0.4", { loosenUnions: true }); + +describe("type", () => { + test("turns a type pair with null into nullable", async () => { + const { schemas, problems } = await from31.schemas({ + A: { type: ["string", "null"], description: "a" }, + B: { type: ["null", "object"], properties: { c: { type: "string" } } } + }); + expect(schemas).toStrictEqual({ + A: { type: "string", nullable: true, description: "a" }, + B: { type: "object", nullable: true, properties: { c: { type: "string" } } } + }); + expect(problems).toStrictEqual([]); + }); + + test("reaches nested schemas", async () => { + const { schemas } = await from31.schemas({ + A: { type: "array", items: { type: ["integer", "null"] } }, + B: { type: "object", properties: { c: { allOf: [{ type: ["boolean", "null"] }] } } } + }); + expect(schemas).toStrictEqual({ + A: { type: "array", items: { type: "integer", nullable: true } }, + B: { type: "object", properties: { c: { allOf: [{ type: "boolean", nullable: true }] } } } + }); + }); + + test("leaves a single type alone", async () => { + const { schemas, problems } = await from31.schemas({ A: { type: "string" } }); + expect(schemas).toStrictEqual({ A: { type: "string" } }); + expect(problems).toStrictEqual([]); + }); + + test("reports a type 3.0 cannot express", async () => { + const { problems } = await from31.schemas({ + A: { type: "null" }, + B: { type: ["null"] } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/A/type", message: "OpenAPI 3.0.4 has no `null` type." }, + { severity: "error", pointer: "#/components/schemas/B/type", message: "OpenAPI 3.0.4 has no `null` type." } + ]); + }); + + test("writes several types as the union they are", async () => { + const { schemas, problems } = await from31.schemas({ + A: { type: ["string", "integer"], minLength: 1 }, + B: { type: ["string", "integer", "null"] } + }); + expect(schemas).toStrictEqual({ + A: { anyOf: [{ type: "string" }, { type: "integer" }], minLength: 1 }, + B: { anyOf: [{ type: "string", nullable: true }, { type: "integer" }] } + }); + expect(problems).toStrictEqual([]); + }); + + test("loosens several types as the union they are", async () => { + const { schemas, problems } = await loosening.schemas({ + A: { type: ["string", "integer"], minLength: 1, description: "a" }, + B: { type: ["string", "integer", "null"] }, + C: { type: ["string", "integer"], oneOf: [{ minLength: 1 }, { minimum: 1 }] } + }); + expect(schemas).toStrictEqual({ + A: { description: "a" }, + B: {}, + C: { allOf: [{}] } + }); + expect(problems).toStrictEqual([]); + }); +}); + +describe("unions", () => { + const user = { + type: "object", + required: ["id", "name"], + properties: { id: { type: "string" }, name: { type: "string" }, state: reference("State"), age: { type: "integer" } } + }; + const current = { + type: "object", + required: ["id", "email"], + properties: { id: { type: "string" }, email: { type: "string" }, state: reference("State") } + }; + const state = { type: "string", enum: ["active", "offline"] }; + + test("merges objects, requiring only what every member requires", async () => { + const { schemas, problems } = await loosening.schemas({ + User: user, + Current: current, + State: state, + Union: { title: "Union", oneOf: [reference("User"), reference("Current")], discriminator: { propertyName: "id" } } + }); + expect(schemas.Union).toStrictEqual({ + title: "Union", + type: "object", + required: ["id"], + properties: { + id: { type: "string" }, + name: { type: "string" }, + state: reference("State"), + age: { type: "integer" }, + email: { type: "string" } + } + }); + expect(problems).toStrictEqual([]); + }); + + test("loosens a property the members declare differently", async () => { + const { schemas } = await loosening.schemas({ + Union: { + anyOf: [ + { type: "object", properties: { kind: { type: "string", enum: ["a"], minLength: 1 } } }, + { type: "object", properties: { kind: { type: "string", enum: ["b"], minLength: 2 } } } + ] + } + }); + expect(schemas.Union).toStrictEqual({ type: "object", properties: { kind: { type: "string", enum: ["a", "b"] } } }); + }); + + test("merges what each member reaches through allOf, letting a member's own declaration win", async () => { + const { schemas, problems } = await loosening.schemas({ + Base: { type: "object", required: ["id", "kind"], properties: { id: { type: "string" }, kind: { type: "string" } } }, + A: { type: "object", allOf: [reference("Base")], required: ["a"], properties: { kind: { type: "string", enum: ["a"] }, a: { type: "integer" } } }, + B: { type: "object", allOf: [reference("Base")], required: ["b"], properties: { kind: { type: "string", enum: ["b"] }, b: { type: "integer" } } }, + Union: { oneOf: [reference("A"), reference("B")] } + }); + expect(schemas.Union).toStrictEqual({ + type: "object", + required: ["id", "kind"], + properties: { + id: { type: "string" }, + kind: { type: "string", enum: ["a", "b"] }, + a: { type: "integer" }, + b: { type: "integer" } + } + }); + expect(problems).toStrictEqual([]); + }); + + test("loosens a union of single values into an enum, keeping each value's title, description and deprecation", async () => { + const { schemas, problems } = await loosening.schemas({ + Status: { + oneOf: [ + { type: "string", const: "a", title: "A", description: "first" }, + { type: "string", const: "b", title: "B", deprecated: true }, + { type: "string", const: "c" } + ] + }, + Mixed: { anyOf: [{ type: "string", enum: ["a", "b"] }, { const: "c", description: "see" }] }, + Plain: { oneOf: [{ type: "integer", const: 1 }, { type: "integer", const: 2 }] }, + Nullable: { oneOf: [{ type: "string", const: "a", title: "A" }, { type: "string", const: "b" }, { type: "null" }] } + }); + expect(schemas).toStrictEqual({ + Status: { type: "string", enum: ["a", "b", "c"], "x-enum-descriptions": ["A - first", "B", ""], "x-enum-deprecated": [false, true, false] }, + Mixed: { type: "string", enum: ["a", "b", "c"], "x-enum-descriptions": ["", "", "see"] }, + Plain: { type: "integer", enum: [1, 2] }, + Nullable: { type: "string", nullable: true, enum: ["a", "b"], "x-enum-descriptions": ["A", ""] } + }); + expect(problems).toStrictEqual([]); + }); + + test("leaves enum extensions a union already carries", async () => { + const { schemas } = await loosening.schemas({ + Status: { "x-enum-descriptions": ["kept"], oneOf: [{ type: "string", const: "a", title: "A" }, { type: "string", const: "b" }] } + }); + expect(schemas.Status).toStrictEqual({ type: "string", enum: ["a", "b"], "x-enum-descriptions": ["kept"] }); + }); + + test("drops an enum some members lack", async () => { + const { schemas } = await loosening.schemas({ + Union: { oneOf: [{ type: "string", enum: ["a"] }, { type: "string", format: "uri" }] } + }); + expect(schemas.Union).toStrictEqual({ type: "string" }); + }); + + test("loosens array items", async () => { + const { schemas } = await loosening.schemas({ + Union: { oneOf: [{ type: "array", items: { type: "string" } }, { type: "array", items: { type: "integer" } }] } + }); + expect(schemas.Union).toStrictEqual({ type: "array", items: {} }); + }); + + test("accepts anything when the members' types differ", async () => { + const { schemas, problems } = await loosening.schemas({ + User: user, + State: state, + Union: { description: "Either.", oneOf: [{ type: "string" }, reference("User")] } + }); + expect(schemas.Union).toStrictEqual({ description: "Either." }); + expect(problems).toStrictEqual([]); + }); + + test("drops a rule beside the union that the loosened type takes no part in", async () => { + const { schemas, problems } = await loosening.schemas({ + User: user, + State: state, + Mixed: { minLength: 1, maxItems: 2, required: ["id"], description: "m", oneOf: [{ type: "string" }, reference("User")] }, + Strings: { minLength: 1, minimum: 0, oneOf: [{ type: "string" }, { type: "string", format: "uri" }] }, + Numbers: { minimum: 0, multipleOf: 2, pattern: "^a", anyOf: [{ type: "integer" }, { type: "null" }] }, + Reference: { maxLength: 3, minProperties: 1, anyOf: [reference("State"), { type: "null" }] } + }); + expect(schemas.Mixed).toStrictEqual({ required: ["id"], description: "m" }); + expect(schemas.Strings).toStrictEqual({ type: "string", minLength: 1 }); + expect(schemas.Numbers).toStrictEqual({ type: "integer", nullable: true, minimum: 0, multipleOf: 2 }); + expect(schemas.Reference).toStrictEqual({ ...reference("State"), nullable: true, maxLength: 3 }); + expect(problems).toStrictEqual([]); + }); + + test("turns a null member into nullable", async () => { + const { schemas, problems } = await loosening.schemas({ + Union: { oneOf: [{ type: "string", minLength: 1 }, { type: "null" }] } + }); + expect(schemas.Union).toStrictEqual({ type: "string", minLength: 1, nullable: true }); + expect(problems).toStrictEqual([]); + }); + + test("keeps nullable from a member", async () => { + const { schemas, problems } = await loosening.schemas({ + Union: { anyOf: [{ type: ["string", "null"] }, { type: "string", enum: ["a"] }] } + }); + expect(schemas.Union).toStrictEqual({ type: "string", nullable: true }); + expect(problems).toStrictEqual([]); + }); + + test("drops a null member when the rest accepts anything", async () => { + const { schemas, problems } = await loosening.schemas({ + User: user, + State: state, + Union: { oneOf: [{ type: "string" }, { type: "null" }, reference("User")] } + }); + expect(schemas.Union).toStrictEqual({}); + expect(problems).toStrictEqual([]); + }); + + test("keeps a reference that every member makes", async () => { + const { schemas, problems } = await loosening.schemas({ + State: state, + Union: { oneOf: [reference("State"), reference("State")] } + }); + expect(schemas.Union).toStrictEqual(reference("State")); + expect(problems).toStrictEqual([]); + }); + + test("writes a nullable reference the way openapi-generator reads one", async () => { + const { schemas, problems } = await loosening.schemas({ + State: state, + Union: { description: "u", anyOf: [reference("State"), { type: "null" }] } + }); + expect(schemas.Union).toStrictEqual({ description: "u", ...reference("State"), nullable: true }); + expect(problems).toStrictEqual([]); + }); + + test("leaves allOf alone", async () => { + const { schemas, problems } = await loosening.schemas({ + State: state, + Intersection: { allOf: [reference("State"), { description: "s" }] } + }); + expect(schemas.Intersection).toStrictEqual({ allOf: [reference("State"), { description: "s" }] }); + expect(problems).toStrictEqual([]); + }); +}); + +describe("null members", () => { + const state = { type: "string", enum: ["active", "offline"] }; + + test("keeps a union without null as it is", async () => { + const { schemas, problems } = await from31.schemas({ A: { oneOf: [{ type: "string" }, { type: "integer" }] } }); + expect(schemas).toStrictEqual({ A: { oneOf: [{ type: "string" }, { type: "integer" }] } }); + expect(problems).toStrictEqual([]); + }); + + test("turns a null member beside one other into nullable", async () => { + const { schemas, problems } = await from31.schemas({ + A: { description: "a", oneOf: [{ type: "string", minLength: 1 }, { type: "null" }] } + }); + expect(schemas).toStrictEqual({ A: { description: "a", type: "string", minLength: 1, nullable: true } }); + expect(problems).toStrictEqual([]); + }); + + test("makes one member of a union nullable, so null still matches exactly one", async () => { + const { schemas, problems } = await from31.schemas({ + State: state, + A: { anyOf: [{ type: "string" }, { type: "integer" }, { type: "null" }] }, + B: { oneOf: [{ type: "string" }, reference("State"), { type: "null" }] }, + C: { oneOf: [reference("State"), { type: "integer" }, { type: "null" }] } + }); + expect(schemas).toStrictEqual({ + State: state, + A: { anyOf: [{ type: "string", nullable: true }, { type: "integer" }] }, + B: { oneOf: [{ type: "string", nullable: true }, reference("State")] }, + C: { oneOf: [reference("State"), { type: "integer", nullable: true }] } + }); + expect(problems).toStrictEqual([]); + }); + + test("lets an anyOf member that already takes null stand for the null member", async () => { + const { schemas, problems } = await from31.schemas({ A: { anyOf: [{ type: ["string", "null"] }, { type: "integer" }, { type: "null" }] } }); + expect(schemas).toStrictEqual({ A: { anyOf: [{ type: "string", nullable: true }, { type: "integer" }] } }); + expect(problems).toStrictEqual([]); + }); + + test("writes a nullable reference the way openapi-generator reads one", async () => { + const other = { type: "integer" }; + const { schemas, problems } = await from31.schemas({ + State: state, + Other: other, + A: { description: "a", anyOf: [reference("State"), { type: "null" }] }, + B: { oneOf: [reference("State"), reference("Other"), { type: "null" }] } + }); + expect(schemas).toStrictEqual({ + State: state, + Other: other, + A: { description: "a", ...reference("State"), nullable: true }, + B: { oneOf: [{ ...reference("State"), nullable: true }, reference("Other")] } + }); + expect(problems).toStrictEqual([]); + }); + + test("reports a oneOf in which null already matches more than one member", async () => { + const { problems } = await from31.schemas({ C: { oneOf: [{ type: ["string", "null"] }, { type: "integer" }, { type: "null" }] } }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/C", message: "OpenAPI 3.0.4 cannot say this `oneOf`: `null` matches more than one member." } + ]); + }); +}); + +describe("schema keywords", () => { + test("turns a numeric exclusive bound into a boolean beside its limit", async () => { + const { schemas, problems } = await from31.schemas({ + A: { type: "integer", exclusiveMinimum: 3 }, + B: { type: "integer", exclusiveMaximum: 9, maximum: 20 }, + C: { type: "integer", exclusiveMinimum: 3, minimum: 5 }, + D: { type: "integer", exclusiveMinimum: 3, minimum: 3 } + }); + expect(schemas).toStrictEqual({ + A: { type: "integer", minimum: 3, exclusiveMinimum: true }, + B: { type: "integer", maximum: 9, exclusiveMaximum: true }, + C: { type: "integer", minimum: 5 }, + D: { type: "integer", minimum: 3, exclusiveMinimum: true } + }); + expect(problems).toStrictEqual([]); + }); + + test("leaves a boolean exclusive bound alone", async () => { + const { schemas, problems } = await from31.schemas({ A: { type: "integer", minimum: 3, exclusiveMinimum: true } }); + expect(schemas).toStrictEqual({ A: { type: "integer", minimum: 3, exclusiveMinimum: true } }); + expect(problems).toStrictEqual([]); + }); + + test("keeps the first of a schema's examples, and all of them in their registry extension", async () => { + const { schemas, problems } = await from31.schemas({ + A: { type: "string", examples: ["a", "b"] }, + B: { type: "string", example: "kept", examples: ["c"] }, + C: { type: "string", examples: [] } + }); + expect(schemas).toStrictEqual({ + A: { type: "string", example: "a", "x-jsonschema-examples": ["a", "b"] }, + B: { type: "string", example: "kept", "x-jsonschema-examples": ["c"] }, + C: { type: "string", "x-jsonschema-examples": [] } + }); + expect(problems).toStrictEqual([]); + }); + + test("turns const into a one-value enum", async () => { + const { schemas, problems } = await from31.schemas({ + A: { type: "boolean", const: false }, + B: { type: "string", const: "b", enum: ["a", "b"] } + }); + expect(schemas).toStrictEqual({ + A: { type: "boolean", enum: [false] }, + B: { type: "string", enum: ["b"] } + }); + expect(problems).toStrictEqual([]); + }); + + test("reports a const outside its enum", async () => { + const { problems } = await from31.schemas({ A: { type: "string", const: "c", enum: ["a", "b"] } }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/A/const", message: "OpenAPI 3.0.4 cannot express a `const` outside `enum`." } + ]); + }); + + test("turns content keywords into the formats 3.0 uses, keeping them in their registry extensions", async () => { + const { schemas } = await from31.schemas({ + A: { type: "string", contentEncoding: "base64" }, + B: { type: "string", contentMediaType: "application/octet-stream" }, + C: { type: "string", contentMediaType: "image/png", contentEncoding: "base64", contentSchema: { type: "object" } }, + E: { type: "string", format: "uri", contentEncoding: "base64" } + }); + expect(schemas).toStrictEqual({ + A: { type: "string", format: "byte", "x-jsonschema-contentEncoding": "base64" }, + B: { type: "string", format: "binary", "x-jsonschema-contentMediaType": "application/octet-stream" }, + C: { + type: "string", + format: "byte", + "x-jsonschema-contentMediaType": "image/png", + "x-jsonschema-contentEncoding": "base64", + "x-jsonschema-contentSchema": { type: "object" } + }, + E: { type: "string", format: "uri", "x-jsonschema-contentEncoding": "base64" } + }); + }); + + test("keeps an encoding 3.0 has no format for in its registry extension", async () => { + const { schemas, problems } = await from31.schemas({ A: { type: "string", contentEncoding: "base64url" } }); + expect(schemas).toStrictEqual({ A: { type: "string", "x-jsonschema-contentEncoding": "base64url" } }); + expect(problems).toStrictEqual([]); + }); + + test("turns boolean schemas into the objects 3.0 requires", async () => { + const { schemas, problems } = await from31.schemas({ + A: { type: "object", properties: { open: true, closed: false }, additionalProperties: false }, + B: { type: "array", items: false }, + C: { not: true, allOf: [true, { type: "string" }] } + }); + expect(schemas).toStrictEqual({ + A: { type: "object", properties: { open: {}, closed: { not: {} } }, additionalProperties: false }, + B: { type: "array", items: { not: {} } }, + C: { not: {}, allOf: [{}, { type: "string" }] } + }); + expect(problems).toStrictEqual([]); + }); + + test("gives an array without items any items", async () => { + const { schemas } = await from31.schemas({ A: { type: "array" }, B: { type: ["array", "null"] } }); + expect(schemas).toStrictEqual({ A: { type: "array", items: {} }, B: { type: "array", nullable: true, items: {} } }); + }); + + test("drops a nullable 3.1 does not read before writing its own", async () => { + const { schemas } = await from31.schemas({ A: { type: "string", nullable: true }, B: { type: ["string", "null"], nullable: false } }); + expect(schemas).toStrictEqual({ A: { type: "string" }, B: { type: "string", nullable: true } }); + }); + + test("rewrites the empty lists 3.0 forbids", async () => { + const { schemas } = await from31.schemas({ A: { type: "object", required: [] }, B: { type: "string", enum: [] } }); + expect(schemas).toStrictEqual({ A: { type: "object" }, B: { type: "string", not: {} } }); + }); + + test("reports schema rules 3.0 adds", async () => { + const { problems } = await from31.schemas({ + A: { type: "string", default: 1 }, + B: { type: ["string", "null"], default: null }, + C: { type: "integer", default: 1.5 }, + D: { type: "string", readOnly: true, writeOnly: true } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/A/default", message: "OpenAPI 3.0.4 requires `default` to match `type`." }, + { severity: "error", pointer: "#/components/schemas/C/default", message: "OpenAPI 3.0.4 requires `default` to match `type`." }, + { severity: "error", pointer: "#/components/schemas/D", message: "OpenAPI 3.0.4 forbids `readOnly` and `writeOnly` together." } + ]); + }); + + test("reports a reference that is not a JSON Pointer", async () => { + const { problems } = await from31.schemas({ + A: { $anchor: "a", type: "string" }, + B: { type: "object", properties: { a: { $ref: "#a" } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/B/properties/a", message: "OpenAPI 3.0.4 reads a `$ref` fragment only as a JSON Pointer." } + ]); + }); + + test("drops schema identifiers and comments, keeping $anchor as its registry extension", async () => { + const { schemas } = await from31.schemas({ + A: { + $schema: "https://json-schema.org/draft/2020-12/schema", + $vocabulary: { "https://json-schema.org/draft/2020-12/vocab/core": true }, + $id: "a", + id: "a", + $anchor: "a", + $dynamicAnchor: "a", + $recursiveAnchor: true, + $comment: "c", + type: "string" + } + }); + expect(schemas).toStrictEqual({ A: { type: "string", "x-jsonschema-$anchor": "a" } }); + }); + + test("writes the keywords the registry covers as x-jsonschema extensions, lowering the schemas inside them", async () => { + const { schemas, problems } = await from31.schemas({ + A: { + type: "object", + patternProperties: { "^x": { type: ["string", "null"] } }, + propertyNames: { maxLength: 3 }, + unevaluatedProperties: false, + dependentSchemas: { a: { required: ["b"] } } + }, + B: { type: "array", contains: { const: 1 }, minContains: 1, maxContains: 2 }, + C: { if: { type: "string" }, then: { minLength: 1 }, else: true } + }); + expect(schemas).toStrictEqual({ + A: { + type: "object", + "x-jsonschema-patternProperties": { "^x": { type: "string", nullable: true } }, + "x-jsonschema-propertyNames": { maxLength: 3 }, + "x-jsonschema-unevaluatedProperties": false, + "x-jsonschema-dependentSchemas": { a: { required: ["b"] } } + }, + B: { type: "array", items: {}, "x-jsonschema-contains": { enum: [1] }, "x-jsonschema-minContains": 1, "x-jsonschema-maxContains": 2 }, + C: { "x-jsonschema-if": { type: "string" }, "x-jsonschema-then": { minLength: 1 }, "x-jsonschema-else": {} } + }); + expect(problems).toStrictEqual([]); + }); + + test("reports keywords 3.0 does not have", async () => { + const { problems } = await from31.schemas({ + A: { type: "array", prefixItems: [{ type: "string" }] }, + C: { type: "object", definitions: { d: { type: "string" } }, dependencies: { a: ["b"] } }, + D: { $recursiveRef: "#" } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/A/prefixItems", message: "OpenAPI 3.0.4 has no `prefixItems`." }, + { severity: "error", pointer: "#/components/schemas/C/definitions", message: "OpenAPI 3.0.4 has no `definitions`." }, + { severity: "error", pointer: "#/components/schemas/C/dependencies", message: "OpenAPI 3.0.4 has no `dependencies`." }, + { severity: "error", pointer: "#/components/schemas/D/$recursiveRef", message: "OpenAPI 3.0.4 has no `$recursiveRef`." } + ]); + }); + + test("wraps a reference whose siblings constrain it", async () => { + const { schemas } = await from31.schemas({ + Name: { type: "string" }, + A: { $ref: "#/components/schemas/Name", minLength: 1, description: "a" } + }); + expect(schemas.A).toStrictEqual({ allOf: [reference("Name")], minLength: 1, description: "a" }); + }); + + test("leaves a reference with only annotations beside it", async () => { + const { schemas, problems } = await from31.schemas({ + Name: { type: "string" }, + A: { $ref: "#/components/schemas/Name", description: "a", deprecated: true, nullable: true } + }); + expect(schemas.A).toStrictEqual({ $ref: "#/components/schemas/Name", description: "a", deprecated: true, nullable: true }); + expect(problems).toStrictEqual([]); + }); +}); + +describe("document", () => { + test("writes the fields 3.0 lacks as registry extensions, and drops the rest", async () => { + const { document, problems } = await from31({ + jsonSchemaDialect: "https://spec.openapis.org/oas/3.1/dialect/base", + info: { title: "fixture", version: "1", summary: "s", license: { name: "MIT", identifier: "MIT" } }, + webhooks: { ping: { post: { responses: { 200: { description: "ok" } } } } } + }); + expect(document).toStrictEqual({ + openapi: "3.0.4", + info: { title: "fixture", version: "1", license: { name: "MIT", "x-oai-license-identifier": "MIT" } }, + "x-webhooks": { ping: { post: { responses: { 200: { description: "ok" } } } } }, + paths: {}, + components: {} + }); + expect(problems).toStrictEqual([]); + }); + + test("inlines path items from components", async () => { + const item = { get: { responses: { 200: { description: "ok" } } } }; + const { document } = await from31({ + paths: { "/a": { $ref: "#/components/pathItems/A" } }, + components: { pathItems: { A: item } } + }); + expect(document.paths).toStrictEqual({ "/a": item }); + expect(document.components).toStrictEqual({}); + }); + + test("gives a description without paths an empty one", async () => { + const { document } = await from31({ paths: undefined, components: { schemas: { A: { type: "string" } } } }); + expect(document.paths).toStrictEqual({}); + }); + + test("reports an operation without responses", async () => { + const { problems } = await from31({ paths: { "/a": { get: { summary: "a" } } } }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/get", message: "OpenAPI 3.0.4 requires `responses`." } + ]); + }); + + test("reports mutual TLS", async () => { + const { problems } = await from31({ components: { securitySchemes: { tls: { type: "mutualTLS" } } } }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/securitySchemes/tls/type", message: "OpenAPI 3.0.4 has no `type: mutualTLS`." } + ]); + }); +}); + +describe("paths and operations", () => { + const ok = { 200: { description: "ok" } }; + const id = { name: "id", in: "path", required: true, schema: { type: "string" } }; + + test("drops an empty path item whose template has no parameter", async () => { + const { document } = await from31({ + paths: { "/a/{id}": { summary: "a" }, "/b/{id}": { parameters: [id] }, "/c": { get: { responses: ok } } } + }); + expect(document.paths).toStrictEqual({ "/b/{id}": { parameters: [id] }, "/c": { get: { responses: ok } } }); + }); + + test("reports what a 3.0 reader ignores", async () => { + const { problems } = await from31({ + security: [{ key: ["admin"] }], + paths: { "/a": { get: { requestBody: { content: { "application/json": {} } }, responses: ok } } }, + components: { securitySchemes: { key: { type: "apiKey", in: "header", name: "key" } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/security/0/key", message: "OpenAPI 3.0.4 lists roles only for `oauth2` and `openIdConnect` schemes." }, + { severity: "error", pointer: "#/paths/~1a/get/requestBody", message: "OpenAPI 3.0.4 ignores `requestBody` on `get`." } + ]); + }); + + test("reports a link to an operation 3.0 does not have", async () => { + const { problems } = await from31({ + webhooks: { ping: { post: { operationId: "ping", responses: ok } } }, + paths: { "/a": { get: { responses: { 200: { description: "ok", links: { ping: { operationRef: "#/webhooks/ping/post" } } } } } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/get/responses/200/links/ping/operationRef", message: "OpenAPI 3.0.4 has no `webhooks` for this to point into." } + ]); + }); + + test("reports a relative URL, which 3.0 resolves against a different base", async () => { + const { problems } = await from31({ + info: { title: "fixture", version: "1", termsOfService: "/terms", contact: { url: "https://example.com" } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/info/termsOfService", message: "OpenAPI 3.0.4 resolves a relative URL against a different base." } + ]); + }); +}); + +describe("multipart", () => { + const body = (schema: Record, encoding?: Record) => ({ + paths: { "/a": { post: { requestBody: { content: { "multipart/form-data": { schema, ...(encoding && { encoding }) } } }, responses: { 200: { description: "ok" } } } } } + }); + const media = (document: Record) => document.paths["/a"].post.requestBody.content["multipart/form-data"]; + + test("types a part that 3.1 sends as octets", async () => { + const { document } = await from31(body({ type: "object", properties: { file: {}, files: { type: "array", items: {} }, note: { type: "string" } } })); + expect(media(document).schema).toStrictEqual({ + type: "object", + properties: { + file: { type: "string", format: "binary" }, + files: { type: "array", items: { type: "string", format: "binary" } }, + note: { type: "string" } + } + }); + }); + + test("reports serialization fields 3.0 ignores in multipart", async () => { + const { problems } = await from31(body({ type: "object", properties: { tags: { type: "array", items: { type: "string" } } } }, { tags: { style: "form", explode: true } })); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/post/requestBody/content/multipart~1form-data/encoding/tags/style", message: "OpenAPI 3.0.4 ignores `style` in multipart." }, + { severity: "error", pointer: "#/paths/~1a/post/requestBody/content/multipart~1form-data/encoding/tags/explode", message: "OpenAPI 3.0.4 ignores `explode` in multipart." } + ]); + }); +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/drop-empty-path-items.ts b/packages/redocly-plugin-downlevel/src/3.1.0/drop-empty-path-items.ts new file mode 100644 index 00000000..509c9ceb --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/drop-empty-path-items.ts @@ -0,0 +1,27 @@ +import type { Node, Transform } from "../layer.ts"; + +const methods = ["get", "put", "post", "delete", "options", "head", "patch", "trace"]; + +/** + * 3.1 excuses a path item with no operations from declaring its template's path + * parameters; 3.0 requires every template expression to have one. Such a path + * item describes nothing a client can call, so it goes. + * + * https://spec.openapis.org/oas/v3.1.1#path-templating + */ +export const dropEmptyPathItems: Transform = () => ({ + Paths: { + leave: (paths) => { + for (const [path, item] of Object.entries(paths as Record)) { + if (!item || typeof item !== "object" || item.$ref !== undefined) continue; + if (methods.some((method) => item[method] !== undefined)) continue; + + const declared = new Set( + ((item.parameters ?? []) as Array).filter((parameter) => parameter.in === "path").map((parameter) => parameter.name) + ); + const templated = [...path.matchAll(/\{([^}]+)\}/g)].map(([, name]) => name); + if (templated.some((name) => !declared.has(name))) delete (paths as Record)[path]; + } + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/index.ts b/packages/redocly-plugin-downlevel/src/3.1.0/index.ts new file mode 100644 index 00000000..b7148f6c --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/index.ts @@ -0,0 +1,95 @@ +import { Oas3_1Types } from "@redocly/openapi-core"; + +import { dropFields } from "../builders/drop-fields.ts"; +import { extendFields } from "../builders/extend-fields.ts"; +import { inlineComponents } from "../builders/inline-components.ts"; +import { reportFields } from "../builders/report-fields.ts"; +import type { Layer } from "../layer.ts"; +import { reportRelativeUrls } from "../transforms/report-relative-urls.ts"; +import { dropEmptyPathItems } from "./drop-empty-path-items.ts"; +import { loosenUnions } from "./loosen-unions.ts"; +import { lowerBooleanSchemas } from "./lower-boolean-schemas.ts"; +import { lowerBounds } from "./lower-bounds.ts"; +import { lowerConst } from "./lower-const.ts"; +import { lowerContent } from "./lower-content.ts"; +import { lowerMultipart } from "./lower-multipart.ts"; +import { lowerNullMembers } from "./lower-null-members.ts"; +import { lowerSchemaExamples } from "./lower-schema-examples.ts"; +import { lowerSchemaRules } from "./lower-schema-rules.ts"; +import { lowerTypes } from "./lower-types.ts"; +import { reportOperations } from "./report-operations.ts"; +import { reportPlainNames } from "./report-plain-names.ts"; +import { requireFields } from "./require-fields.ts"; +import { splitTypes } from "./split-types.ts"; +import { wrapReferenceSiblings } from "./wrap-reference-siblings.ts"; + +/** + * https://spec.openapis.org/oas/v3.0.4.html + * https://learn.openapis.org/upgrading/v3.0-to-v3.1.html + */ +export const layer: Layer = { + version: "3.1.0", + writes: "3.0.4", + types: Oas3_1Types, + specVersion: "oas3_1", + checks: [ + reportFields({ + Schema: { + prefixItems: true, + dependentRequired: true, + dependencies: true, + unevaluatedItems: true, + $dynamicRef: true, + $recursiveRef: true, + $defs: true, + definitions: true + }, + SecurityScheme: { type: ["mutualTLS"] } + }), + reportPlainNames, + reportOperations, + reportRelativeUrls + ], + transforms: [ + lowerBooleanSchemas, + wrapReferenceSiblings, + dropFields({ Schema: ["nullable"] }), + splitTypes, + loosenUnions, + lowerNullMembers, + lowerTypes, + lowerBounds, + lowerSchemaExamples, + lowerConst, + lowerContent, + lowerSchemaRules, + lowerMultipart, + inlineComponents("pathItems"), + extendFields({ + Root: { webhooks: ["x-webhooks"] }, + License: { identifier: ["x-oai-license-identifier"] }, + Schema: Object.fromEntries( + [ + "$anchor", + "contains", + "minContains", + "maxContains", + "if", + "then", + "else", + "dependentSchemas", + "patternProperties", + "propertyNames", + "unevaluatedProperties" + ].map((keyword) => [keyword, [`x-jsonschema-${keyword}`]]) + ) + }), + dropFields({ + Root: ["jsonSchemaDialect"], + Info: ["summary"], + Schema: ["$schema", "$vocabulary", "$id", "id", "$dynamicAnchor", "$recursiveAnchor", "$comment"] + }), + dropEmptyPathItems, + requireFields + ] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/loosen-unions.ts b/packages/redocly-plugin-downlevel/src/3.1.0/loosen-unions.ts new file mode 100644 index 00000000..e62c48c5 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/loosen-unions.ts @@ -0,0 +1,216 @@ +import { isDeepStrictEqual } from "node:util"; + +import type { Node, Transform } from "../layer.ts"; +import { resolveSchema } from "../pointer.ts"; + +const unions = ["oneOf", "anyOf"] as const; +const merged = new Set(["type", "properties", "required", "items", "enum", "discriminator"]); +const enumeration = new Set(["const", "title", "description", "deprecated"]); + +/** + * https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.txt + * sections 6.2 to 6.5 + */ +const rules: Record> = { + multipleOf: ["number", "integer"], + maximum: ["number", "integer"], + exclusiveMaximum: ["number", "integer"], + minimum: ["number", "integer"], + exclusiveMinimum: ["number", "integer"], + maxLength: ["string"], + minLength: ["string"], + pattern: ["string"], + maxItems: ["array"], + minItems: ["array"], + uniqueItems: ["array"], + maxProperties: ["object"], + minProperties: ["object"] +}; + +/** + * Replaces every `oneOf` and `anyOf` with one schema that accepts everything any + * member accepts, for readers that take no unions. + * + * Members of one type merge, each with what it reaches through `allOf` folded + * in and its own declaration of a property winning over its parts': an object + * carries every member's properties and requires only what every member + * requires, an array loosens its items, and a keyword survives when every + * member gives it the same value. Members of different types leave `{}`. A `null` member makes the result nullable; a + * reference is made nullable with `nullable: true` beside the `$ref`, the form + * openapi-generator reads, as `lowerNullMembers` explains. + * + * Members that each allow only listed values, by `enum` or `const`, become one + * `enum`, the way openapi-generator's `SIMPLIFY_ONEOF_ANYOF_ENUM` rule reads such + * a union: a single value's `title` and `description` go to + * `x-enum-descriptions`, and its `deprecated` to `x-enum-deprecated`, so a + * generator reading the lowered union builds what it builds from the union. + * + * Runs only with `loosenUnions`; otherwise `lowerNullMembers` deals with the + * `null` members and the unions stay. + * + * https://github.com/OpenAPITools/openapi-generator/blob/v7.24.0/modules/openapi-generator/src/main/java/org/openapitools/codegen/OpenAPINormalizer.java#L1644 + * + * A size or value rule written beside the union stays only where the loosened + * schema has a type it constrains. Left on a schema of no type, generators read + * it as a rule for a type the schema never declared. + */ +export const loosenUnions: Transform = ({ loosenUnions: enabled }) => { + if (!enabled) return {}; + + let root: Node; + const resolve = (schema: Node): Node => resolveSchema(root, schema); + + const flatten = (member: Node): Array => { + const resolved = resolve(member); + const union = unions.map((keyword) => resolved[keyword]).find(Array.isArray) as Array | undefined; + return union ? union.flatMap(flatten) : [member]; + }; + + const compose = (schema: Node): Node => { + if (!Array.isArray(schema.allOf)) return schema; + + const { allOf, ...own } = schema; + const parts = [...(allOf as Array).map((part) => compose(resolve(part))), own]; + const result: Node = Object.assign({}, ...parts); + + const properties = Object.assign({}, ...parts.map((part) => part.properties ?? {})); + if (Object.keys(properties).length > 0) result.properties = properties; + + const required = [...new Set(parts.flatMap((part) => (part.required ?? []) as Array))]; + if (required.length > 0) result.required = required; + + return result; + }; + + const typesOf = (schema: Node): Array | undefined => + schema.type === undefined ? undefined : [schema.type].flat() as Array; + + const valuesOf = (schema: Node): Array | undefined => + Array.isArray(schema.enum) ? schema.enum : "const" in schema ? [schema.const] : undefined; + + const enumerate = (schemas: Array, typeSets: Array | undefined>, nullable: boolean): Node | undefined => { + const lists = schemas.map(valuesOf); + if (lists.includes(undefined)) return; + + const declared = typeSets.filter((types) => types !== undefined); + if (declared.some((types) => types.length !== 1 || types[0] !== declared[0][0])) return; + const type = declared[0]?.[0]; + if (nullable && !type) return; + + const entries: Array<{ value: unknown; description: string; deprecated: boolean }> = []; + schemas.forEach((schema, index) => { + const values = lists[index]!; + const description = values.length === 1 ? [schema.title, schema.description].filter((part) => typeof part === "string" && part !== "").join(" - ") : ""; + for (const value of values) { + const entry = { value, description, deprecated: schema.deprecated === true }; + const existing = entries.findIndex((other) => isDeepStrictEqual(other.value, value)); + if (existing === -1) entries.push(entry); + else entries[existing] = entry; + } + }); + + const result: Node = {}; + if (type) result.type = nullable ? [type, "null"] : type; + for (const [key, value] of Object.entries(schemas[0])) + if (!merged.has(key) && !enumeration.has(key) && schemas.every((schema) => key in schema && isDeepStrictEqual(schema[key], value))) + result[key] = structuredClone(value); + result.enum = entries.map((entry) => structuredClone(entry.value)); + if (entries.some((entry) => entry.description !== "")) result["x-enum-descriptions"] = entries.map((entry) => entry.description); + if (entries.some((entry) => entry.deprecated)) result["x-enum-deprecated"] = entries.map((entry) => entry.deprecated); + return result; + }; + + const loosen = (members: Array): Node => { + let nullable = false; + const concrete: Array = []; + + for (const member of members.flatMap(flatten)) { + const types = typesOf(resolve(member)); + if (types?.includes("null")) nullable = true; + if (types?.every((type) => type === "null")) continue; + if (!concrete.some((other) => isDeepStrictEqual(other, member))) concrete.push(member); + } + + if (concrete.length === 0) return { type: "null" }; + + if (concrete.length === 1) { + const [member] = concrete; + if (member.$ref !== undefined) return nullable ? { ...structuredClone(member), nullable: true } : structuredClone(member); + + const result = structuredClone(member); + const types = typesOf(result); + if (nullable && types && !types.includes("null")) result.type = [...types, "null"]; + return result; + } + + const schemas = concrete.map((member) => compose(resolve(member))); + const typeSets = schemas.map((schema) => typesOf(schema)?.filter((type) => type !== "null")); + + const enumerated = enumerate(schemas, typeSets, nullable); + if (enumerated) return enumerated; + + const [type] = typeSets[0] ?? []; + if (!type || typeSets.some((types) => types?.length !== 1 || types[0] !== type)) return {}; + + const result: Node = { type: nullable ? [type, "null"] : type }; + + for (const [key, value] of Object.entries(schemas[0])) { + if (merged.has(key)) continue; + if (schemas.every((schema) => key in schema && isDeepStrictEqual(schema[key], value))) + result[key] = structuredClone(value); + } + + if (schemas.every((schema) => Array.isArray(schema.enum))) { + const values: Array = []; + for (const value of schemas.flatMap((schema) => schema.enum as Array)) + if (!values.some((other) => isDeepStrictEqual(other, value))) values.push(value); + result.enum = values; + } + + if (schemas.some((schema) => schema.properties)) { + const declared = new Map>(); + for (const schema of schemas) + for (const [name, property] of Object.entries((schema.properties ?? {}) as Record)) + declared.set(name, [...(declared.get(name) ?? []), property]); + + const properties: Record = {}; + for (const [name, declarations] of declared) properties[name] = loosen(declarations); + result.properties = properties; + } + + const required = schemas + .map((schema) => (schema.required ?? []) as Array) + .reduce((left, right) => left.filter((name) => right.includes(name))); + if (required.length > 0) result.required = required; + + if (schemas.every((schema) => schema.items)) { + result.items = loosen(schemas.map((schema) => schema.items as Node)); + } + + return result; + }; + + return { + Root: { + enter: (document) => { + root = document; + } + }, + Schema: { + leave: (node) => { + const keyword = unions.find((candidate) => Array.isArray(node[candidate])); + if (!keyword) return; + + const result = loosen(node[keyword] as Array); + + const types = typesOf(resolve(result)) ?? []; + const applies = (key: string) => !(key in rules) || rules[key].some((type) => types.includes(type)); + const own = Object.fromEntries( + Object.entries(node).filter(([key]) => !unions.includes(key as never) && key !== "discriminator" && applies(key)) + ); + for (const key of Object.keys(node)) delete node[key]; + Object.assign(node, result, own); + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-boolean-schemas.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-boolean-schemas.ts new file mode 100644 index 00000000..6561637e --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-boolean-schemas.ts @@ -0,0 +1,42 @@ +import type { Node, Transform } from "../layer.ts"; + +const lower = (value: unknown) => (value === true ? {} : value === false ? { not: {} } : value); + +/** + * 3.1 lets `true` stand for the schema that accepts anything and `false` for the + * one that accepts nothing; 3.0 needs an object everywhere but + * `additionalProperties`. Redocly never hands a visitor a boolean, so each + * schema lowers the booleans it holds. + * + * https://spec.openapis.org/oas/v3.1.1#json-schema-keywords + */ +export const lowerBooleanSchemas: Transform = () => { + const lowerIn = (node: Node, keys: Array) => { + for (const key of keys) if (typeof node[key] === "boolean") node[key] = lower(node[key]); + }; + + const lowerSchema = (node: Node) => { + lowerIn(node, ["items", "not", "contains", "if", "then", "else", "propertyNames", "unevaluatedItems"]); + for (const keyword of ["allOf", "anyOf", "oneOf", "prefixItems"]) + if (Array.isArray(node[keyword])) node[keyword] = (node[keyword] as Array).map(lower); + for (const keyword of ["properties", "patternProperties", "dependentSchemas", "$defs"]) { + const map = node[keyword] as Node | undefined; + if (map && typeof map === "object") lowerIn(map, Object.keys(map)); + } + }; + + const lowerHolder = (holder: unknown) => lowerIn(holder as Node, ["schema"]); + + return { + Schema: { leave: lowerSchema }, + Parameter: { leave: lowerHolder }, + Header: { leave: lowerHolder }, + MediaType: { leave: lowerHolder }, + Components: { + leave: (components) => { + const schemas = components.schemas as Node | undefined; + if (schemas) lowerIn(schemas, Object.keys(schemas)); + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-bounds.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-bounds.ts new file mode 100644 index 00000000..9032e92b --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-bounds.ts @@ -0,0 +1,33 @@ +import type { Transform } from "../layer.ts"; + +const bounds = [ + { exclusive: "exclusiveMinimum", inclusive: "minimum", tighter: (limit: number, bound: number) => limit > bound }, + { exclusive: "exclusiveMaximum", inclusive: "maximum", tighter: (limit: number, bound: number) => limit < bound } +] as const; + +/** + * 3.1 writes an exclusive bound as a number of its own; 3.0 writes the number in + * `minimum` or `maximum` and marks it exclusive with a boolean. Where a schema + * has both, the tighter one survives. + * + * https://spec.openapis.org/oas/v3.0.3#properties + */ +export const lowerBounds: Transform = () => ({ + Schema: { + leave: (node) => { + for (const { exclusive, inclusive, tighter } of bounds) { + const bound = node[exclusive]; + if (typeof bound !== "number") continue; + + const limit = node[inclusive]; + if (typeof limit === "number" && tighter(limit, bound)) { + delete node[exclusive]; + continue; + } + + node[inclusive] = bound; + node[exclusive] = true; + } + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-const.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-const.ts new file mode 100644 index 00000000..4b7c8e5d --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-const.ts @@ -0,0 +1,21 @@ +import { isDeepStrictEqual } from "node:util"; + +import type { Transform } from "../layer.ts"; + +/** + * 3.0 has no `const`; an `enum` of one value says the same. + */ +export const lowerConst: Transform = ({ version }) => ({ + Schema: { + leave: (node, { report, location }) => { + if (!("const" in node)) return; + + const value = node.const; + if (Array.isArray(node.enum) && !node.enum.some((member) => isDeepStrictEqual(member, value))) + return report({ message: `OpenAPI ${version} cannot express a \`const\` outside \`enum\`.`, location: location.child("const") }); + + node.enum = [value]; + delete node.const; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-content.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-content.ts new file mode 100644 index 00000000..d432f345 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-content.ts @@ -0,0 +1,29 @@ +import type { Transform } from "../layer.ts"; + +const keywords = ["contentEncoding", "contentMediaType", "contentSchema"] as const; + +/** + * 3.1 describes encoded strings with the JSON Schema content keywords; 3.0 uses + * `format: byte` for base64 and `format: binary` for raw octets. A schema that + * already has a `format` keeps it. The keywords themselves, which are + * annotations in 3.1, go to their `x-jsonschema-*` extensions, so an encoding + * 3.0 has no format for survives too. + * + * https://spec.openapis.org/oas/v3.1.1#working-with-binary-data + * https://spec.openapis.org/oas/v3.0.3#data-types + * https://spec.openapis.org/registry/extension/x-jsonschema-contentEncoding.html + */ +export const lowerContent: Transform = () => ({ + Schema: { + leave: (node) => { + const format = node.contentEncoding === "base64" ? "byte" : node.contentMediaType === "application/octet-stream" ? "binary" : undefined; + if (format && !("format" in node)) node.format = format; + + for (const keyword of keywords) { + if (!(keyword in node)) continue; + node[`x-jsonschema-${keyword}`] ??= node[keyword]; + delete node[keyword]; + } + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-multipart.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-multipart.ts new file mode 100644 index 00000000..3e2138ed --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-multipart.ts @@ -0,0 +1,36 @@ +import type { Node, Transform } from "../layer.ts"; + +const constraining = ["type", "$ref", "allOf", "anyOf", "oneOf", "not", "enum", "const"]; +function typeless(schema: unknown) { + return !!schema && typeof schema === "object" && !constraining.some((keyword) => keyword in (schema as Node)); +} + +/** + * In multipart, 3.1 sends a part whose schema has no `type` as + * `application/octet-stream`; 3.0 bases that default on `format: binary`, and + * has no default for a part without a type. Such parts become binary strings. + * + * 3.0 also applies `style`, `explode` and `allowReserved` only to + * `application/x-www-form-urlencoded`, so in multipart they are reported. + * + * https://spec.openapis.org/oas/v3.1.1#encoding-object + * https://spec.openapis.org/oas/v3.0.3#encoding-object + */ +export const lowerMultipart: Transform = ({ version }) => ({ + MediaType: { + leave: (node, { report, location, key }) => { + if (!String(key).startsWith("multipart/")) return; + + const properties = (node.schema as Node | undefined)?.properties as Record | undefined; + for (const [name, property] of Object.entries(properties ?? {})) { + if (typeless(property)) properties![name] = { ...property, type: "string", format: "binary" }; + else if (property.type === "array" && typeless(property.items)) property.items = { ...(property.items as Node), type: "string", format: "binary" }; + } + + for (const [name, encoding] of Object.entries((node.encoding ?? {}) as Record)) + for (const field of ["style", "explode", "allowReserved"]) + if (field in encoding) + report({ message: `OpenAPI ${version} ignores \`${field}\` in multipart.`, location: location.child(["encoding", name, field]) }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-null-members.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-null-members.ts new file mode 100644 index 00000000..afc75e71 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-null-members.ts @@ -0,0 +1,81 @@ +import type { Node, Transform } from "../layer.ts"; +import { resolveSchema } from "../pointer.ts"; + +const unions = ["oneOf", "anyOf"] as const; + +const typesOf = (schema: Node) => (schema.type === undefined ? undefined : ([schema.type].flat() as Array)); +const isNull = (schema: Node) => typesOf(schema)?.every((type) => type === "null") === true; +const acceptsNull = (schema: Node) => typesOf(schema)?.includes("null") ?? true; + +/** + * 3.1 makes a union nullable with a `{type: "null"}` member; 3.0 has only + * `nullable`, which widens the `type` beside it. The `null` member goes, and + * one other member takes `null` instead: the first one written inline with a + * `type`, so a `oneOf` still finds exactly one match for `null`. A union left + * with one member becomes that member. + * + * Where another member already takes `null`, an `anyOf` needs nothing more, + * and a `oneOf` rejected `null` all along, since it matched twice; 3.0 cannot + * say that, so it is reported. A member without a `type` counts as taking + * `null`. + * + * A reference has no `type` to widen, so `nullable: true` goes beside the + * `$ref`. 3.0 says keywords beside a `$ref` are ignored, but openapi-generator + * reads that pair as a nullable reference, and writes it itself when it + * simplifies the same union. + * + * Runs unless `loosenUnions` is set, in which case the unions go altogether. + * + * https://spec.openapis.org/oas/v3.0.3#fixed-fields-19 + * https://github.com/OpenAPITools/openapi-generator/blob/v7.25.0/modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/ModelUtils.java#L2597-L2625 + */ +export const lowerNullMembers: Transform = ({ version, loosenUnions }) => { + if (loosenUnions) return {}; + + let root: Node; + + return { + Root: { + enter: (document) => { + root = document; + } + }, + Schema: { + leave: (node, { report, location }) => { + const keyword = unions.find((candidate) => Array.isArray(node[candidate])); + if (!keyword) return; + + const members = node[keyword] as Array; + const rest = members.filter((member) => !isNull(resolveSchema(root, member))); + if (rest.length === members.length) return; + + const addNull = (member: Node) => { + const types = typesOf(member); + if (member.$ref !== undefined) member.nullable = true; + else if (types && !types.includes("null")) member.type = [...types, "null"]; + }; + + if (rest.length === 1) { + const [member] = rest; + delete node[keyword]; + const own = { ...node }; + for (const key of Object.keys(node)) delete node[key]; + Object.assign(node, member, own); + addNull(node); + return; + } + + if (rest.some((member) => acceptsNull(resolveSchema(root, member)))) { + if (keyword === "oneOf") + return report({ message: `OpenAPI ${version} cannot say this \`oneOf\`: \`null\` matches more than one member.`, location }); + node[keyword] = rest; + return; + } + + const target = rest.find((member) => member.$ref === undefined && typesOf(member) !== undefined) ?? rest.find((member) => member.$ref !== undefined)!; + addNull(target); + node[keyword] = rest; + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-schema-examples.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-schema-examples.ts new file mode 100644 index 00000000..a004cad2 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-schema-examples.ts @@ -0,0 +1,20 @@ +import type { Transform } from "../layer.ts"; + +/** + * A 3.0 schema has one `example` where a 3.1 schema has a list of `examples`. + * The first survives unless the schema already has an `example`, and the whole + * list goes to `x-jsonschema-examples`. + * + * https://spec.openapis.org/registry/extension/x-jsonschema-examples.html + */ +export const lowerSchemaExamples: Transform = () => ({ + Schema: { + leave: (node) => { + if (!Array.isArray(node.examples)) return; + + if (node.examples.length > 0 && !("example" in node)) node.example = node.examples[0]; + node["x-jsonschema-examples"] ??= node.examples; + delete node.examples; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-schema-rules.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-schema-rules.ts new file mode 100644 index 00000000..327137af --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-schema-rules.ts @@ -0,0 +1,42 @@ +import type { Transform } from "../layer.ts"; + +const matches: Record boolean> = { + string: (value) => typeof value === "string", + number: (value) => typeof value === "number", + integer: (value) => Number.isInteger(value), + boolean: (value) => typeof value === "boolean", + array: (value) => Array.isArray(value), + object: (value) => typeof value === "object" && value !== null && !Array.isArray(value) +}; + +/** + * The rules 3.0 puts on a schema that 3.1 does not. + * + * - `items` must be present when `type` is `array`; `{}` is what its absence + * meant. + * - `required` and `enum` need at least one entry. An empty `required` requires + * nothing, and an empty `enum` accepts nothing, which `not: {}` says. + * - `default` must match `type`, and `readOnly` and `writeOnly` cannot both be + * true; neither has a 3.0 form, so both are reported. + * + * https://spec.openapis.org/oas/v3.0.3#properties + */ +export const lowerSchemaRules: Transform = ({ version }) => ({ + Schema: { + leave: (node, { report, location }) => { + if (node.type === "array" && node.items === undefined) node.items = {}; + if (Array.isArray(node.required) && node.required.length === 0) delete node.required; + if (Array.isArray(node.enum) && node.enum.length === 0) { + delete node.enum; + node.not = {}; + } + + const accepts = typeof node.type === "string" ? matches[node.type] : undefined; + if (accepts && "default" in node && !accepts(node.default) && !(node.default === null && node.nullable === true)) + report({ message: `OpenAPI ${version} requires \`default\` to match \`type\`.`, location: location.child("default") }); + + if (node.readOnly === true && node.writeOnly === true) + report({ message: `OpenAPI ${version} forbids \`readOnly\` and \`writeOnly\` together.`, location }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/lower-types.ts b/packages/redocly-plugin-downlevel/src/3.1.0/lower-types.ts new file mode 100644 index 00000000..ff8e0d4b --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/lower-types.ts @@ -0,0 +1,23 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.1 writes a nullable value as a type pair with `"null"`; 3.0 writes the other + * type and `nullable: true`. `null` on its own has no 3.0 form and is reported. + * Runs after `splitTypes` and `loosenUnions`, so no `type` names more than one + * type besides `null`. + * + * https://spec.openapis.org/oas/v3.0.3#fixed-fields-19 + */ +export const lowerTypes: Transform = ({ version }) => ({ + Schema: { + leave: (schema, { report, location }) => { + const types = [schema.type].flat(); + if (!types.includes("null")) return; + + const [other] = types.filter((type) => type !== "null"); + if (!other) return report({ message: `OpenAPI ${version} has no \`null\` type.`, location: location.child("type") }); + + Object.assign(schema, { type: other, nullable: true }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/report-operations.ts b/packages/redocly-plugin-downlevel/src/3.1.0/report-operations.ts new file mode 100644 index 00000000..5b825d03 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/report-operations.ts @@ -0,0 +1,58 @@ +import type { Node, Transform } from "../layer.ts"; +import { resolvePointer } from "../pointer.ts"; + +const bodiless = new Set(["get", "head", "delete"]); +const scoped = new Set(["oauth2", "openIdConnect"]); + +/** + * What a 3.0 reader of an operation ignores or cannot find. + * + * - A `requestBody` on GET, HEAD or DELETE, which 3.0 says "SHALL be ignored". + * - Roles in a security requirement for a scheme other than OAuth 2 or OpenID + * Connect, whose list 3.0 says "MUST be empty". + * - A link's `operationRef` into `webhooks` or `components.pathItems`, which 3.0 + * does not have. + * + * https://spec.openapis.org/oas/v3.0.3#operation-object + * https://spec.openapis.org/oas/v3.0.3#security-requirement-object + */ +export const reportOperations: Transform = ({ version }) => { + let root: Node; + + return { + Root: { + enter: (document) => { + root = document; + } + }, + Operation: { + enter: (operation, { report, location, key }) => { + if (operation.requestBody !== undefined && bodiless.has(String(key))) + report({ message: `OpenAPI ${version} ignores \`requestBody\` on \`${String(key)}\`.`, location: location.child("requestBody") }); + } + }, + SecurityRequirement: { + enter: (requirement, { report, location }) => { + for (const [name, roles] of Object.entries(requirement)) { + const scheme = resolvePointer(root, `#/components/securitySchemes/${name.replaceAll("~", "~0").replaceAll("/", "~1")}`) as Node | undefined; + if (Array.isArray(roles) && roles.length > 0 && scheme && !scheme.$ref && !scoped.has(String(scheme.type))) + report({ message: `OpenAPI ${version} lists roles only for \`oauth2\` and \`openIdConnect\` schemes.`, location: location.child(name) }); + } + } + }, + Link: { + enter: (link, { report, location }) => { + const target = link.operationRef; + if (typeof target !== "string") return; + + const fragment = target.split("#")[1] ?? ""; + const removed = ["/webhooks/", "/components/pathItems/"].find((prefix) => fragment.startsWith(prefix)); + if (removed) + report({ + message: `OpenAPI ${version} has no \`${removed === "/webhooks/" ? "webhooks" : "components.pathItems"}\` for this to point into.`, + location: location.child("operationRef") + }); + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/report-plain-names.ts b/packages/redocly-plugin-downlevel/src/3.1.0/report-plain-names.ts new file mode 100644 index 00000000..73cd4145 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/report-plain-names.ts @@ -0,0 +1,18 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.1 resolves a `$ref` fragment that is not a JSON Pointer, such as `#name`, as + * the plain name of an `$anchor`; 3.0 follows JSON Reference, whose fragments + * are JSON Pointers, and has no anchors to find. + * + * https://spec.openapis.org/oas/v3.0.3#reference-object + */ +export const reportPlainNames: Transform = ({ version }) => ({ + ref: { + enter: (reference, { report, location }) => { + const fragment = String(reference.$ref).split("#")[1]; + if (fragment && !fragment.startsWith("/")) + report({ message: `OpenAPI ${version} reads a \`$ref\` fragment only as a JSON Pointer.`, location }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/require-fields.ts b/packages/redocly-plugin-downlevel/src/3.1.0/require-fields.ts new file mode 100644 index 00000000..83165f9b --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/require-fields.ts @@ -0,0 +1,21 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.1 made `paths` and an operation's `responses` optional. A description with + * no paths has an empty set of them; an operation with no responses has nothing + * 3.0 can put in their place, since its Responses Object needs at least one. + * + * https://spec.openapis.org/oas/v3.0.3#responses-object + */ +export const requireFields: Transform = ({ version }) => ({ + Root: { + leave: (root) => { + root.paths ??= {}; + } + }, + Operation: { + leave: (operation, { report, location }) => { + if (operation.responses === undefined) report({ message: `OpenAPI ${version} requires \`responses\`.`, location }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/split-types.ts b/packages/redocly-plugin-downlevel/src/3.1.0/split-types.ts new file mode 100644 index 00000000..c18c27df --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/split-types.ts @@ -0,0 +1,26 @@ +import type { Transform } from "../layer.ts"; + +/** + * A `type` naming several types accepts a value of any of them, which is the + * union `anyOf` spells out one member per type. Written that way, it loosens + * like any other union. A schema that already has a union keeps it, and the + * types join it through `allOf`. + * + * https://json-schema.org/draft/2020-12/json-schema-validation#section-6.1.1 + */ +export const splitTypes: Transform = () => ({ + Schema: { + leave: (node) => { + if (!Array.isArray(node.type)) return; + + const types = node.type as Array; + if (types.filter((type) => type !== "null").length < 2) return; + + const union = { anyOf: types.map((type) => ({ type })) }; + delete node.type; + + if (node.oneOf || node.anyOf) node.allOf = [...((node.allOf as Array | undefined) ?? []), union]; + else Object.assign(node, union); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.0/wrap-reference-siblings.ts b/packages/redocly-plugin-downlevel/src/3.1.0/wrap-reference-siblings.ts new file mode 100644 index 00000000..6076d370 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.0/wrap-reference-siblings.ts @@ -0,0 +1,28 @@ +import type { Transform } from "../layer.ts"; + +const annotations = new Set(["title", "description", "default", "deprecated", "readOnly", "writeOnly", "example", "externalDocs", "xml", "nullable"]); + +/** + * 3.1 applies the keywords written beside a `$ref`; 3.0 ignores them. Where one + * constrains the value, the reference moves into an `allOf` so the constraint + * still holds. Annotations alone stay beside the `$ref`, where 3.0 ignores them + * as it always has. + * + * Visits references rather than schemas: a schema visitor is handed what a + * reference resolves to, never the object the `$ref` is written in. + * + * https://spec.openapis.org/oas/v3.0.3#reference-object + */ +export const wrapReferenceSiblings: Transform = () => ({ + ref: { + leave: (node, { type }) => { + if (type.name !== "Schema") return; + + const siblings = Object.keys(node).filter((key) => key !== "$ref"); + if (siblings.every((key) => annotations.has(key))) return; + + node.allOf = [{ $ref: node.$ref }]; + delete node.$ref; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.1/downlevel.test.ts b/packages/redocly-plugin-downlevel/src/3.1.1/downlevel.test.ts new file mode 100644 index 00000000..333da334 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.1/downlevel.test.ts @@ -0,0 +1,83 @@ +import { describe, expect, test } from "bun:test"; + +import { layer, reference } from "../fixture.ts"; + +const from311 = layer("3.1.1", "3.1.0"); + +describe("3.1.1", () => { + test("spells out the JSON encoding of object properties in form bodies", async () => { + const { document } = await from311({ + paths: { + "/a": { + post: { + requestBody: { + content: { + "application/x-www-form-urlencoded": { + schema: { type: "object", properties: { filter: { type: "object" }, name: { type: "string" }, set: { type: "object" } } }, + encoding: { set: { contentType: "text/plain" } } + } + } + }, + responses: { 200: { description: "ok" } } + } + } + } + }); + expect(document.paths?.["/a"]).toStrictEqual({ + post: { + requestBody: { + content: { + "application/x-www-form-urlencoded": { + schema: { type: "object", properties: { filter: { type: "object" }, name: { type: "string" }, set: { type: "object" } } }, + encoding: { set: { contentType: "text/plain" }, filter: { contentType: "application/json" } } + } + } + }, + responses: { 200: { description: "ok" } } + } + }); + }); + + test("reads a form body and its properties through references", async () => { + const { document } = await from311({ + paths: { + "/a": { + post: { + requestBody: { content: { "application/x-www-form-urlencoded": { schema: reference("Form") } } }, + responses: { 200: { description: "ok" } } + } + } + }, + components: { + schemas: { + Form: { type: "object", properties: { filter: { type: "object" }, range: reference("Range"), name: { type: "string" } } }, + Range: { type: "object", properties: { from: { type: "integer" } } } + } + } + }); + expect(document.paths?.["/a"]).toStrictEqual({ + post: { + requestBody: { + content: { + "application/x-www-form-urlencoded": { + schema: reference("Form"), + encoding: { filter: { contentType: "application/json" }, range: { contentType: "application/json" } } + } + } + }, + responses: { 200: { description: "ok" } } + } + }); + }); + + test("reports what 3.1.0 reads differently", async () => { + const { problems } = await from311({ + externalDocs: { url: "docs" }, + components: { schemas: { A: { type: "string", xml: { namespace: "https://example.com/ns#a" } } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/externalDocs/url", message: "OpenAPI 3.1.0 resolves a relative URL against a different base." }, + { severity: "error", pointer: "#/components/schemas/A/xml/namespace", message: "OpenAPI 3.1.0 requires `namespace` to be an absolute URI, without a fragment." } + ]); + }); +}); diff --git a/packages/redocly-plugin-downlevel/src/3.1.1/index.ts b/packages/redocly-plugin-downlevel/src/3.1.1/index.ts new file mode 100644 index 00000000..db8fa2d9 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.1/index.ts @@ -0,0 +1,18 @@ +import { Oas3_1Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; +import { pinFormEncoding } from "../transforms/pin-form-encoding.ts"; +import { reportNamespaceFragments } from "../transforms/report-namespace-fragments.ts"; +import { reportRelativeUrls } from "../transforms/report-relative-urls.ts"; + +/** + * https://spec.openapis.org/oas/v3.1.0.html + */ +export const layer: Layer = { + version: "3.1.1", + writes: "3.1.0", + types: Oas3_1Types, + specVersion: "oas3_1", + checks: [reportRelativeUrls, reportNamespaceFragments], + transforms: [pinFormEncoding] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.1.2/index.ts b/packages/redocly-plugin-downlevel/src/3.1.2/index.ts new file mode 100644 index 00000000..9bd807a2 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.1.2/index.ts @@ -0,0 +1,15 @@ +import { Oas3_1Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; + +/** + * https://spec.openapis.org/oas/v3.1.1.html + */ +export const layer: Layer = { + version: "3.1.2", + writes: "3.1.1", + types: Oas3_1Types, + specVersion: "oas3_1", + checks: [], + transforms: [] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/describe-responses.ts b/packages/redocly-plugin-downlevel/src/3.2.0/describe-responses.ts new file mode 100644 index 00000000..e113c241 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/describe-responses.ts @@ -0,0 +1,15 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.2 made a response's `description` optional; 3.1 requires one. + * + * https://spec.openapis.org/oas/v3.2.0#response-object + * https://spec.openapis.org/oas/v3.1.2#response-object + */ +export const describeResponses: Transform = () => ({ + Response: { + leave: (response) => { + response.description ??= ""; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/downlevel.test.ts b/packages/redocly-plugin-downlevel/src/3.2.0/downlevel.test.ts new file mode 100644 index 00000000..f9360f51 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/downlevel.test.ts @@ -0,0 +1,505 @@ +import { describe, expect, test } from "bun:test"; + +import { layer } from "../fixture.ts"; + +const from32 = layer("3.2.0", "3.1.2"); + +const ok = { 200: { description: "ok" } }; + +describe("document", () => { + test("writes the fields 3.1 lacks as registry extensions, and drops the rest", async () => { + const { document, problems } = await from32({ + $self: "https://example.com/openapi.yaml", + servers: [{ url: "https://example.com", name: "production" }], + tags: [{ name: "a", summary: "A", kind: "nav" }, { name: "b", parent: "a" }], + paths: { "/a": { get: { responses: { 200: { description: "ok", summary: "OK" } } } } }, + components: { + securitySchemes: { key: { type: "apiKey", in: "header", name: "key", deprecated: true } }, + schemas: { + Pet: { + type: "object", + discriminator: { propertyName: "kind", defaultMapping: "#/components/schemas/Cat" }, + required: ["kind"], + properties: { kind: { type: "string" } } + }, + Cat: { type: "object" } + } + } + }); + expect(document).toStrictEqual({ + openapi: "3.1.2", + "x-oai-$self": "https://example.com/openapi.yaml", + info: { title: "fixture", version: "1" }, + servers: [{ url: "https://example.com", "x-oai-name": "production" }], + tags: [{ name: "a", "x-displayName": "A" }, { name: "b" }], + "x-tagGroups": [{ name: "A", tags: ["a", "b"] }], + paths: { "/a": { get: { responses: { 200: { description: "ok", "x-oai-summary": "OK", "x-summary": "OK" } } } } }, + components: { + securitySchemes: { key: { type: "apiKey", in: "header", name: "key", "x-oai-deprecated": true } }, + schemas: { + Pet: { type: "object", discriminator: { propertyName: "kind" }, required: ["kind"], properties: { kind: { type: "string" } } }, + Cat: { type: "object" } + } + } + }); + expect(problems).toStrictEqual([]); + }); + + test("gives a response without a description an empty one", async () => { + const { document } = await from32({ paths: { "/a": { get: { responses: { 200: {} } } } } }); + expect(document.paths).toStrictEqual({ "/a": { get: { responses: { 200: { description: "" } } } } }); + }); + + test("inlines media types from components", async () => { + const json = { schema: { type: "string" } }; + const { document } = await from32({ + paths: { "/a": { get: { responses: { 200: { description: "ok", content: { "application/json": { $ref: "#/components/mediaTypes/Json" } } } } } } }, + components: { mediaTypes: { Json: json } } + }); + expect(document.paths).toStrictEqual({ + "/a": { get: { responses: { 200: { description: "ok", content: { "application/json": json } } } } } + }); + expect(document.components).toStrictEqual({}); + }); +}); + +describe("tags", () => { + test("writes the guide's 3.2 tags as the extensions 3.1 renderers read", async () => { + const { document, problems } = await from32({ + tags: [ + { name: "products", summary: "Products", description: "All product operations", kind: "nav" }, + { name: "books", summary: "Books & Literature", parent: "products", kind: "nav" }, + { name: "cds", summary: "Music CDs", parent: "products", kind: "nav" }, + { name: "giftcards", summary: "Gift Cards", parent: "products", kind: "nav" }, + { name: "digital-delivery", summary: "Digital Delivery", kind: "badge" } + ], + paths: { "/giftcards": { get: { tags: ["giftcards", "digital-delivery"], responses: ok } } } + }); + expect(document.tags).toStrictEqual([ + { name: "products", "x-displayName": "Products", description: "All product operations" }, + { name: "books", "x-displayName": "Books & Literature" }, + { name: "cds", "x-displayName": "Music CDs" }, + { name: "giftcards", "x-displayName": "Gift Cards" }, + { name: "digital-delivery", "x-displayName": "Digital Delivery" } + ]); + expect(document["x-tagGroups"]).toStrictEqual([{ name: "Products", tags: ["products", "books", "cds", "giftcards"] }]); + expect(document.paths).toStrictEqual({ + "/giftcards": { get: { tags: ["giftcards", "digital-delivery"], "x-badges": [{ name: "Digital Delivery" }], responses: ok } } + }); + expect(problems).toStrictEqual([]); + }); + + test("groups every tag under its top-level tag, so none drops out of the navigation", async () => { + const { document } = await from32({ + tags: [{ name: "a" }, { name: "b", parent: "a" }, { name: "c", parent: "b" }, { name: "d", parent: "a" }, { name: "e" }] + }); + expect(document["x-tagGroups"]).toStrictEqual([ + { name: "a", tags: ["a", "b", "c", "d"] }, + { name: "e", tags: ["e"] } + ]); + }); + + test("keeps the extensions the description already has", async () => { + const groups = [{ name: "Mine", tags: ["b"] }]; + const { document } = await from32({ + tags: [{ name: "a", summary: "A", "x-displayName": "Kept" }, { name: "b", parent: "a" }, { name: "new", summary: "New", kind: "badge" }], + "x-tagGroups": groups, + paths: { "/a": { get: { tags: ["b", "new"], "x-badges": [{ name: "New" }, { name: "Beta" }], responses: ok } } } + }); + expect(document.tags).toStrictEqual([{ name: "a", "x-displayName": "Kept" }, { name: "b" }, { name: "new", "x-displayName": "New" }]); + expect(document["x-tagGroups"]).toStrictEqual(groups); + expect(document.paths).toStrictEqual({ "/a": { get: { tags: ["b", "new"], "x-badges": [{ name: "New" }, { name: "Beta" }], responses: ok } } }); + }); + + test("adds no tag groups where no tag has a parent", async () => { + const { document } = await from32({ tags: [{ name: "a", summary: "A" }] }); + expect(document).not.toHaveProperty("x-tagGroups"); + }); +}); + +describe("responses", () => { + test("writes a response summary as every extension that carries it", async () => { + const { document } = await from32({ + paths: { + "/a": { + get: { responses: { 200: { summary: "OK", description: "Found." }, 404: { summary: "Missing", description: "Gone.", "x-oai-summary": "Kept" } } } + } + } + }); + expect(document.paths).toStrictEqual({ + "/a": { get: { responses: { 200: { "x-oai-summary": "OK", "x-summary": "OK", description: "Found." }, 404: { description: "Gone.", "x-oai-summary": "Kept", "x-summary": "Missing" } } } } + }); + }); +}); + +describe("examples", () => { + test("turns dataValue and serializedValue into value, keeping the serialized form in its registry extension", async () => { + const { document } = await from32({ + components: { + examples: { + Data: { dataValue: { a: 1 } }, + Serialized: { serializedValue: "a=1" }, + Both: { dataValue: { a: 1 }, serializedValue: "a=1" } + } + } + }); + expect(document.components).toStrictEqual({ + examples: { + Data: { value: { a: 1 } }, + Serialized: { value: "a=1", "x-oai-serializedValue": "a=1" }, + Both: { value: { a: 1 }, "x-oai-serializedValue": "a=1" } + } + }); + }); +}); + +describe("xml", () => { + test("turns nodeType into the flags 3.1 uses", async () => { + const { document, problems } = await from32({ + components: { + schemas: { + Attribute: { type: "string", xml: { nodeType: "attribute" } }, + Wrapped: { type: "array", items: { type: "string" }, xml: { nodeType: "element", name: "list" } }, + Element: { type: "string", xml: { nodeType: "element" } }, + Unwrapped: { type: "array", items: { type: "string" }, xml: { nodeType: "none" } } + } + } + }); + expect(document.components?.schemas).toStrictEqual({ + Attribute: { type: "string", xml: { attribute: true } }, + Wrapped: { type: "array", items: { type: "string" }, xml: { wrapped: true, name: "list" } }, + Element: { type: "string", xml: {} }, + Unwrapped: { type: "array", items: { type: "string" }, xml: {} } + }); + expect(problems).toStrictEqual([]); + }); + + test("reports a node type 3.1 cannot express", async () => { + const { problems } = await from32({ + components: { schemas: { Text: { type: "string", xml: { nodeType: "text" } }, None: { type: "string", xml: { nodeType: "none" } } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/Text/xml/nodeType", message: "OpenAPI 3.1.2 has no `nodeType: text`." }, + { severity: "error", pointer: "#/components/schemas/None/xml/nodeType", message: "OpenAPI 3.1.2 has no `nodeType: none`." } + ]); + }); +}); + +describe("reports", () => { + test("reports what 3.1 cannot express", async () => { + const { problems } = await from32({ + paths: { + "/a": { + parameters: [ + { name: "q", in: "querystring", content: { "application/x-www-form-urlencoded": { schema: { type: "object" } } } }, + { name: "c", in: "cookie", style: "cookie", schema: { type: "string" } } + ] + } + } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/parameters/0/in", message: "OpenAPI 3.1.2 has no `in: querystring`." }, + { severity: "error", pointer: "#/paths/~1a/parameters/1/style", message: "OpenAPI 3.1.2 has no `style: cookie`." } + ]); + }); + + test("writes item schemas and encodings as their registry extensions", async () => { + const { document, problems } = await from32({ + paths: { + "/a": { + get: { responses: { 200: { description: "ok", content: { "application/jsonl": { itemSchema: { type: "object" } } } } } }, + post: { + requestBody: { + content: { + "multipart/mixed": { + itemSchema: { type: "string" }, + prefixEncoding: [{ contentType: "application/json" }], + itemEncoding: { contentType: "image/png" } + }, + "multipart/form-data": { + schema: { type: "object", properties: { part: { type: "string" } } }, + encoding: { part: { contentType: "multipart/mixed", encoding: { inner: { contentType: "text/plain" } }, itemEncoding: { contentType: "text/plain" } } } + } + } + }, + responses: ok + } + } + } + }); + expect(document.paths).toStrictEqual({ + "/a": { + get: { responses: { 200: { description: "ok", content: { "application/jsonl": { "x-oai-itemSchema": { type: "object" } } } } } }, + post: { + requestBody: { + content: { + "multipart/mixed": { + "x-oai-itemSchema": { type: "string" }, + "x-oai-prefixEncoding": [{ contentType: "application/json" }], + "x-oai-itemEncoding": { contentType: "image/png" } + }, + "multipart/form-data": { + schema: { type: "object", properties: { part: { type: "string" } } }, + encoding: { + part: { contentType: "multipart/mixed", "x-oai-encoding": { inner: { contentType: "text/plain" } }, "x-oai-itemEncoding": { contentType: "text/plain" } } + } + } + } + }, + responses: ok + } + } + }); + expect(problems).toStrictEqual([]); + }); + + test("writes QUERY and other methods as x-oai-additionalOperations", async () => { + const { document, problems } = await from32({ + paths: { + "/a": { + get: { responses: ok }, + query: { operationId: "search", responses: ok }, + additionalOperations: { COPY: { operationId: "copy", responses: ok } } + } + } + }); + expect(document.paths).toStrictEqual({ + "/a": { + get: { responses: ok }, + "x-oai-additionalOperations": { QUERY: { operationId: "search", responses: ok }, COPY: { operationId: "copy", responses: ok } } + } + }); + expect(problems).toStrictEqual([]); + }); + + test("keeps an operation x-oai-additionalOperations already holds", async () => { + const { document } = await from32({ + paths: { "/a": { query: { operationId: "new", responses: ok }, "x-oai-additionalOperations": { QUERY: { operationId: "kept", responses: ok } } } } + }); + expect(document.paths).toStrictEqual({ "/a": { "x-oai-additionalOperations": { QUERY: { operationId: "kept", responses: ok } } } }); + }); + + test("writes the device authorization flow as its registry extensions", async () => { + const { document, problems } = await from32({ + components: { + securitySchemes: { + device: { + type: "oauth2", + flows: { deviceAuthorization: { deviceAuthorizationUrl: "https://example.com/device", tokenUrl: "https://example.com/token", scopes: {} } } + } + } + } + }); + expect(document.components).toStrictEqual({ + securitySchemes: { + device: { + type: "oauth2", + flows: { + "x-oai-deviceAuthorization": { "x-oai-deviceAuthorizationUrl": "https://example.com/device", tokenUrl: "https://example.com/token", scopes: {} } + } + } + } + }); + expect(problems).toStrictEqual([]); + }); +}); + +describe("parameters", () => { + test("makes deepObject explode, the only way 3.1 defines it", async () => { + const { document } = await from32({ + paths: { + "/a": { + get: { + parameters: [ + { name: "filter", in: "query", style: "deepObject", schema: { type: "object" } }, + { name: "sort", in: "query", style: "deepObject", explode: false, schema: { type: "object" } } + ], + responses: ok + } + } + } + }); + expect(document.paths).toStrictEqual({ + "/a": { + get: { + parameters: [ + { name: "filter", in: "query", style: "deepObject", explode: true, schema: { type: "object" } }, + { name: "sort", in: "query", style: "deepObject", explode: true, schema: { type: "object" } } + ], + responses: ok + } + } + }); + }); + + test("moves examples beside content into the media type", async () => { + const { document, problems } = await from32({ + paths: { + "/a": { + get: { + parameters: [{ name: "q", in: "query", content: { "application/json": { schema: { type: "object" } } }, example: { a: 1 } }], + responses: { + 200: { + description: "ok", + headers: { "X-A": { content: { "text/plain": { schema: { type: "string" } } }, examples: { one: { value: "1" } } } } + } + } + } + } + } + }); + expect(document.paths).toStrictEqual({ + "/a": { + get: { + parameters: [{ name: "q", in: "query", content: { "application/json": { schema: { type: "object" }, example: { a: 1 } } } }], + responses: { + 200: { + description: "ok", + headers: { "X-A": { content: { "text/plain": { schema: { type: "string" }, examples: { one: { value: "1" } } } } } } + } + } + } + } + }); + expect(problems).toStrictEqual([]); + }); + + test("reports examples that collide with the media type's", async () => { + const { problems } = await from32({ + paths: { "/a": { get: { parameters: [{ name: "q", in: "query", content: { "application/json": { example: 2 } }, example: 1 }], responses: ok } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/get/parameters/0/example", message: "OpenAPI 3.1.2 has no room for `example` beside `content`: the media type has its own." } + ]); + }); + + test("reports allowReserved where 3.1 does not apply it", async () => { + const { problems } = await from32({ + paths: { + "/a/{id}": { + get: { + parameters: [ + { name: "id", in: "path", required: true, allowReserved: true, schema: { type: "string" } }, + { name: "q", in: "query", allowReserved: true, schema: { type: "string" } } + ], + responses: ok + } + } + } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a~1{id}/get/parameters/0/allowReserved", message: "OpenAPI 3.1.2 applies `allowReserved` only to `in: query`." } + ]); + }); +}); + +describe("security", () => { + test("names a scheme a requirement gives by URI", async () => { + const { document, problems } = await from32({ + security: [{ "#/components/securitySchemes/key": [] }, { key: [] }], + components: { securitySchemes: { key: { type: "apiKey", in: "header", name: "key" } } } + }); + expect(document.security).toStrictEqual([{ key: [] }, { key: [] }]); + expect(problems).toStrictEqual([]); + }); + + test("reports a URI that is not a scheme in this document", async () => { + const { problems } = await from32({ security: [{ "https://example.com/openapi.yaml#/components/securitySchemes/key": [] }] }); + expect(problems).toStrictEqual([ + { + severity: "error", + pointer: "#/security/0/https:~1~1example.com~1openapi.yaml#~1components~1securitySchemes~1key", + message: "OpenAPI 3.1.2 names a security scheme only by its name under `components`." + } + ]); + }); +}); + +describe("dialect", () => { + test("points the 3.2 dialect at the 3.1 one", async () => { + const { document } = await from32({ + jsonSchemaDialect: "https://spec.openapis.org/oas/3.2/dialect/2025-09-17", + components: { schemas: { A: { $schema: "https://spec.openapis.org/oas/3.2/dialect/2026-02-26", type: "string" } } } + }); + expect(document.jsonSchemaDialect).toBe("https://spec.openapis.org/oas/3.1/dialect/base"); + expect(document.components?.schemas).toStrictEqual({ A: { $schema: "https://spec.openapis.org/oas/3.1/dialect/base", type: "string" } }); + }); +}); + +describe("media types", () => { + const response = (media: string, value: Record) => ({ + paths: { "/a": { get: { responses: { 200: { description: "ok", content: { [media]: value } } } } } } + }); + + test("drops a media type description, which only the published schema allows", async () => { + const { document } = await from32(response("application/json", { description: "d", schema: { type: "object" } })); + expect(document.paths).toStrictEqual(response("application/json", { schema: { type: "object" } }).paths); + }); + + test("reports encoding outside a request body", async () => { + const { problems } = await from32(response("multipart/form-data", { schema: { type: "object", properties: { a: { type: "string" } } }, encoding: { a: { contentType: "text/plain" } } })); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/get/responses/200/content/multipart~1form-data/encoding", message: "OpenAPI 3.1.2 applies `encoding` only to request bodies." } + ]); + }); + + test("reports encoding for a property the schema does not have", async () => { + const { problems } = await from32({ + paths: { + "/a": { + post: { + requestBody: { content: { "multipart/form-data": { schema: { type: "object", properties: { a: { type: "string" } } }, encoding: { b: { contentType: "text/plain" } } } } }, + responses: ok + } + } + } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/post/requestBody/content/multipart~1form-data/encoding/b", message: "OpenAPI 3.1.2 requires `b` to be a property of the schema." } + ]); + }); + + test("reports what 3.2 gives meaning to and 3.1 does not", async () => { + const { problems } = await from32({ + paths: { + "/a": { + post: { requestBody: { content: { "multipart/form-data": { schema: { type: "array", items: { type: "string" } } } } }, responses: ok }, + get: { responses: { 200: { description: "ok", content: { "application/jsonl": { schema: { type: "array" } } } } } } + } + } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/get/responses/200/content/application~1jsonl/schema", message: "OpenAPI 3.1.2 gives `schema` no meaning for the sequential media type `application/jsonl`." }, + { severity: "error", pointer: "#/paths/~1a/post/requestBody/content/multipart~1form-data/schema", message: "OpenAPI 3.1.2 gives an array `schema` no meaning for `multipart/form-data`." } + ]); + }); +}); + +describe("schemas", () => { + test("reports a namespace 3.1 cannot hold", async () => { + const { problems } = await from32({ + components: { schemas: { Tagged: { type: "string", xml: { namespace: "https://example.com/ñ" } }, Plain: { type: "string", xml: { namespace: "https://example.com/n" } } } } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/components/schemas/Tagged/xml/namespace", message: "OpenAPI 3.1.2 requires `namespace` to be a URI, and this IRI is not one." } + ]); + }); +}); + +describe("defaults", () => { + test("drops allowReserved: false where 3.1 forbids the field", async () => { + const { document, problems } = await from32({ + paths: { "/a/{id}": { get: { parameters: [{ name: "id", in: "path", required: true, allowReserved: false, schema: { type: "string" } }], responses: ok } } } + }); + expect(document.paths).toStrictEqual({ + "/a/{id}": { get: { parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" } }], responses: ok } } + }); + expect(problems).toStrictEqual([]); + }); + + test("leaves a scheme name the description never declares to the linter", async () => { + const { document, problems } = await from32({ security: [{ undeclared: [] }] }); + expect(document.security).toStrictEqual([{ undeclared: [] }]); + expect(problems).toStrictEqual([]); + }); +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/drop-default-allow-reserved.ts b/packages/redocly-plugin-downlevel/src/3.2.0/drop-default-allow-reserved.ts new file mode 100644 index 00000000..5005bf65 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/drop-default-allow-reserved.ts @@ -0,0 +1,15 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.2 accepts `allowReserved` beyond `in: query`; 3.1 forbids it there. Its + * default, `false`, changes nothing wherever it is written, so it goes. + * + * https://spec.openapis.org/oas/v3.1.1#parameter-allow-reserved + */ +export const dropDefaultAllowReserved: Transform = () => ({ + Parameter: { + leave: (parameter) => { + if (parameter.in !== "query" && parameter.allowReserved === false) delete parameter.allowReserved; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/explode-deep-objects.ts b/packages/redocly-plugin-downlevel/src/3.2.0/explode-deep-objects.ts new file mode 100644 index 00000000..82ffaacb --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/explode-deep-objects.ts @@ -0,0 +1,18 @@ +import type { Node, Transform } from "../layer.ts"; + +function explode(node: Node) { + if (node.style === "deepObject") node.explode = true; +} + +/** + * 3.2 says `explode` has no effect on `deepObject`, whose one serialization is + * the exploded one. 3.1 defaults `explode` to `false` for it and calls that + * combination undefined, so `true` is written out. + * + * https://spec.openapis.org/oas/v3.2.0#parameter-explode + * https://spec.openapis.org/oas/v3.1.1#parameter-explode + */ +export const explodeDeepObjects: Transform = () => ({ + Parameter: { leave: explode }, + Encoding: { leave: explode } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/index.ts b/packages/redocly-plugin-downlevel/src/3.2.0/index.ts new file mode 100644 index 00000000..c7c6ec1d --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/index.ts @@ -0,0 +1,65 @@ +import { Oas3_2Types } from "@redocly/openapi-core"; + +import { dropFields } from "../builders/drop-fields.ts"; +import { extendFields } from "../builders/extend-fields.ts"; +import { inlineComponents } from "../builders/inline-components.ts"; +import { reportFields } from "../builders/report-fields.ts"; +import type { Layer } from "../layer.ts"; +import { describeResponses } from "./describe-responses.ts"; +import { dropDefaultAllowReserved } from "./drop-default-allow-reserved.ts"; +import { explodeDeepObjects } from "./explode-deep-objects.ts"; +import { lowerAdditionalOperations } from "./lower-additional-operations.ts"; +import { lowerDeviceAuthorization } from "./lower-device-authorization.ts"; +import { lowerDialect } from "./lower-dialect.ts"; +import { lowerExamples } from "./lower-examples.ts"; +import { lowerTags } from "./lower-tags.ts"; +import { lowerXml } from "./lower-xml.ts"; +import { moveContentExamples } from "./move-content-examples.ts"; +import { reportMeaning } from "./report-meaning.ts"; +import { resolveSecurityUris } from "./resolve-security-uris.ts"; + +/** + * https://spec.openapis.org/oas/v3.1.2.html + * https://learn.openapis.org/upgrading/v3.1-to-v3.2.html + */ +export const layer: Layer = { + version: "3.2.0", + writes: "3.1.2", + types: Oas3_2Types, + specVersion: "oas3_2", + checks: [ + reportFields({ + Parameter: { in: ["querystring"], style: ["cookie"] }, + Encoding: { prefixEncoding: true } + }), + reportMeaning + ], + transforms: [ + resolveSecurityUris, + lowerDialect, + explodeDeepObjects, + dropDefaultAllowReserved, + lowerXml, + lowerExamples, + moveContentExamples, + lowerTags, + lowerAdditionalOperations, + lowerDeviceAuthorization, + extendFields({ + Root: { $self: ["x-oai-$self"] }, + Server: { name: ["x-oai-name"] }, + Response: { summary: ["x-oai-summary", "x-summary"] }, + SecurityScheme: { deprecated: ["x-oai-deprecated"] }, + MediaType: { itemSchema: ["x-oai-itemSchema"], prefixEncoding: ["x-oai-prefixEncoding"], itemEncoding: ["x-oai-itemEncoding"] }, + Encoding: { encoding: ["x-oai-encoding"], itemEncoding: ["x-oai-itemEncoding"] } + }), + inlineComponents("mediaTypes"), + dropFields({ + Tag: ["summary", "parent", "kind"], + MediaType: ["description"], + SecurityScheme: ["oauth2MetadataUrl"], + Discriminator: ["defaultMapping"] + }), + describeResponses + ] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/lower-additional-operations.ts b/packages/redocly-plugin-downlevel/src/3.2.0/lower-additional-operations.ts new file mode 100644 index 00000000..d0542d2a --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/lower-additional-operations.ts @@ -0,0 +1,22 @@ +import type { Node, Transform } from "../layer.ts"; + +/** + * 3.2 gave path items a `query` operation and `additionalOperations` for any + * other method; 3.1 knows a fixed set of methods. Both move to + * `x-oai-additionalOperations`, keyed by method as 3.2's `additionalOperations` + * is, keeping any operation the extension already holds. + * + * https://spec.openapis.org/registry/extension/x-oai-additionalOperations.html + */ +export const lowerAdditionalOperations: Transform = () => ({ + PathItem: { + leave: (node) => { + const operations: Node = { ...(node.query ? { QUERY: node.query } : {}), ...((node.additionalOperations ?? {}) as Node) }; + if (Object.keys(operations).length === 0) return; + + node["x-oai-additionalOperations"] = { ...operations, ...((node["x-oai-additionalOperations"] ?? {}) as Node) }; + delete node.query; + delete node.additionalOperations; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/lower-device-authorization.ts b/packages/redocly-plugin-downlevel/src/3.2.0/lower-device-authorization.ts new file mode 100644 index 00000000..e99e87d5 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/lower-device-authorization.ts @@ -0,0 +1,25 @@ +import type { Node, Transform } from "../layer.ts"; + +/** + * 3.2 added the OAuth 2 device authorization flow; 3.1 has no field for it. The + * flow moves to `x-oai-deviceAuthorization`, and its `deviceAuthorizationUrl`, + * which no 3.1 flow has, to `x-oai-deviceAuthorizationUrl`. + * + * https://spec.openapis.org/registry/extension/x-oai-deviceAuthorization.html + * https://spec.openapis.org/registry/extension/x-oai-deviceAuthorizationUrl.html + */ +export const lowerDeviceAuthorization: Transform = () => ({ + OAuth2Flows: { + leave: (flows) => { + const flow = flows.deviceAuthorization as Node | undefined; + if (!flow) return; + + if ("deviceAuthorizationUrl" in flow) { + flow["x-oai-deviceAuthorizationUrl"] ??= flow.deviceAuthorizationUrl; + delete flow.deviceAuthorizationUrl; + } + flows["x-oai-deviceAuthorization"] ??= flow; + delete flows.deviceAuthorization; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/lower-dialect.ts b/packages/redocly-plugin-downlevel/src/3.2.0/lower-dialect.ts new file mode 100644 index 00000000..ad733e6b --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/lower-dialect.ts @@ -0,0 +1,21 @@ +import type { Transform } from "../layer.ts"; + +const dialect = "https://spec.openapis.org/oas/3.2/dialect/"; +const replacement = "https://spec.openapis.org/oas/3.1/dialect/base"; + +function lower(node: Record, field: string) { + const value = node[field]; + if (typeof value === "string" && value.startsWith(dialect)) node[field] = replacement; +} + +/** + * The 3.2 schema dialect differs from 3.1's only by the 3.2 keywords, which + * the other transforms in this layer lower, so a description naming it names + * the dialect every 3.1 tool must support instead. + * + * https://spec.openapis.org/oas/v3.1.1#json-schema-keywords + */ +export const lowerDialect: Transform = () => ({ + Root: { leave: (root) => lower(root, "jsonSchemaDialect") }, + Schema: { leave: (schema) => lower(schema, "$schema") } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/lower-examples.ts b/packages/redocly-plugin-downlevel/src/3.2.0/lower-examples.ts new file mode 100644 index 00000000..fd26917c --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/lower-examples.ts @@ -0,0 +1,23 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.2 splits an example's `value` into `dataValue`, the data, and + * `serializedValue`, its serialized form. 3.1 has only `value`, which takes the + * data where there is some and the serialized string otherwise; the serialized + * form also goes to `x-oai-serializedValue`, which keeps it apart from data. + * + * https://spec.openapis.org/oas/v3.2.0#example-object + * https://spec.openapis.org/registry/extension/x-oai-serializedValue.html + */ +export const lowerExamples: Transform = () => ({ + Example: { + leave: (node) => { + if ("dataValue" in node) node.value = node.dataValue; + else if ("serializedValue" in node) node.value = node.serializedValue; + if ("serializedValue" in node) node["x-oai-serializedValue"] ??= node.serializedValue; + + delete node.dataValue; + delete node.serializedValue; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/lower-tags.ts b/packages/redocly-plugin-downlevel/src/3.2.0/lower-tags.ts new file mode 100644 index 00000000..7a772b53 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/lower-tags.ts @@ -0,0 +1,62 @@ +import type { Node, Transform } from "../layer.ts"; + +/** + * 3.2 gave tags a `summary`, a `parent` and a `kind`; 3.1 renderers read the same + * things from extensions. A summary becomes the tag's `x-displayName`. A badge + * tag becomes an entry in the `x-badges` of each operation that carries it. The + * hierarchy becomes `x-tagGroups`, one group per top-level tag holding it and + * every tag beneath it: a renderer leaves out any tag no group names, so every + * navigation tag goes in one. Extensions the description already carries stay. + * + * https://learn.openapis.org/upgrading/v3.1-to-v3.2.html#migration-examples-from-extensions-to-native-tags + * https://redocly.com/docs/realm/content/api-docs/openapi-extensions/x-tag-groups + * https://github.com/scalar/scalar/blob/c0f6f096d/packages/schemas/src/extensions/operation/x-badge.ts + */ +export const lowerTags: Transform = () => { + const badges = new Map(); + + return { + Root: { + enter: (document) => { + const tags = (document.tags ?? []) as Array; + const byName = new Map(tags.map((tag) => [tag.name as string, tag])); + const label = (tag: Node) => (tag.summary ?? tag.name) as string; + + for (const tag of tags) { + if (tag.summary !== undefined) tag["x-displayName"] ??= tag.summary; + if (tag.kind === "badge") badges.set(tag.name as string, label(tag)); + } + + if (document["x-tagGroups"] !== undefined || !tags.some((tag) => typeof tag.parent === "string")) return; + + const top = (tag: Node) => { + const seen = new Set([tag]); + let current = tag; + for (let parent = byName.get(current.parent as string); parent && !seen.has(parent); parent = byName.get(current.parent as string)) { + seen.add(parent); + current = parent; + } + return current; + }; + + const groups = new Map>(); + for (const tag of tags) { + if (tag.kind === "badge") continue; + const root = top(tag); + groups.set(root, [...(groups.get(root) ?? []), tag.name as string]); + } + document["x-tagGroups"] = [...groups].map(([root, members]) => ({ name: label(root), tags: members })); + } + }, + Operation: { + enter: (operation) => { + const names = ((operation.tags ?? []) as Array).filter((name) => badges.has(name)).map((name) => badges.get(name)!); + if (names.length === 0) return; + + const existing = (operation["x-badges"] ?? []) as Array; + const added = names.filter((name) => !existing.some((badge) => badge.name === name)).map((name) => ({ name })); + if (added.length > 0) operation["x-badges"] = [...existing, ...added]; + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/lower-xml.ts b/packages/redocly-plugin-downlevel/src/3.2.0/lower-xml.ts new file mode 100644 index 00000000..69c952cc --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/lower-xml.ts @@ -0,0 +1,43 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.2 says how a schema becomes XML with `nodeType`; 3.1 has `attribute` and, + * for arrays, `wrapped`. A node type that is 3.1's default for the schema is + * dropped, and one 3.1 has no flag for is reported. + * + * https://spec.openapis.org/oas/v3.2.0#xml-object + */ +export const lowerXml: Transform = ({ version }) => ({ + Schema: { + leave: (node, { report, location }) => { + const xml = node.xml as Record | undefined; + if (!xml || !("nodeType" in xml)) return; + + const array = [node.type].flat().includes("array"); + const unwrapped = array || "$ref" in node; + + switch (xml.nodeType) { + case "attribute": { + xml.attribute = true; + break; + } + case "element": { + if (array) xml.wrapped = true; + break; + } + case "none": { + if (unwrapped) break; + return report({ message: `OpenAPI ${version} has no \`nodeType: none\`.`, location: location.child(["xml", "nodeType"]) }); + } + default: { + return report({ + message: `OpenAPI ${version} has no \`nodeType: ${String(xml.nodeType)}\`.`, + location: location.child(["xml", "nodeType"]) + }); + } + } + + delete xml.nodeType; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/move-content-examples.ts b/packages/redocly-plugin-downlevel/src/3.2.0/move-content-examples.ts new file mode 100644 index 00000000..ac7c7e19 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/move-content-examples.ts @@ -0,0 +1,35 @@ +import type { UserContext } from "@redocly/openapi-core"; + +import type { Node, Transform } from "../layer.ts"; + +/** + * 3.2 lets a Parameter or Header carry `example` or `examples` beside + * `content`; 3.1 allows them only beside `schema`. With `content`, they move + * into its one Media Type Object, unless it already has examples of its own. + * + * https://spec.openapis.org/oas/v3.2.0#common-fixed-fields + */ +export const moveContentExamples: Transform = ({ version }) => { + const move = (node: Node, { report, location }: UserContext) => { + const content = node.content as Record | undefined; + if (!content) return; + + const [media] = Object.values(content); + for (const field of ["example", "examples"]) { + if (!(field in node)) continue; + + if (!media || "example" in media || "examples" in media) { + report({ message: `OpenAPI ${version} has no room for \`${field}\` beside \`content\`: the media type has its own.`, location: location.child(field) }); + continue; + } + + media[field] = node[field]; + delete node[field]; + } + }; + + return { + Parameter: { leave: move }, + Header: { leave: move } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/report-meaning.ts b/packages/redocly-plugin-downlevel/src/3.2.0/report-meaning.ts new file mode 100644 index 00000000..6321b75b --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/report-meaning.ts @@ -0,0 +1,72 @@ +import type { Node, Transform } from "../layer.ts"; +import { resolveSchema } from "../pointer.ts"; + +const sequential = new Set(["application/jsonl", "application/x-ndjson", "application/json-seq", "text/event-stream", "multipart/mixed"]); +const isSequential = (media: string) => sequential.has(media) || media.endsWith("+json-seq"); + +/** + * What 3.2 gives a meaning that a 3.1 reader would not take from the same + * document. + * + * - `allowReserved: true` beyond `in: query`, which 3.1 applies nowhere else. + * - `encoding` outside a request body, which 3.1 ignores there, and entries for + * properties the schema lacks, which 3.1 forbids. + * - An array `schema` for `multipart/form-data`, and a `schema` for a + * sequential media type, which 3.2 reads item by item and 3.1 not at all. + * - An XML `namespace` that is an IRI but not a URI. + * + * https://spec.openapis.org/oas/v3.2.0#sequential-media-types + * https://spec.openapis.org/oas/v3.1.1#encoding-object + */ +export const reportMeaning: Transform = ({ version }) => { + let root: Node; + let bodies = 0; + + return { + Root: { + enter: (document) => { + root = document; + } + }, + RequestBody: { + enter: () => { + bodies++; + }, + leave: () => { + bodies--; + } + }, + Parameter: { + enter: (parameter, { report, location }) => { + if (parameter.allowReserved === true && parameter.in !== "query") + report({ message: `OpenAPI ${version} applies \`allowReserved\` only to \`in: query\`.`, location: location.child("allowReserved") }); + } + }, + MediaType: { + enter: (node, { report, location, key }) => { + const name = String(key); + const schema = node.schema ? resolveSchema(root, node.schema as Node) : undefined; + + if (node.encoding !== undefined && bodies === 0) + report({ message: `OpenAPI ${version} applies \`encoding\` only to request bodies.`, location: location.child("encoding") }); + else if (node.encoding && schema?.properties) { + for (const property of Object.keys(node.encoding as Node)) + if (!(property in (schema.properties as Node))) + report({ message: `OpenAPI ${version} requires \`${property}\` to be a property of the schema.`, location: location.child(["encoding", property]) }); + } + + if (schema && isSequential(name)) + report({ message: `OpenAPI ${version} gives \`schema\` no meaning for the sequential media type \`${name}\`.`, location: location.child("schema") }); + else if (name === "multipart/form-data" && schema?.type === "array") + report({ message: `OpenAPI ${version} gives an array \`schema\` no meaning for \`multipart/form-data\`.`, location: location.child("schema") }); + } + }, + Xml: { + enter: (xml, { report, location }) => { + const namespace = xml.namespace; + if (typeof namespace === "string" && [...namespace].some((character) => character.codePointAt(0)! > 0x7F)) + report({ message: `OpenAPI ${version} requires \`namespace\` to be a URI, and this IRI is not one.`, location: location.child("namespace") }); + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.0/resolve-security-uris.ts b/packages/redocly-plugin-downlevel/src/3.2.0/resolve-security-uris.ts new file mode 100644 index 00000000..f0c91e7a --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.0/resolve-security-uris.ts @@ -0,0 +1,43 @@ +import { unescapePointerFragment } from "@redocly/openapi-core"; + +import type { Node, Transform } from "../layer.ts"; + +const prefix = "#/components/securitySchemes/"; +const componentName = /^[\w.-]+$/; + +/** + * 3.2 lets a security requirement name its scheme by URI as well as by + * component name; 3.1 takes only the name. A URI pointing at a scheme in this + * document's components becomes that name; any other is reported. A key shaped + * like a component name is one, declared or not. + * + * https://spec.openapis.org/oas/v3.2.0#security-requirement-object + */ +export const resolveSecurityUris: Transform = ({ version }) => { + let schemes: Node; + + return { + Root: { + enter: (root) => { + schemes = ((root.components as Node | undefined)?.securitySchemes as Node | undefined) ?? {}; + } + }, + SecurityRequirement: { + leave: (node, { report, location }) => { + for (const name of Object.keys(node)) { + if (name in schemes || componentName.test(name)) continue; + + const component = name.startsWith(prefix) ? unescapePointerFragment(name.slice(prefix.length)) : undefined; + if (!component || !(component in schemes)) { + report({ message: `OpenAPI ${version} names a security scheme only by its name under \`components\`.`, location: location.child(name) }); + continue; + } + + const entries = Object.entries(node).map(([key, value]) => [key === name ? component : key, value]); + for (const key of Object.keys(node)) delete node[key]; + Object.assign(node, Object.fromEntries(entries)); + } + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.1/downlevel.test.ts b/packages/redocly-plugin-downlevel/src/3.2.1/downlevel.test.ts new file mode 100644 index 00000000..93088c30 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.1/downlevel.test.ts @@ -0,0 +1,44 @@ +import { describe, expect, test } from "bun:test"; + +import { layer } from "../fixture.ts"; + +const from321 = layer("3.2.1", "3.2.0"); + +const ok = { 200: { description: "ok" } }; + +describe("3.2.1", () => { + test("names the dialect 3.2.0 would otherwise take as 3.1's", async () => { + const { document, problems } = await from321({}); + expect(document.openapi).toBe("3.2.0"); + expect(document.jsonSchemaDialect).toBe("https://spec.openapis.org/oas/3.2/dialect/2026-02-26"); + expect(problems).toStrictEqual([]); + }); + + test("keeps a dialect the description names", async () => { + const { document, problems } = await from321({ jsonSchemaDialect: "https://example.com/dialect" }); + expect(document.jsonSchemaDialect).toBe("https://example.com/dialect"); + expect(problems).toStrictEqual([]); + }); + + test("reports what 3.2.0 reads differently", async () => { + const { problems } = await from321({ + paths: { + "/a": { + post: { + requestBody: { + content: { + "multipart/mixed": { schema: { type: "object" }, itemEncoding: { contentType: "text/plain" } }, + "multipart/form-data": { schema: { type: "array", items: { type: "string" } } } + } + }, + responses: ok + } + } + } + }); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/paths/~1a/post/requestBody/content/multipart~1mixed/itemEncoding", message: "OpenAPI 3.2.0 requires `itemSchema` or an array `schema` beside `itemEncoding`." }, + { severity: "error", pointer: "#/paths/~1a/post/requestBody/content/multipart~1form-data/schema", message: "OpenAPI 3.2.0 names `multipart/form-data` parts through `encoding` headers, not array items." } + ]); + }); +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.1/index.ts b/packages/redocly-plugin-downlevel/src/3.2.1/index.ts new file mode 100644 index 00000000..dd90b904 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.1/index.ts @@ -0,0 +1,17 @@ +import { Oas3_2Types } from "@redocly/openapi-core"; + +import type { Layer } from "../layer.ts"; +import { pinDialect } from "./pin-dialect.ts"; +import { reportPositionalEncoding } from "./report-positional-encoding.ts"; + +/** + * https://spec.openapis.org/oas/v3.2.0.html + */ +export const layer: Layer = { + version: "3.2.1", + writes: "3.2.0", + types: Oas3_2Types, + specVersion: "oas3_2", + checks: [reportPositionalEncoding], + transforms: [pinDialect] +}; diff --git a/packages/redocly-plugin-downlevel/src/3.2.1/pin-dialect.ts b/packages/redocly-plugin-downlevel/src/3.2.1/pin-dialect.ts new file mode 100644 index 00000000..0717fc29 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.1/pin-dialect.ts @@ -0,0 +1,16 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.2.0 names 3.1's dialect as its default, an erratum 3.2.1 corrected; a 3.2.0 + * reader would validate 3.2 schema keywords against a dialect that lacks them. + * A description that names no dialect gets the latest published 3.2 one. + * + * https://spec.openapis.org/oas/v3.2.1#json-schema-keywords + */ +export const pinDialect: Transform = () => ({ + Root: { + leave: (root) => { + root.jsonSchemaDialect ??= "https://spec.openapis.org/oas/3.2/dialect/2026-02-26"; + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/3.2.1/report-positional-encoding.ts b/packages/redocly-plugin-downlevel/src/3.2.1/report-positional-encoding.ts new file mode 100644 index 00000000..190ab2d4 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/3.2.1/report-positional-encoding.ts @@ -0,0 +1,35 @@ +import type { Node, Transform } from "../layer.ts"; +import { resolveSchema } from "../pointer.ts"; + +/** + * 3.2.1 lets `prefixEncoding` and `itemEncoding` stand without an item schema, + * ignoring entries nothing matches, and reads a `multipart/form-data` array + * schema as parts named by their items. 3.2.0 requires `itemSchema` or an array + * `schema` for the first, and names form parts through `encoding` headers. + * + * https://spec.openapis.org/oas/v3.2.1#encoding-by-position + */ +export const reportPositionalEncoding: Transform = ({ version }) => { + let root: Node; + + return { + Root: { + enter: (document) => { + root = document; + } + }, + MediaType: { + enter: (node, { report, location, key }) => { + const schema = node.schema ? resolveSchema(root, node.schema as Node) : undefined; + const positional = node.itemSchema !== undefined || schema?.type === "array"; + + for (const field of ["prefixEncoding", "itemEncoding"]) + if (field in node && !positional) + report({ message: `OpenAPI ${version} requires \`itemSchema\` or an array \`schema\` beside \`${field}\`.`, location: location.child(field) }); + + if (key === "multipart/form-data" && schema?.type === "array") + report({ message: `OpenAPI ${version} names \`multipart/form-data\` parts through \`encoding\` headers, not array items.`, location: location.child("schema") }); + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/__snapshots__/fixtures.test.ts.snap b/packages/redocly-plugin-downlevel/src/__snapshots__/fixtures.test.ts.snap new file mode 100644 index 00000000..ae57f973 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/__snapshots__/fixtures.test.ts.snap @@ -0,0 +1,6907 @@ +// Bun Snapshot v1, https://bun.sh/docs/test/snapshots + +exports[`fixtures learn/3.1/non-oauth-scopes.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "securitySchemes": { + "bearerAuth": { + "bearerFormat": "jwt", + "description": "note: non-oauth scopes are not defined at the securityScheme level", + "scheme": "bearer", + "type": "http", + }, + }, + }, + "info": { + "title": "Non-oAuth Scopes example", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/users": { + "get": { + "security": [ + { + "bearerAuth": [ + "read:users", + "public", + ], + }, + ], + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 lists roles only for \`oauth2\` and \`openIdConnect\` schemes.", + "pointer": "#/paths/~1users/get/security/0/bearerAuth", + }, + ], + }, +} +`; + +exports[`fixtures learn/3.1/tictactoe.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "columnParam": { + "description": "Board column (horizontal coordinate)", + "in": "path", + "name": "column", + "required": true, + "schema": { + "$ref": "#/components/schemas/coordinate", + }, + }, + "rowParam": { + "description": "Board row (vertical coordinate)", + "in": "path", + "name": "row", + "required": true, + "schema": { + "$ref": "#/components/schemas/coordinate", + }, + }, + }, + "schemas": { + "board": { + "items": { + "items": { + "$ref": "#/components/schemas/mark", + }, + "maxItems": 3, + "minItems": 3, + "type": "array", + }, + "maxItems": 3, + "minItems": 3, + "type": "array", + }, + "coordinate": { + "example": 1, + "maximum": 3, + "minimum": 1, + "type": "integer", + }, + "errorMessage": { + "description": "A text message describing an error", + "maxLength": 256, + "type": "string", + }, + "mark": { + "description": "Possible values for a board square. \`.\` means empty square.", + "enum": [ + ".", + "X", + "O", + ], + "example": ".", + "type": "string", + }, + "status": { + "properties": { + "board": { + "$ref": "#/components/schemas/board", + }, + "winner": { + "$ref": "#/components/schemas/winner", + }, + }, + "type": "object", + }, + "winner": { + "description": "Winner of the game. \`.\` means nobody has won yet.", + "enum": [ + ".", + "X", + "O", + ], + "example": ".", + "type": "string", + }, + }, + "securitySchemes": { + "app2AppOauth": { + "flows": { + "clientCredentials": { + "scopes": { + "board:read": "Read the board", + }, + "tokenUrl": "https://learn.openapis.org/oauth/2.0/token", + }, + }, + "type": "oauth2", + }, + "basicHttpAuthentication": { + "description": "Basic HTTP Authentication", + "scheme": "Basic", + "type": "http", + }, + "bearerHttpAuthentication": { + "bearerFormat": "JWT", + "description": "Bearer token using a JWT", + "scheme": "Bearer", + "type": "http", + }, + "defaultApiKey": { + "description": "API key provided in console", + "in": "header", + "name": "api-key", + "type": "apiKey", + }, + "user2AppOauth": { + "flows": { + "authorizationCode": { + "authorizationUrl": "https://learn.openapis.org/oauth/2.0/auth", + "scopes": { + "board:read": "Read the board", + "board:write": "Write to the board", + }, + "tokenUrl": "https://learn.openapis.org/oauth/2.0/token", + }, + }, + "type": "oauth2", + }, + }, + }, + "info": { + "description": +"This API allows writing down marks on a Tic Tac Toe board +and requesting the state of the board or of individual squares. +" +, + "title": "Tic Tac Toe", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": { + "/board": { + "get": { + "description": "Retrieves the current state of the board and the winner.", + "operationId": "get-board", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/status", + }, + }, + }, + "description": "OK", + }, + }, + "security": [ + { + "defaultApiKey": [], + }, + { + "app2AppOauth": [ + "board:read", + ], + }, + ], + "summary": "Get the whole board", + "tags": [ + "Gameplay", + ], + }, + }, + "/board/{row}/{column}": { + "get": { + "description": "Retrieves the requested square.", + "operationId": "get-square", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/mark", + }, + }, + }, + "description": "OK", + "links": { + "markSquare": { + "description": "Operation to use if the mark value returned indicates the square is empty", + "operationId": "put-square", + "parameters": { + "column": "$request.path.column", + "row": "$request.path.row", + }, + }, + }, + }, + "400": { + "content": { + "text/html": { + "example": "Illegal coordinates", + "schema": { + "$ref": "#/components/schemas/errorMessage", + }, + }, + }, + "description": "The provided parameters are incorrect", + }, + }, + "security": [ + { + "bearerHttpAuthentication": [], + }, + { + "user2AppOauth": [ + "board:read", + ], + }, + ], + "summary": "Get a single board square", + "tags": [ + "Gameplay", + ], + }, + "parameters": [ + { + "$ref": "#/components/parameters/rowParam", + }, + { + "$ref": "#/components/parameters/columnParam", + }, + ], + "put": { + "callbacks": { + "statusCallback": { + "{$request.header.progressUrl}": { + "post": { + "description": "Provides the status of the mark operation", + "operationId": "markOperationCallback", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/status", + }, + }, + }, + }, + "responses": { + "200": { + "description": "Mark operation status received", + }, + }, + "summary": "Status of mark operation", + }, + }, + }, + }, + "description": "Places a mark on the board and retrieves the whole board and the winner (if any).", + "operationId": "put-square", + "parameters": [ + { + "description": "Progress URL that should be called if asynchronous response is returned", + "in": "header", + "name": "progressUrl", + "required": false, + "schema": { + "type": "string", + }, + }, + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/mark", + }, + }, + }, + "required": true, + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/status", + }, + }, + }, + "description": "OK", + }, + "202": { + "description": "Mark operation has not completed. Use callback to check for progress", + "headers": { + "Location": { + "description": "Callback URL", + "schema": { + "type": "string", + }, + }, + }, + }, + "400": { + "content": { + "text/html": { + "examples": { + "illegalCoordinates": { + "value": "Illegal coordinates.", + }, + "invalidMark": { + "value": "Invalid Mark (X or O).", + }, + "notEmpty": { + "value": "Square is not empty.", + }, + }, + "schema": { + "$ref": "#/components/schemas/errorMessage", + }, + }, + }, + "description": "The provided parameters are incorrect", + }, + }, + "security": [ + { + "bearerHttpAuthentication": [], + }, + { + "user2AppOauth": [ + "board:write", + ], + }, + ], + "summary": "Set a single board square", + "tags": [ + "Gameplay", + ], + }, + }, + }, + "tags": [ + { + "name": "Gameplay", + }, + ], + "x-webhooks": { + "markStatus": { + "post": { + "description": "Provides the status of the mark operation on completion", + "operationId": "markOperationWebhook", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/status", + }, + }, + }, + "description": "Mark operation has completed successfully", + }, + }, + "summary": "Status of mark operation", + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures learn/3.1/webhook-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + "type": "object", + }, + }, + }, + "info": { + "title": "Webhook Example", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "x-webhooks": { + "newPet": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + "description": "Information about a new pet in the system", + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully", + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures learn/3.2/3.2-query-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "Flight API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/flights/search": { + "x-oai-additionalOperations": { + "QUERY": { + "description": +"Uses the HTTP QUERY method to perform a safe, idempotent flight search with filters that are too complex for a URL query string. +" +, + "operationId": "searchFlights", + "requestBody": { + "content": { + "application/json": { + "schema": { + "properties": { + "cabinClass": { + "enum": [ + "economy", + "premium-economy", + "business", + "first", + ], + "example": "business", + "type": "string", + }, + "departureDate": { + "example": "2026-06-15", + "format": "date", + "type": "string", + }, + "destination": { + "example": "LHR", + "type": "string", + }, + "nonStopOnly": { + "example": true, + "type": "boolean", + }, + "origin": { + "example": "ATL", + "type": "string", + }, + "passengers": { + "example": 2, + "minimum": 1, + "type": "integer", + }, + "returnDate": { + "example": "2026-06-25", + "format": "date", + "type": "string", + }, + }, + "required": [ + "origin", + "destination", + "departureDate", + ], + "type": "object", + }, + }, + }, + "required": true, + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "flights": { + "items": { + "properties": { + "arrivalTime": { + "example": "2026-06-16T10:15:00Z", + "format": "date-time", + "type": "string", + }, + "departureTime": { + "example": "2026-06-15T22:30:00Z", + "format": "date-time", + "type": "string", + }, + "destination": { + "example": "LHR", + "type": "string", + }, + "flightNumber": { + "example": "DL30", + "type": "string", + }, + "origin": { + "example": "ATL", + "type": "string", + }, + "price": { + "example": 1249.99, + "format": "float", + "type": "number", + }, + }, + "type": "object", + }, + "type": "array", + }, + }, + "type": "object", + }, + }, + }, + "description": "Matching flights", + }, + }, + "summary": "Search flights with complex criteria", + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures learn/3.2/3.2-tags-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": "as 3.1.0", + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1flights/get", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1flights~1international/get", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1flights~1domestic/get", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1flights~1delayed/get", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "Flight API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/flights": { + "get": { + "summary": "List all flights", + "tags": [ + "flights", + ], + }, + }, + "/flights/delayed": { + "get": { + "summary": "Get delayed flights", + "tags": [ + "delays", + ], + "x-badges": [ + { + "name": "Delays", + }, + ], + }, + }, + "/flights/domestic": { + "get": { + "summary": "List domestic flights", + "tags": [ + "domestic", + ], + }, + }, + "/flights/international": { + "get": { + "summary": "List international flights", + "tags": [ + "international", + ], + }, + }, + }, + "tags": [ + { + "description": "Core flight operations", + "name": "flights", + "x-displayName": "Flights", + }, + { + "description": "Flights that cross country borders", + "name": "international", + "x-displayName": "International", + }, + { + "description": "Flights within a single country", + "name": "domestic", + "x-displayName": "Domestic", + }, + { + "description": "Information about flight delays", + "externalDocs": { + "description": "Delay compensation policies", + "url": "https://docs.example.com/delay-policies", + }, + "name": "delays", + "x-displayName": "Delays", + }, + ], + "x-tagGroups": [ + { + "name": "Flights", + "tags": [ + "flights", + "international", + "domestic", + ], + }, + ], + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.0/api-with-examples.yaml 1`] = `{}`; + +exports[`fixtures oai/3.0/callback-example.yaml 1`] = `{}`; + +exports[`fixtures oai/3.0/link-example.yaml 1`] = `{}`; + +exports[`fixtures oai/3.0/petstore-expanded.yaml 1`] = `{}`; + +exports[`fixtures oai/3.0/petstore.yaml 1`] = `{}`; + +exports[`fixtures oai/3.0/uspto.yaml 1`] = ` +{ + "3.0.0": { + "document": { + "components": { + "schemas": { + "dataSetList": { + "properties": { + "apis": { + "items": { + "properties": { + "apiDocumentationUrl": { + "description": "A URL to the API console for each API", + "format": "uriref", + "type": "string", + }, + "apiKey": { + "description": "To be used as a dataset parameter value", + "type": "string", + }, + "apiUrl": { + "description": "The URL describing the dataset's fields", + "format": "uriref", + "type": "string", + }, + "apiVersionNumber": { + "description": "To be used as a version parameter value", + "type": "string", + }, + }, + "type": "object", + }, + "type": "array", + }, + "total": { + "type": "integer", + }, + }, + "type": "object", + }, + }, + }, + "info": { + "contact": { + "email": "developer@uspto.gov", + "name": "Open Data Portal", + "url": "https://developer.uspto.gov", + }, + "description": "The Data Set API (DSAPI) allows the public users to discover and search USPTO exported data sets. This is a generic API that allows USPTO users to make any CSV based data files searchable through API. With the help of GET call, it returns the list of data fields that are searchable. With the help of POST call, data can be fetched based on the filters on the field names. Please note that POST call is used to search the actual data. The reason for the POST call is that it allows users to specify any complex search criteria without worry about the GET size limitations as well as encoding of the input parameters.", + "title": "USPTO Data Set API", + "version": "1.0.0", + }, + "openapi": "3.0.0", + "paths": { + "/": { + "get": { + "operationId": "list-data-sets", + "responses": { + "200": { + "content": { + "application/json": { + "example": { + "apis": [ + { + "apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/oa_citations.json", + "apiKey": "oa_citations", + "apiUrl": "https://developer.uspto.gov/ds-api/oa_citations/v1/fields", + "apiVersionNumber": "v1", + }, + { + "apiDocumentationUrl": "https://developer.uspto.gov/ds-api-docs/index.html?url=https://developer.uspto.gov/ds-api/swagger/docs/cancer_moonshot.json", + "apiKey": "cancer_moonshot", + "apiUrl": "https://developer.uspto.gov/ds-api/cancer_moonshot/v1/fields", + "apiVersionNumber": "v1", + }, + ], + "total": 2, + }, + "schema": { + "$ref": "#/components/schemas/dataSetList", + }, + }, + }, + "description": "Returns a list of data sets", + }, + }, + "summary": "List available data sets", + "tags": [ + "metadata", + ], + }, + }, + "/{dataset}/{version}/fields": { + "get": { + "description": "This GET API returns the list of all the searchable field names that are in the oa_citations. Please see the 'fields' attribute which returns an array of field names. Each field or a combination of fields can be searched using the syntax options shown below.", + "operationId": "list-searchable-fields", + "parameters": [ + { + "description": "Name of the dataset.", + "example": "oa_citations", + "in": "path", + "name": "dataset", + "required": true, + "schema": { + "type": "string", + }, + }, + { + "description": "Version of the dataset.", + "example": "v1", + "in": "path", + "name": "version", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "string", + }, + }, + }, + "description": "The dataset API for the given version is found and it is accessible to consume.", + }, + "404": { + "content": { + "application/json": { + "schema": { + "type": "string", + }, + }, + }, + "description": "The combination of dataset name and version is not found in the system or it is not published yet to be consumed by public.", + }, + }, + "summary": "Provides the general information about the API and the list of fields that can be used to query the dataset.", + "tags": [ + "metadata", + ], + }, + }, + "/{dataset}/{version}/records": { + "post": { + "description": "This API is based on Solr/Lucene Search. The data is indexed using SOLR. This GET API returns the list of all the searchable field names that are in the Solr Index. Please see the 'fields' attribute which returns an array of field names. Each field or a combination of fields can be searched using the Solr/Lucene Syntax. Please refer https://lucene.apache.org/core/3_6_2/queryparsersyntax.html#Overview for the query syntax. List of field names that are searchable can be determined using above GET api.", + "operationId": "perform-search", + "parameters": [ + { + "description": "Version of the dataset.", + "in": "path", + "name": "version", + "required": true, + "schema": { + "default": "v1", + "type": "string", + }, + }, + { + "description": "Name of the dataset. In this case, the default value is oa_citations", + "in": "path", + "name": "dataset", + "required": true, + "schema": { + "default": "oa_citations", + "type": "string", + }, + }, + ], + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "properties": { + "criteria": { + "default": "*:*", + "description": "Uses Lucene Query Syntax in the format of propertyName:value, propertyName:[num1 TO num2] and date range format: propertyName:[yyyyMMdd TO yyyyMMdd]. In the response please see the 'docs' element which has the list of record objects. Each record structure would consist of all the fields and their corresponding values.", + "type": "string", + }, + "rows": { + "default": 100, + "description": "Specify number of rows to be returned. If you run the search with default values, in the response you will see 'numFound' attribute which will tell the number of records available in the dataset.", + "type": "integer", + }, + "start": { + "default": 0, + "description": "Starting record number. Default value is 0.", + "type": "integer", + }, + }, + "required": [ + "criteria", + ], + "type": "object", + }, + }, + }, + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "additionalProperties": { + "type": "object", + }, + "type": "object", + }, + "type": "array", + }, + }, + }, + "description": "successful operation", + }, + "404": { + "description": "No matching record found for the given criteria.", + }, + }, + "summary": "Provides search capability for the data set with the given search criteria.", + "tags": [ + "search", + ], + }, + }, + }, + "servers": [ + { + "url": "{scheme}://developer.uspto.gov/ds-api", + "variables": { + "scheme": { + "default": "https", + "description": "The Data Set API is accessible via https and http", + "enum": [ + "https", + "http", + ], + }, + }, + }, + ], + "tags": [ + { + "description": "Find out about the data sets", + "name": "metadata", + }, + { + "description": "Search a data set", + "name": "search", + }, + ], + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/callback-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "callbacks": { + "myCallback": { + "{$request.query.queryUrl}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + "transactionCallback": { + "http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + }, + "schemas": { + "SomePayload": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/comp_pathitems.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/components-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "limitParam": { + "description": "max records to return", + "in": "query", + "name": "limit", + "required": true, + "schema": { + "format": "int32", + "type": "integer", + }, + }, + "skipParam": { + "description": "number of items to skip", + "in": "query", + "name": "skip", + "required": true, + "schema": { + "format": "int32", + "type": "integer", + }, + }, + }, + "responses": { + "GeneralError": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GeneralError", + }, + }, + }, + "description": "General Error", + }, + "IllegalInput": { + "description": "Illegal input for operation.", + }, + "NotFound": { + "description": "Entity not found.", + }, + }, + "schemas": { + "Category": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + }, + "type": "object", + }, + "GeneralError": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "type": "object", + }, + "Tag": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + }, + "type": "object", + }, + }, + "securitySchemes": { + "api_key": { + "in": "header", + "name": "api-key", + "type": "apiKey", + }, + "petstore_auth": { + "flows": { + "implicit": { + "authorizationUrl": "https://example.org/api/oauth/dialog", + "scopes": { + "read:pets": "read your pets", + "write:pets": "modify pets in your account", + }, + }, + }, + "type": "oauth2", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/example-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "examples": { + "confirmation-success": {}, + "zip-example": {}, + }, + "parameters": { + "with-example": { + "examples": { + "zip-example": { + "$ref": "#/components/examples/zip-example", + }, + }, + "in": "query", + "name": "zipCode", + "schema": { + "format": "zip-code", + "type": "string", + }, + }, + }, + "requestBodies": { + "with-example": { + "content": { + "application/json": { + "examples": { + "bar": { + "summary": "A bar example", + "value": { + "bar": "baz", + }, + }, + "foo": { + "summary": "A foo example", + "value": { + "foo": "bar", + }, + }, + }, + "schema": { + "$ref": "#/components/schemas/Address", + }, + }, + "application/xml": { + "examples": { + "xmlExample": { + "externalValue": "https://example.org/examples/address-example.xml", + "summary": "This is an example in XML", + }, + }, + }, + "text/plain": { + "examples": { + "textExample": { + "externalValue": "https://foo.bar/examples/address-example.txt", + "summary": "This is a text example", + }, + }, + }, + }, + }, + }, + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "confirmation-success": { + "$ref": "#/components/examples/confirmation-success", + }, + }, + "schema": { + "$ref": "#/components/schemas/SuccessResponse", + }, + }, + "application/x-www-form-urlencoded": { + "encoding": { + "jsonValue": { + "contentType": "application/json", + }, + }, + "examples": { + "jsonFormValue": { + "description": "The JSON string "json" as a form value", + "value": "jsonValue=%22json%22", + }, + }, + "schema": { + "properties": { + "jsonValue": { + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "your car appointment has been booked", + }, + }, + "schemas": { + "Address": {}, + "SuccessResponse": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/header-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "headers": { + "ETag": { + "content": { + "text/plain": { + "schema": { + "pattern": "^"", + "type": "string", + }, + }, + }, + "required": true, + }, + "Reference": { + "$ref": "#/components/headers/ETag", + }, + "Style": { + "explode": true, + "schema": { + "items": {}, + "type": "array", + }, + "style": "simple", + }, + "X-Rate-Limit-Limit": { + "deprecated": false, + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/info-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "info": { + "contact": { + "email": "support@example.com", + "name": "API Support", + "url": "https://www.example.com/support", + }, + "description": "This is an example server for a pet store.", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + }, + "termsOfService": "https://example.com/terms/", + "title": "Example Pet Store App", + "version": "1.0.1", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/info_summary.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/json_schema_dialect.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "WithDollarSchema": {}, + }, + }, + "info": { + "license": { + "name": "Apache 2.0", + "x-oai-license-identifier": "Apache-2.0", + }, + "title": "My API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/license_identifier.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "license": { + "name": "Apache", + "x-oai-license-identifier": "Apache-2.0", + }, + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/link-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": { + "/users/{id}": { + "get": { + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "uuid": { + "format": "uuid", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "the user being returned", + "links": { + "UserRepositories": { + "operationRef": "#/paths/~12.0~1repositories~1%7Busername%7D/get", + "parameters": { + "username": "$response.body#/username", + }, + }, + "UserRepositories2": { + "operationRef": "https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1%7Busername%7D/get", + "parameters": { + "username": "$response.body#/username", + }, + }, + "address": { + "operationId": "getUserAddress", + "parameters": { + "userid": "$request.path.id", + }, + }, + "address2": { + "operationId": "getUserAddressByUUID", + "parameters": { + "userUuid": "$response.body#/uuid", + }, + }, + "withBody": { + "operationId": "queryUserWithBody", + "requestBody": { + "userId": "$request.path.id", + }, + }, + }, + }, + }, + }, + "parameters": [ + { + "description": "the user identifier, as userId", + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + }, + "/users/{userid}/address": { + "get": { + "operationId": "getUserAddress", + "responses": { + "200": { + "description": "the user's address", + }, + }, + }, + "parameters": [ + { + "description": "the user identifier, as userId", + "in": "path", + "name": "userid", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/media-type-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "examples": { + "frog-example": {}, + }, + "schemas": { + "Address": {}, + "Pet": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/something": { + "put": { + "requestBody": { + "content": { + "application/json": { + "examples": { + "cat": { + "summary": "An example of a cat", + "value": { + "breed": "Persian", + "color": "White", + "gender": "male", + "name": "Fluffy", + "petType": "Cat", + }, + }, + "dog": { + "summary": "An example of a dog with a cat's name", + "value": { + "breed": "Mixed", + "color": "Black", + "gender": "Female", + "name": "Puma", + "petType": "Dog", + }, + }, + "frog": { + "$ref": "#/components/examples/frog-example", + }, + }, + "schema": { + "$ref": "#/components/schemas/Pet", + }, + }, + "application/x-www-form-urlencoded": { + "encoding": { + "icon": { + "contentType": "image/png, image/jpeg", + }, + }, + "schema": { + "properties": { + "address": { + "properties": {}, + "type": "object", + }, + "icon": { + "type": "string", + "x-jsonschema-contentEncoding": "base64url", + }, + "id": { + "format": "uuid", + "type": "string", + }, + }, + "type": "object", + }, + }, + "application/xml": { + "schema": { + "properties": { + "attr": { + "type": "string", + "xml": { + "attribute": true, + }, + }, + "bar": { + "items": { + "type": "number", + }, + "type": "array", + "xml": { + "wrapped": true, + }, + }, + "foo": { + "type": "string", + "xml": { + "name": "Foo", + "namespace": "https://example.com", + "prefix": "example", + }, + }, + }, + "type": "object", + }, + }, + "multipart/form-data": { + "encoding": { + "addresses": { + "contentType": "application/xml; charset=utf-8", + }, + "forCoverage": { + "allowReserved": true, + "explode": false, + "style": "form", + }, + "forCoverage2": { + "explode": true, + "style": "spaceDelimited", + }, + "profileImage": { + "contentType": "image/png, image/jpeg", + "headers": { + "X-Rate-Limit-Limit": { + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + }, + "schema": { + "properties": { + "addresses": { + "description": "addresses in XML format", + "items": { + "$ref": "#/components/schemas/Address", + }, + "type": "array", + }, + "forCoverage": { + "type": "string", + }, + "forCoverage2": { + "type": "string", + }, + "id": { + "format": "uuid", + "type": "string", + }, + "profileImage": { + "format": "binary", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 ignores \`style\` in multipart.", + "pointer": "#/paths/~1something/put/requestBody/content/multipart~1form-data/encoding/forCoverage/style", + }, + { + "message": "OpenAPI 3.0.4 ignores \`explode\` in multipart.", + "pointer": "#/paths/~1something/put/requestBody/content/multipart~1form-data/encoding/forCoverage/explode", + }, + { + "message": "OpenAPI 3.0.4 ignores \`allowReserved\` in multipart.", + "pointer": "#/paths/~1something/put/requestBody/content/multipart~1form-data/encoding/forCoverage/allowReserved", + }, + { + "message": "OpenAPI 3.0.4 ignores \`style\` in multipart.", + "pointer": "#/paths/~1something/put/requestBody/content/multipart~1form-data/encoding/forCoverage2/style", + }, + { + "message": "OpenAPI 3.0.4 ignores \`explode\` in multipart.", + "pointer": "#/paths/~1something/put/requestBody/content/multipart~1form-data/encoding/forCoverage2/explode", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/mega.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "pathItems": { + "myPathItem": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/Foo", + }, + ], + "discriminator": { + "mapping": { + "foo": "Foo", + }, + "propertyName": "type", + "x-extension": true, + }, + "externalDocs": { + "description": "More docs!", + "url": "https://example.com/elsewhere.html", + }, + "myArbitraryKeyword": true, + "properties": { + "arr": { + "$comment": "Array without items keyword", + "type": "array", + }, + "either": { + "type": [ + "string", + "null", + ], + }, + "int": { + "exclusiveMaximum": 100, + "exclusiveMinimum": 0, + "type": "integer", + }, + "none": { + "type": "null", + }, + "type": { + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "required": true, + }, + }, + }, + }, + "schemas": { + "Foo": { + "properties": { + "type": { + "const": "foo", + }, + }, + "type": "object", + }, + }, + "securitySchemes": { + "mtls": { + "type": "mutualTLS", + }, + }, + }, + "info": { + "license": { + "identifier": "Apache-2.0", + "name": "Apache 2.0", + }, + "summary": "My API's summary", + "title": "My API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/": { + "get": { + "parameters": [], + }, + }, + "/{pathTest}": {}, + }, + "webhooks": { + "myWebhook": { + "$ref": "#/components/pathItems/myPathItem", + "description": "Overriding description", + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`type: mutualTLS\`.", + "pointer": "#/components/securitySchemes/mtls/type", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/minimal_comp.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/minimal_hooks.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "x-webhooks": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/minimal_paths.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/non-oauth-scopes.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "securitySchemes": { + "bearerAuth": { + "bearerFormat": "jwt", + "description": "note: non-oauth scopes are not defined at the securityScheme level", + "scheme": "bearer", + "type": "http", + }, + }, + }, + "info": { + "title": "Non-oAuth Scopes example", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/users": { + "get": { + "security": [ + { + "bearerAuth": [ + "read:users", + "public", + ], + }, + ], + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 lists roles only for \`oauth2\` and \`openIdConnect\` schemes.", + "pointer": "#/paths/~1users/get/security/0/bearerAuth", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/operation-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": { + "/pets/{id}": { + "put": { + "operationId": "updatePetWithForm", + "parameters": [ + { + "description": "ID of pet that needs to be updated", + "in": "path", + "name": "petId", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "properties": { + "name": { + "description": "Updated name of the pet", + "type": "string", + }, + "status": { + "description": "Updated status of the pet", + "type": "string", + }, + }, + "required": [ + "status", + ], + "type": "object", + }, + }, + }, + }, + "responses": { + "200": { + "content": { + "application/json": {}, + "application/xml": {}, + }, + "description": "Pet updated.", + }, + "405": { + "content": { + "application/json": {}, + "application/xml": {}, + }, + "description": "Method Not Allowed", + }, + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Updates a pet in the store with form data", + "tags": [ + "pet", + ], + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/parameter-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/parameter-object-query-allowReserved.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "my_query": { + "allowReserved": true, + "in": "query", + "name": "my_query", + "schema": {}, + }, + }, + }, + "info": { + "title": "allowReserved only permitted with in: query", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/path-item-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "ErrorModel": {}, + "Pet": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": { + "/pets/{id}": { + "get": { + "description": "Returns pets based on ID", + "operationId": "getPetsById", + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "items": { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + }, + "description": "pet response", + }, + "default": { + "content": { + "text/html": { + "schema": { + "$ref": "#/components/schemas/ErrorModel", + }, + }, + }, + "description": "error payload", + }, + }, + "summary": "Find pets by ID", + }, + "parameters": [ + { + "description": "ID of pet to use", + "in": "path", + "name": "id", + "required": true, + "schema": { + "items": { + "type": "string", + }, + "type": "array", + }, + "style": "simple", + }, + ], + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/path_item_servers_parameters.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "callbacks": { + "transactionCallback": { + "http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + }, + "examples": { + "ThingExample": { + "description": "A thing", + "summary": "A thing", + "value": { + "id": 1, + "name": "Thing", + }, + }, + }, + "links": { + "ThingLink": { + "description": "A link to a thing", + "operationId": "getThing", + "parameters": { + "thingId": "$response.body#/id", + }, + "server": { + "url": "https://things.example.com", + }, + }, + "ThingyLink": { + "$ref": "#/components/links/ThingLink", + }, + }, + "parameters": { + "biscuit": { + "in": "cookie", + "name": "biscuit", + "schema": { + "type": "string", + }, + "style": "form", + }, + "limit": { + "allowEmptyValue": false, + "allowReserved": false, + "deprecated": true, + "description": "The maximum number of list items to return", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "minimum": 0, + "type": "integer", + }, + }, + }, + "requestBodies": { + "ThingRequestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + }, + }, + }, + }, + }, + "responses": { + "ThingResponse": { + "content": { + "application/json": { + "schema": { + "type": "object", + }, + }, + }, + "description": "A thing", + }, + }, + "schemas": { + "SomePayload": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/things": { + "delete": {}, + "get": { + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "parameters": [ + { + "$ref": "#/components/parameters/biscuit", + "description": "The maximum number of things to return", + "summary": "The maximum number of things to return", + }, + ], + "responses": { + "default": { + "description": "A list of things", + }, + }, + "servers": [ + { + "url": "https://things.example.com", + }, + ], + "summary": "Get a list of things", + }, + "head": {}, + "options": {}, + "patch": {}, + "post": { + "callbacks": { + "myCallback": { + "{$request.query.queryUrl}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + "transactionCallback": { + "$ref": "#/components/callbacks/transactionCallback", + }, + }, + "deprecated": false, + "requestBody": { + "$ref": "#/components/requestBodies/ThingRequestBody", + }, + "responses": { + "201": { + "$ref": "#/components/responses/ThingResponse", + }, + }, + }, + "servers": [ + { + "url": "https://things.example.com", + }, + ], + "summary": "Lots of things", + "trace": {}, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/delete", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/options", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/head", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/patch", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/trace", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/path_no_response.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/": { + "get": {}, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1/get", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/path_var_empty_pathitem.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/paths-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "pet": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": { + "/pets": { + "get": { + "description": "Returns all pets from the system that the user has access to", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/pet", + }, + "type": "array", + }, + }, + }, + "description": "A list of pets.", + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/request-body-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "User": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": { + "/something": { + "put": { + "requestBody": { + "content": { + "*/*": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.whatever", + "summary": "User example in other format", + }, + }, + }, + "application/json": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.json", + "summary": "User example", + }, + }, + "schema": { + "$ref": "#/components/schemas/User", + }, + }, + "application/xml": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.xml", + "summary": "User example in XML", + }, + }, + "schema": { + "$ref": "#/components/schemas/User", + }, + }, + "text/plain": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.txt", + "summary": "User example in plain text", + }, + }, + }, + }, + "description": "user to add to the system", + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1something/put", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/response-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "responses": { + "complex-object-array": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/VeryComplexType", + }, + "type": "array", + }, + }, + }, + "description": "A complex object array response", + }, + "no-return-value": { + "description": "object created", + }, + "plain-text-with-headers": { + "content": { + "text/plain": { + "example": "whoa!", + "schema": { + "type": "string", + }, + }, + }, + "description": "A simple string response", + "headers": { + "X-Rate-Limit-Limit": { + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + "X-Rate-Limit-Remaining": { + "description": "The number of remaining requests in the current period", + "schema": { + "type": "integer", + }, + }, + "X-Rate-Limit-Reset": { + "description": "The number of seconds left in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + "simple-string": { + "content": { + "text/plain": { + "schema": { + "type": "string", + }, + }, + }, + "description": "A simple string response", + }, + }, + "schemas": { + "VeryComplexType": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/schema-object-deprecated-example-keyword.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": { + "/user": { + "parameters": [ + { + "in": "query", + "name": "example", + "schema": { + "example": { + "flag": null, + "numbers": [ + 1, + 2, + ], + }, + "type": "object", + }, + }, + ], + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/schema.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "model": { + "properties": { + "eight": { + "description": "exclusiveMaximum true", + "exclusiveMaximum": 20, + }, + "eleven": { + "description": "x-nullable string", + "nullable": true, + "type": "string", + }, + "five": { + "description": "singular example", + "examples": [ + "exampleValue", + ], + "type": "string", + }, + "four": { + "description": "array with no items", + "type": "array", + }, + "nine": { + "description": "exclusiveMaximum false", + "maximum": 20, + }, + "one": { + "anyOf": [ + { + "type": "integer", + }, + { + "type": "string", + }, + ], + "description": "type array", + }, + "seven": { + "description": "exclusiveMinimum false", + "minimum": 10, + }, + "six": { + "description": "exclusiveMinimum true", + "exclusiveMinimum": 10, + }, + "ten": { + "description": "nullable string", + "nullable": true, + "type": "string", + }, + "three": { + "description": "type array including 'null'", + "nullable": true, + "type": "string", + }, + "twelve": { + "description": "file/binary", + }, + "two": { + "description": "type 'null'", + "type": "null", + }, + }, + "type": "object", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": {}, + }, + "loosened": { + "document": { + "components": { + "schemas": { + "model": { + "properties": { + "eight": { + "description": "exclusiveMaximum true", + "exclusiveMaximum": 20, + }, + "eleven": { + "description": "x-nullable string", + "nullable": true, + "type": "string", + }, + "five": { + "description": "singular example", + "examples": [ + "exampleValue", + ], + "type": "string", + }, + "four": { + "description": "array with no items", + "type": "array", + }, + "nine": { + "description": "exclusiveMaximum false", + "maximum": 20, + }, + "one": { + "description": "type array", + }, + "seven": { + "description": "exclusiveMinimum false", + "minimum": 10, + }, + "six": { + "description": "exclusiveMinimum true", + "exclusiveMinimum": 10, + }, + "ten": { + "description": "nullable string", + "nullable": true, + "type": "string", + }, + "three": { + "description": "type array including 'null'", + "nullable": true, + "type": "string", + }, + "twelve": { + "description": "file/binary", + }, + "two": { + "description": "type 'null'", + "type": "null", + }, + }, + "type": "object", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": {}, + }, + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`null\` type.", + "pointer": "#/components/schemas/model/properties/two/type", + }, + ], + }, + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`null\` type.", + "pointer": "#/components/schemas/model/properties/two/type", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/security-scheme-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "securitySchemes": { + "JWT-bearer": { + "bearerFormat": "JWT", + "scheme": "bearer", + "type": "http", + }, + "OAuth2": { + "flows": { + "authorizationCode": { + "authorizationUrl": "https://example.com/api/oauth/dialog", + "refreshUrl": "https://example.com/api/oauth/refresh", + "scopes": { + "read:pets": "read your pets", + "write:pets": "modify pets in your account", + }, + "tokenUrl": "https://example.com/api/oauth/token", + }, + "clientCredentials": { + "refreshUrl": "https://example.com/api/oauth/refresh", + "scopes": { + "read:pets": "read your pets", + }, + "tokenUrl": "https://example.com/api/oauth/token", + }, + "implicit": { + "authorizationUrl": "https://example.com/api/oauth/dialog", + "refreshUrl": "https://example.com/api/oauth/refresh", + "scopes": { + "read:pets": "read your pets", + "write:pets": "modify pets in your account", + }, + }, + "password": { + "refreshUrl": "https://example.com/api/oauth/refresh", + "scopes": { + "read:pets": "read your pets", + }, + "tokenUrl": "https://example.com/api/oauth/token", + }, + }, + "type": "oauth2", + }, + "OpenIdConnect": { + "openIdConnectUrl": "https://example.com/api/oauth/openid", + "type": "openIdConnect", + }, + "apiKey": { + "in": "header", + "name": "api-key", + "type": "apiKey", + }, + "basic": { + "scheme": "basic", + "type": "http", + }, + "external": { + "$ref": "https://example.com/api/openapi.json#/components/externalDocs/ThingExternalDocs", + }, + "mutualTLS": { + "description": "Cert must be signed by example.com CA", + "type": "mutualTLS", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "security": [ + { + "basic": [], + }, + { + "apiKey": [], + }, + { + "JWT-bearer": [], + }, + { + "mutualTLS": [], + }, + { + "OAuth2": [ + "write:pets", + "read:pets", + ], + }, + ], + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`type: mutualTLS\`.", + "pointer": "#/components/securitySchemes/mutualTLS/type", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.1/servers.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "servers": [ + { + "description": "Run locally.", + "url": "/v1", + }, + { + "description": "Run on production server.", + "url": "https://production.com/v1", + }, + { + "description": "The production API server", + "url": "https://{username}.gigantic-server.com:{port}/{basePath}", + "variables": { + "basePath": { + "default": "v2", + }, + "port": { + "default": "8443", + "enum": [ + "8443", + "443", + ], + }, + "username": { + "default": "demo", + "description": "A user-specific subdomain. Use \`demo\` for a free sandbox environment.", + }, + }, + }, + ], + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/specification-extensions.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "x-tensions": "specification extensions are prefixed with \`x-\`", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/style-defaults.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "cookie_form": { + "in": "cookie", + "name": "cookie_form", + "schema": {}, + "x-comment": "expecting defaults: required=false, deprecated=false, style=form, explode=true, allowReserved=false", + }, + "cookie_media_type": { + "content": { + "text/*": { + "schema": {}, + }, + }, + "in": "cookie", + "name": "cookie_media_type", + "x-comment": "expecting defaults: required=false, deprecated=false", + }, + "encoding_object_defaults": { + "content": { + "encoding_object_defaults": { + "encoding": { + "allowReserved": { + "allowReserved": true, + "x-comment": "expecting default: style=form, explode=true", + }, + "explode": { + "explode": false, + "x-comment": "expecting defaults: style=form, allowReserved=false", + }, + "no_styles": { + "x-comment": "style, explode and allowReserved are not present, so contentType is used; no defaults expected as default contentType cannot be determined by the schema", + }, + "style_form": { + "style": "form", + "x-comment": "expecting defaults: explode=true, allowReserved=false", + }, + "style_spaceDelimited": { + "style": "spaceDelimited", + "x-comment": "expecting defaults: explode=false, allowReserved=false", + }, + }, + }, + }, + "in": "path", + "name": "encoding_object_defaults", + }, + "header": { + "in": "path", + "name": "header", + "required": true, + "schema": {}, + "x-comment": "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false", + }, + "path_label": { + "in": "path", + "name": "path_label", + "required": true, + "schema": {}, + "style": "label", + "x-comment": "expecting defaults: deprecated=false, explode=false, allowReserved=false", + }, + "path_matrix": { + "in": "path", + "name": "path_matrix", + "required": true, + "schema": {}, + "style": "matrix", + "x-comment": "expecting defaults: deprecated=false, explode=false, allowReserved=false", + }, + "path_media_type": { + "content": { + "text/*": { + "schema": {}, + }, + }, + "in": "path", + "name": "path_media-type", + "required": true, + "x-comment": "expecting defaults: deprecated=false", + }, + "path_simple": { + "in": "path", + "name": "path_simple", + "required": true, + "schema": {}, + "x-comment": "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false", + }, + "query_deepObject": { + "in": "query", + "name": "query_deepObject", + "schema": {}, + "style": "deepObject", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, allowReserved=false", + }, + "query_form": { + "in": "query", + "name": "query_form", + "schema": {}, + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, style=form, explode=true, allowReserved=false", + }, + "query_media_type": { + "content": { + "text/*": { + "schema": {}, + }, + }, + "in": "query", + "name": "query_media_type", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false", + }, + "query_pipeDelimited": { + "in": "query", + "name": "query_pipeDelimited", + "schema": {}, + "style": "pipeDelimited", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false", + }, + "query_spaceDelimited": { + "in": "query", + "name": "query_spaceDelimited", + "schema": {}, + "style": "spaceDelimited", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false", + }, + }, + }, + "info": { + "title": "various permutations of parameter objects, with non-required values left to their defaults", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/tag-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "tags": [ + { + "description": "Pets operations", + "name": "pet", + }, + { + "description": "Operations available to external consumers", + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "name": "external", + }, + ], + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/valid_schema_types.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "anything_boolean": {}, + "anything_object": {}, + "nothing_boolean": { + "not": {}, + }, + "nothing_object": { + "not": {}, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": { + "document": { + "components": { + "schemas": { + "anything_boolean": true, + "anything_object": {}, + "nothing_boolean": false, + "nothing_object": { + "not": {}, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.1/webhook-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + }, + }, + }, + "info": { + "title": "Webhook Example", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "x-webhooks": { + "newPet": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + "description": "Information about a new pet in the system", + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully", + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/callback-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "callbacks": { + "myCallback": { + "{$request.query.queryUrl}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + "transactionCallback": { + "http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + }, + "schemas": { + "SomePayload": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "callbacks": { + "myCallback": { + "{$request.query.queryUrl}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + "transactionCallback": { + "http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + }, + "schemas": { + "SomePayload": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/comp_pathitems.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "pathItems": {}, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/components-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "limitParam": { + "description": "max records to return", + "in": "query", + "name": "limit", + "required": true, + "schema": { + "format": "int32", + "type": "integer", + }, + }, + "skipParam": { + "description": "number of items to skip", + "in": "query", + "name": "skip", + "required": true, + "schema": { + "format": "int32", + "type": "integer", + }, + }, + }, + "responses": { + "GeneralError": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GeneralError", + }, + }, + }, + "description": "General Error", + }, + "IllegalInput": { + "description": "Illegal input for operation.", + }, + "NotFound": { + "description": "Entity not found.", + }, + }, + "schemas": { + "Category": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + }, + "type": "object", + }, + "GeneralError": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "type": "object", + }, + "Tag": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + }, + "type": "object", + }, + }, + "securitySchemes": { + "api_key": { + "in": "header", + "name": "api-key", + "type": "apiKey", + }, + "petstore_auth": { + "flows": { + "implicit": { + "authorizationUrl": "https://example.org/api/oauth/dialog", + "scopes": { + "read:pets": "read your pets", + "write:pets": "modify pets in your account", + }, + }, + }, + "type": "oauth2", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "parameters": { + "limitParam": { + "description": "max records to return", + "in": "query", + "name": "limit", + "required": true, + "schema": { + "format": "int32", + "type": "integer", + }, + }, + "skipParam": { + "description": "number of items to skip", + "in": "query", + "name": "skip", + "required": true, + "schema": { + "format": "int32", + "type": "integer", + }, + }, + }, + "responses": { + "GeneralError": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GeneralError", + }, + }, + }, + "description": "General Error", + }, + "IllegalInput": { + "description": "Illegal input for operation.", + }, + "NotFound": { + "description": "Entity not found.", + }, + }, + "schemas": { + "Category": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + }, + "type": "object", + }, + "GeneralError": { + "properties": { + "code": { + "format": "int32", + "type": "integer", + }, + "message": { + "type": "string", + }, + }, + "type": "object", + }, + "Tag": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + }, + "type": "object", + }, + }, + "securitySchemes": { + "api_key": { + "in": "header", + "name": "api-key", + "type": "apiKey", + }, + "petstore_auth": { + "flows": { + "implicit": { + "authorizationUrl": "https://example.org/api/oauth/dialog", + "scopes": { + "read:pets": "read your pets", + "write:pets": "modify pets in your account", + }, + }, + }, + "type": "oauth2", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/example-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "examples": { + "confirmation-success": {}, + "zip-example": {}, + }, + "parameters": { + "with-example": { + "examples": { + "zip-example": { + "$ref": "#/components/examples/zip-example", + }, + }, + "in": "query", + "name": "zipCode", + "schema": { + "format": "zip-code", + "type": "string", + }, + }, + }, + "requestBodies": { + "with-example": { + "content": { + "application/json": { + "examples": { + "bar": { + "summary": "A bar example", + "value": { + "bar": "baz", + }, + }, + "foo": { + "summary": "A foo example", + "value": { + "foo": "bar", + }, + }, + }, + "schema": { + "$ref": "#/components/schemas/Address", + }, + }, + "application/xml": { + "examples": { + "xmlExample": { + "externalValue": "https://example.org/examples/address-example.xml", + "summary": "This is an example in XML", + }, + }, + }, + "text/plain": { + "examples": { + "textExample": { + "externalValue": "https://foo.bar/examples/address-example.txt", + "summary": "This is a text example", + }, + }, + }, + }, + }, + }, + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "confirmation-success": { + "$ref": "#/components/examples/confirmation-success", + }, + }, + "schema": { + "$ref": "#/components/schemas/SuccessResponse", + }, + }, + "application/x-www-form-urlencoded": { + "encoding": { + "jsonValue": { + "contentType": "application/json", + }, + }, + "examples": { + "jsonFormValue": { + "dataValue": "json", + "description": "The JSON string "json" as a form value", + "serializedValue": "jsonValue=%22json%22", + }, + }, + "schema": { + "properties": { + "jsonValue": { + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "your car appointment has been booked", + }, + }, + "schemas": { + "Address": {}, + "SuccessResponse": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.2.0", + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.1.2 applies \`encoding\` only to request bodies.", + "pointer": "#/components/responses/200/content/application~1x-www-form-urlencoded/encoding", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.2/header-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "headers": { + "ETag": { + "content": { + "text/plain": { + "schema": { + "pattern": "^"", + "type": "string", + }, + }, + }, + "required": true, + }, + "Reference": { + "$ref": "#/components/headers/ETag", + }, + "Style": { + "explode": true, + "schema": { + "items": {}, + "type": "array", + }, + "style": "simple", + }, + "X-Rate-Limit-Limit": { + "deprecated": false, + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "headers": { + "ETag": { + "content": { + "text/plain": { + "schema": { + "pattern": "^"", + "type": "string", + }, + }, + }, + "required": true, + }, + "Reference": { + "$ref": "#/components/headers/ETag", + }, + "Style": { + "explode": true, + "schema": { + "type": "array", + }, + "style": "simple", + }, + "X-Rate-Limit-Limit": { + "deprecated": false, + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/info-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "info": { + "contact": { + "email": "support@example.com", + "name": "API Support", + "url": "https://www.example.com/support", + }, + "description": "This is an example server for a pet store.", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + }, + "termsOfService": "https://example.com/terms/", + "title": "Example Pet Store App", + "version": "1.0.1", + }, + "openapi": "3.0.4", + "paths": {}, + "x-oai-$self": "https://example.com/openapi", + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "info": { + "contact": { + "email": "support@example.com", + "name": "API Support", + "url": "https://www.example.com/support", + }, + "description": "This is an example server for a pet store.", + "license": { + "name": "Apache 2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html", + }, + "summary": "A pet store manager.", + "termsOfService": "https://example.com/terms/", + "title": "Example Pet Store App", + "version": "1.0.1", + }, + "openapi": "3.1.2", + "x-oai-$self": "https://example.com/openapi", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/info_summary.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "summary": "My lovely API", + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/json_schema_dialect.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "WithDollarSchema": {}, + }, + }, + "info": { + "license": { + "name": "Apache 2.0", + "x-oai-license-identifier": "Apache-2.0", + }, + "title": "My API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "WithDollarSchema": { + "$id": "locked-metaschema", + "$schema": "https://spec.openapis.org/oas/3.1/dialect/base", + }, + }, + }, + "info": { + "license": { + "identifier": "Apache-2.0", + "name": "Apache 2.0", + }, + "summary": "Testing jsonSchemaDialect", + "title": "My API", + "version": "1.0.0", + }, + "jsonSchemaDialect": "https://spec.openapis.org/oas/3.1/dialect/base", + "openapi": "3.1.2", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/license_identifier.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "license": { + "name": "Apache", + "x-oai-license-identifier": "Apache-2.0", + }, + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "license": { + "identifier": "Apache-2.0", + "name": "Apache", + }, + "summary": "My lovely API", + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/link-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/users/{id}": { + "get": { + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "uuid": { + "format": "uuid", + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "description": "the user being returned", + "links": { + "UserRepositories": { + "operationRef": "#/paths/~12.0~1repositories~1%7Busername%7D/get", + "parameters": { + "username": "$response.body#/username", + }, + }, + "UserRepositories2": { + "operationRef": "https://na2.gigantic-server.com/#/paths/~12.0~1repositories~1%7Busername%7D/get", + "parameters": { + "username": "$response.body#/username", + }, + }, + "address": { + "operationId": "getUserAddress", + "parameters": { + "userid": "$request.path.id", + }, + }, + "address2": { + "operationId": "getUserAddressByUUID", + "parameters": { + "userUuid": "$response.body#/uuid", + }, + }, + "withBody": { + "operationId": "queryUserWithBody", + "requestBody": { + "userId": "$request.path.id", + }, + }, + }, + }, + }, + }, + "parameters": [ + { + "description": "the user identifier, as userId", + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + }, + "/users/{userid}/address": { + "get": { + "operationId": "getUserAddress", + "responses": { + "200": { + "description": "the user's address", + }, + }, + }, + "parameters": [ + { + "description": "the user identifier, as userId", + "in": "path", + "name": "userid", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/media-type-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "examples": { + "frog-example": {}, + }, + "mediaTypes": { + "StreamingPets": { + "description": +"Streaming sequence of JSON pet representations, +suitable for use with any of the streaming JSON +media types. +" +, + "itemSchema": { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + "schemas": { + "Address": {}, + "Pet": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.2.0", + "paths": { + "/something": { + "put": { + "requestBody": { + "content": { + "application/json": { + "examples": { + "cat": { + "summary": "An example of a cat", + "value": { + "breed": "Persian", + "color": "White", + "gender": "male", + "name": "Fluffy", + "petType": "Cat", + }, + }, + "dog": { + "summary": "An example of a dog with a cat's name", + "value": { + "breed": "Mixed", + "color": "Black", + "gender": "Female", + "name": "Puma", + "petType": "Dog", + }, + }, + "frog": { + "$ref": "#/components/examples/frog-example", + }, + }, + "schema": { + "$ref": "#/components/schemas/Pet", + }, + }, + "application/jsonl": { + "$ref": "#/components/mediaTypes/StreamingPets", + }, + "application/x-ndjson": { + "$ref": "#/components/mediaTypes/StreamingPets", + }, + "application/x-www-form-urlencoded": { + "encoding": { + "icon": { + "contentType": "image/png, image/jpeg", + }, + }, + "schema": { + "properties": { + "address": { + "properties": {}, + "type": "object", + }, + "icon": { + "contentEncoding": "base64url", + "type": "string", + }, + "id": { + "format": "uuid", + "type": "string", + }, + }, + "type": "object", + }, + }, + "application/xml": { + "schema": { + "properties": { + "attr": { + "type": "string", + "xml": { + "attribute": true, + }, + }, + "attributeNode": { + "type": "string", + "xml": { + "nodeType": "attribute", + }, + }, + "bar": { + "items": { + "type": "number", + }, + "type": "array", + "xml": { + "wrapped": true, + }, + }, + "cdataNode": { + "type": "string", + "xml": { + "nodeType": "cdata", + }, + }, + "elementNode": { + "$ref": "#/components/schemas/Pet", + "xml": { + "nodeType": "element", + }, + }, + "foo": { + "type": "string", + "xml": { + "name": "Foo", + "namespace": "https://example.com", + "prefix": "example", + }, + }, + "noneNode": { + "type": "object", + "xml": { + "nodeType": "none", + }, + }, + "textNode": { + "type": "string", + "xml": { + "nodeType": "text", + }, + }, + }, + "type": "object", + }, + }, + "multipart/form-data": { + "encoding": { + "addresses": { + "contentType": "application/xml; charset=utf-8", + }, + "forCoverage": { + "allowReserved": true, + "explode": false, + "style": "form", + }, + "forCoverage2": { + "explode": true, + "style": "spaceDelimited", + }, + "nested1": { + "contentType": "multipart/form-data", + "encoding": { + "inner": {}, + }, + }, + "nested2": { + "contentType": "multipart/mixed", + "itemEncoding": {}, + "prefixEncoding": [ + {}, + ], + }, + "profileImage": { + "contentType": "image/png, image/jpeg", + "headers": { + "X-Rate-Limit-Limit": { + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + }, + "schema": { + "properties": { + "addresses": { + "description": "addresses in XML format", + "items": { + "$ref": "#/components/schemas/Address", + }, + "type": "array", + }, + "forCoverage": { + "type": "string", + }, + "forCoverage2": { + "type": "string", + }, + "id": { + "format": "uuid", + "type": "string", + }, + "nested1": { + "type": "object", + }, + "nested2": { + "type": "array", + }, + "profileImage": { + "format": "binary", + "type": "string", + }, + }, + "type": "object", + }, + }, + "multipart/related": { + "itemEncoding": { + "contentType": "text/plain", + }, + "prefixEncoding": [ + { + "headers": { + "Content-Location": { + "schema": { + "type": "string", + }, + }, + }, + }, + ], + "schema": { + "type": "array", + }, + }, + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.1.2 has no \`prefixEncoding\`.", + "pointer": "#/paths/~1something/put/requestBody/content/multipart~1form-data/encoding/nested2/prefixEncoding", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.2/mega.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": "as 3.1.0", + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`type: mutualTLS\`.", + "pointer": "#/components/securitySchemes/mtls/type", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "pathItems": { + "myPathItem": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/Foo", + }, + ], + "discriminator": { + "mapping": { + "foo": "Foo", + }, + "propertyName": "type", + "x-extension": true, + }, + "externalDocs": { + "description": "More docs!", + "url": "https://example.com/elsewhere.html", + }, + "myArbitraryKeyword": true, + "properties": { + "arr": { + "$comment": "Array without items keyword", + "type": "array", + }, + "either": { + "type": [ + "string", + "null", + ], + }, + "int": { + "exclusiveMaximum": 100, + "exclusiveMinimum": 0, + "type": "integer", + }, + "none": { + "type": "null", + }, + "type": { + "type": "string", + }, + }, + "type": "object", + }, + }, + }, + "required": true, + }, + }, + }, + }, + "schemas": { + "Foo": { + "properties": { + "type": { + "const": "foo", + }, + }, + "type": "object", + }, + }, + "securitySchemes": { + "mtls": { + "type": "mutualTLS", + }, + }, + }, + "info": { + "license": { + "identifier": "Apache-2.0", + "name": "Apache 2.0", + }, + "summary": "My API's summary", + "title": "My API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/": { + "get": { + "parameters": [], + }, + }, + "/{pathTest}": {}, + }, + "webhooks": { + "myWebhook": { + "$ref": "#/components/pathItems/myPathItem", + "description": "Overriding description", + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/minimal_comp.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/minimal_hooks.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "x-webhooks": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "webhooks": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/minimal_paths.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/non-oauth-scopes.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": "as 3.1.0", + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 lists roles only for \`oauth2\` and \`openIdConnect\` schemes.", + "pointer": "#/paths/~1users/get/security/0/bearerAuth", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "securitySchemes": { + "bearerAuth": { + "bearerFormat": "jwt", + "description": "note: non-oauth scopes are not defined at the securityScheme level", + "scheme": "bearer", + "type": "http", + }, + }, + }, + "info": { + "title": "Non-oAuth Scopes example", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/users": { + "get": { + "security": [ + { + "bearerAuth": [ + "read:users", + "public", + ], + }, + ], + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/operation-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/pets/{id}": { + "put": { + "operationId": "updatePetWithForm", + "parameters": [ + { + "description": "ID of pet that needs to be updated", + "in": "path", + "name": "petId", + "required": true, + "schema": { + "type": "string", + }, + }, + ], + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "properties": { + "name": { + "description": "Updated name of the pet", + "type": "string", + }, + "status": { + "description": "Updated status of the pet", + "type": "string", + }, + }, + "required": [ + "status", + ], + "type": "object", + }, + }, + }, + }, + "responses": { + "200": { + "content": { + "application/json": {}, + "application/xml": {}, + }, + "description": "Pet updated.", + }, + "405": { + "content": { + "application/json": {}, + "application/xml": {}, + }, + "description": "Method Not Allowed", + }, + }, + "security": [ + { + "petstore_auth": [ + "write:pets", + "read:pets", + ], + }, + ], + "summary": "Updates a pet in the store with form data", + "tags": [ + "pet", + ], + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/parameter-object-cookie-form-allowReserved.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "parameters": { + "style_cookie": { + "in": "cookie", + "name": "my_cookie_cookie", + "schema": {}, + "style": "cookie", + }, + "style_form": { + "allowReserved": true, + "in": "cookie", + "name": "my_form_cookie", + "schema": {}, + }, + }, + }, + "info": { + "title": "allowReserved only permitted with in and style values that percent-encode", + "version": "1.0.0", + }, + "openapi": "3.2.0", + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.1.2 has no \`style: cookie\`.", + "pointer": "#/components/parameters/style_cookie/style", + }, + { + "message": "OpenAPI 3.1.2 applies \`allowReserved\` only to \`in: query\`.", + "pointer": "#/components/parameters/style_form/allowReserved", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.2/parameter-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.2.0", + "paths": { + "/user": { + "parameters": [ + { + "content": { + "application/json": { + "example": { + "flag": null, + "numbers": [ + 1, + 2, + ], + }, + "schema": { + "type": "object", + }, + }, + }, + "in": "querystring", + "name": "json", + }, + ], + }, + "/user/{username}": { + "parameters": [ + { + "description": "token to be passed as a header", + "explode": false, + "in": "header", + "name": "token", + "required": true, + "schema": { + "items": { + "format": "int64", + "type": "integer", + }, + "type": "array", + }, + "style": "simple", + }, + { + "description": "usernames to fetch", + "explode": false, + "in": "path", + "name": "usernames", + "required": true, + "schema": { + "type": "array", + }, + }, + { + "description": "IDs of the object to fetch", + "explode": true, + "in": "query", + "name": "id", + "required": false, + "schema": { + "items": { + "type": "string", + }, + "type": "array", + }, + "style": "form", + }, + { + "in": "query", + "name": "freeForm", + "schema": { + "additionalProperties": { + "type": "integer", + }, + "type": "object", + }, + "style": "form", + }, + { + "content": { + "application/json": { + "schema": { + "properties": { + "lat": { + "type": "number", + }, + "long": { + "type": "number", + }, + }, + "required": [ + "lat", + "long", + ], + "type": "object", + }, + }, + }, + "in": "query", + "name": "coordinates", + }, + { + "explode": false, + "in": "cookie", + "name": "my_cookie1", + "schema": {}, + "style": "form", + }, + { + "explode": true, + "in": "cookie", + "name": "my_cookie2", + "schema": {}, + "style": "cookie", + }, + ], + }, + }, + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.1.2 has no \`style: cookie\`.", + "pointer": "#/paths/~1user~1{username}/parameters/6/style", + }, + { + "message": "OpenAPI 3.1.2 has no \`in: querystring\`.", + "pointer": "#/paths/~1user/parameters/0/in", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.2/parameter-object-path-allowReserved.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "path": { + "in": "path", + "name": "my-path", + "required": true, + "schema": {}, + }, + }, + }, + "info": { + "title": "api", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "parameters": { + "path": { + "in": "path", + "name": "my-path", + "required": true, + "schema": {}, + }, + }, + }, + "info": { + "title": "api", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/parameter-object-query-allowReserved.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "parameters": { + "my_query": { + "allowReserved": true, + "in": "query", + "name": "my_query", + "schema": {}, + }, + }, + }, + "info": { + "title": "allowReserved only permitted with in and style values that percent-encode", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "parameters": { + "my_query": { + "allowReserved": true, + "in": "query", + "name": "my_query", + "schema": {}, + }, + }, + }, + "info": { + "title": "allowReserved only permitted with in and style values that percent-encode", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/path-item-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "ErrorModel": {}, + "Pet": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/pets/{id}": { + "get": { + "description": "Returns pets based on ID", + "operationId": "getPetsById", + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "items": { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + }, + "description": "pet response", + }, + "default": { + "content": { + "text/html": { + "schema": { + "$ref": "#/components/schemas/ErrorModel", + }, + }, + }, + "description": "error payload", + }, + }, + "summary": "Find pets by ID", + }, + "parameters": [ + { + "description": "ID of pet to use", + "in": "path", + "name": "id", + "required": true, + "schema": { + "items": { + "type": "string", + }, + "type": "array", + }, + "style": "simple", + }, + ], + "x-oai-additionalOperations": { + "COPY": { + "description": "Copies pet information based on ID", + "operationId": "copyPetsById", + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "items": { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + }, + "description": "pet response", + }, + "default": { + "content": { + "text/html": { + "schema": { + "$ref": "#/components/schemas/ErrorModel", + }, + }, + }, + "description": "error payload", + }, + }, + "summary": "Copies pets by ID", + }, + "QUERY": { + "description": "Returns pets based on ID", + "operationId": "queryPetsById", + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "items": { + "$ref": "#/components/schemas/Pet", + }, + "type": "array", + }, + }, + }, + "description": "pet response", + }, + "default": { + "content": { + "text/html": { + "schema": { + "$ref": "#/components/schemas/ErrorModel", + }, + }, + }, + "description": "error payload", + }, + }, + "summary": "Find pets by ID", + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/path_item_servers_parameters.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": "as 3.1.0", + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/delete", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/options", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/head", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/patch", + }, + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1things/trace", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "callbacks": { + "transactionCallback": { + "http://notificationServer.com?transactionId={$request.body#/id}&email={$request.body#/email}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + }, + "examples": { + "ThingExample": { + "description": "A thing", + "summary": "A thing", + "value": { + "id": 1, + "name": "Thing", + }, + }, + }, + "links": { + "ThingLink": { + "description": "A link to a thing", + "operationId": "getThing", + "parameters": { + "thingId": "$response.body#/id", + }, + "server": { + "url": "https://things.example.com", + }, + }, + "ThingyLink": { + "$ref": "#/components/links/ThingLink", + }, + }, + "parameters": { + "biscuit": { + "in": "cookie", + "name": "biscuit", + "schema": { + "type": "string", + }, + "style": "form", + }, + "limit": { + "allowEmptyValue": false, + "allowReserved": false, + "deprecated": true, + "description": "The maximum number of list items to return", + "in": "query", + "name": "limit", + "required": false, + "schema": { + "minimum": 0, + "type": "integer", + }, + }, + }, + "requestBodies": { + "ThingRequestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + }, + }, + }, + }, + }, + "responses": { + "ThingResponse": { + "content": { + "application/json": { + "schema": { + "type": "object", + }, + }, + }, + "description": "A thing", + }, + }, + "schemas": { + "SomePayload": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/things": { + "delete": {}, + "get": { + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "parameters": [ + { + "$ref": "#/components/parameters/biscuit", + "description": "The maximum number of things to return", + "summary": "The maximum number of things to return", + }, + ], + "responses": { + "default": { + "description": "A list of things", + }, + }, + "servers": [ + { + "url": "https://things.example.com", + }, + ], + "summary": "Get a list of things", + }, + "head": {}, + "options": {}, + "patch": {}, + "post": { + "callbacks": { + "myCallback": { + "{$request.query.queryUrl}": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SomePayload", + }, + }, + }, + "description": "Callback payload", + }, + "responses": { + "200": { + "description": "callback successfully processed", + }, + }, + }, + }, + }, + "transactionCallback": { + "$ref": "#/components/callbacks/transactionCallback", + }, + }, + "deprecated": false, + "requestBody": { + "$ref": "#/components/requestBodies/ThingRequestBody", + }, + "responses": { + "201": { + "$ref": "#/components/responses/ThingResponse", + }, + }, + }, + "servers": [ + { + "url": "https://things.example.com", + }, + ], + "summary": "Lots of things", + "trace": {}, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/path_no_response.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": "as 3.1.0", + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1/get", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/": { + "get": {}, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/path_var_empty_pathitem.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/{var}": {}, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/paths-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "pet": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/pets": { + "get": { + "description": "Returns all pets from the system that the user has access to", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/pet", + }, + "type": "array", + }, + }, + }, + "description": "A list of pets.", + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/request-body-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": "as 3.1.0", + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.0.4 requires \`responses\`.", + "pointer": "#/paths/~1something/put", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "User": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/something": { + "put": { + "requestBody": { + "content": { + "*/*": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.whatever", + "summary": "User example in other format", + }, + }, + }, + "application/json": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.json", + "summary": "User example", + }, + }, + "schema": { + "$ref": "#/components/schemas/User", + }, + }, + "application/xml": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.xml", + "summary": "User example in XML", + }, + }, + "schema": { + "$ref": "#/components/schemas/User", + }, + }, + "text/plain": { + "examples": { + "user": { + "externalValue": "https://foo.bar/examples/user-example.txt", + "summary": "User example in plain text", + }, + }, + }, + }, + "description": "user to add to the system", + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/response-object-examples.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "responses": { + "complex-object-array": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/VeryComplexType", + }, + "type": "array", + }, + }, + }, + "description": "A complex object array response", + "x-oai-summary": "Complex object array", + "x-summary": "Complex object array", + }, + "no-return-value": { + "description": "object created", + }, + "plain-text-with-headers": { + "content": { + "text/plain": { + "example": "whoa!", + "schema": { + "type": "string", + }, + }, + }, + "description": "A simple string response", + "headers": { + "X-Rate-Limit-Limit": { + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + "X-Rate-Limit-Remaining": { + "description": "The number of remaining requests in the current period", + "schema": { + "type": "integer", + }, + }, + "X-Rate-Limit-Reset": { + "description": "The number of seconds left in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + "simple-string": { + "content": { + "text/plain": { + "schema": { + "type": "string", + }, + }, + }, + "description": "A simple string response", + }, + }, + "schemas": { + "VeryComplexType": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "responses": { + "complex-object-array": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/VeryComplexType", + }, + "type": "array", + }, + }, + }, + "description": "A complex object array response", + "x-oai-summary": "Complex object array", + "x-summary": "Complex object array", + }, + "no-return-value": { + "description": "object created", + }, + "plain-text-with-headers": { + "content": { + "text/plain": { + "example": "whoa!", + "schema": { + "type": "string", + }, + }, + }, + "description": "A simple string response", + "headers": { + "X-Rate-Limit-Limit": { + "description": "The number of allowed requests in the current period", + "schema": { + "type": "integer", + }, + }, + "X-Rate-Limit-Remaining": { + "description": "The number of remaining requests in the current period", + "schema": { + "type": "integer", + }, + }, + "X-Rate-Limit-Reset": { + "description": "The number of seconds left in the current period", + "schema": { + "type": "integer", + }, + }, + }, + }, + "simple-string": { + "content": { + "text/plain": { + "schema": { + "type": "string", + }, + }, + }, + "description": "A simple string response", + }, + }, + "schemas": { + "VeryComplexType": {}, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/schema-object-deprecated-example-keyword.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": { + "/user": { + "parameters": [ + { + "in": "query", + "name": "example", + "schema": { + "example": { + "flag": null, + "numbers": [ + 1, + 2, + ], + }, + "type": "object", + }, + }, + ], + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/schema.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "model": { + "properties": { + "eight": { + "description": "exclusiveMaximum true", + "exclusiveMaximum": 20, + }, + "eleven": { + "description": "x-nullable string", + "nullable": true, + "type": "string", + }, + "five": { + "description": "singular example", + "examples": [ + "exampleValue", + ], + "type": "string", + }, + "four": { + "description": "array with no items", + "type": "array", + }, + "nine": { + "description": "exclusiveMaximum false", + "maximum": 20, + }, + "one": { + "anyOf": [ + { + "type": "integer", + }, + { + "type": "string", + }, + ], + "description": "type array", + }, + "seven": { + "description": "exclusiveMinimum false", + "minimum": 10, + }, + "six": { + "description": "exclusiveMinimum true", + "exclusiveMinimum": 10, + }, + "ten": { + "description": "nullable string", + "nullable": true, + "type": "string", + }, + "three": { + "description": "type array including 'null'", + "nullable": true, + "type": "string", + }, + "twelve": { + "description": "file/binary", + }, + "two": { + "description": "type 'null'", + "type": "null", + }, + }, + "type": "object", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": {}, + }, + "loosened": { + "document": { + "components": { + "schemas": { + "model": { + "properties": { + "eight": { + "description": "exclusiveMaximum true", + "exclusiveMaximum": 20, + }, + "eleven": { + "description": "x-nullable string", + "nullable": true, + "type": "string", + }, + "five": { + "description": "singular example", + "examples": [ + "exampleValue", + ], + "type": "string", + }, + "four": { + "description": "array with no items", + "type": "array", + }, + "nine": { + "description": "exclusiveMaximum false", + "maximum": 20, + }, + "one": { + "description": "type array", + }, + "seven": { + "description": "exclusiveMinimum false", + "minimum": 10, + }, + "six": { + "description": "exclusiveMinimum true", + "exclusiveMinimum": 10, + }, + "ten": { + "description": "nullable string", + "nullable": true, + "type": "string", + }, + "three": { + "description": "type array including 'null'", + "nullable": true, + "type": "string", + }, + "twelve": { + "description": "file/binary", + }, + "two": { + "description": "type 'null'", + "type": "null", + }, + }, + "type": "object", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.0", + "paths": {}, + }, + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`null\` type.", + "pointer": "#/components/schemas/model/properties/two/type", + }, + ], + }, + "problems": [ + { + "message": "OpenAPI 3.0.4 has no \`null\` type.", + "pointer": "#/components/schemas/model/properties/two/type", + }, + ], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "model": { + "properties": { + "eight": { + "description": "exclusiveMaximum true", + "exclusiveMaximum": 20, + }, + "eleven": { + "description": "x-nullable string", + "type": [ + "string", + "null", + ], + }, + "five": { + "description": "singular example", + "examples": [ + "exampleValue", + ], + "type": "string", + }, + "four": { + "description": "array with no items", + "type": "array", + }, + "nine": { + "description": "exclusiveMaximum false", + "maximum": 20, + }, + "one": { + "description": "type array", + "type": [ + "integer", + "string", + ], + }, + "seven": { + "description": "exclusiveMinimum false", + "minimum": 10, + }, + "six": { + "description": "exclusiveMinimum true", + "exclusiveMinimum": 10, + }, + "ten": { + "description": "nullable string", + "type": [ + "string", + "null", + ], + }, + "three": { + "description": "type array including 'null'", + "type": [ + "string", + "null", + ], + }, + "twelve": { + "description": "file/binary", + }, + "two": { + "description": "type 'null'", + "type": "null", + }, + }, + "type": "object", + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/servers.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": {}, + "servers": [ + { + "description": "Run locally.", + "url": "/v1", + "x-oai-name": "local", + }, + { + "description": "Run on production server.", + "url": "https://production.com/v1", + }, + { + "description": "The production API server", + "url": "https://{username}.gigantic-server.com:{port}/{basePath}", + "variables": { + "basePath": { + "default": "v2", + }, + "port": { + "default": "8443", + "enum": [ + "8443", + "443", + ], + }, + "username": { + "default": "demo", + "description": "A user-specific subdomain. Use \`demo\` for a free sandbox environment.", + }, + }, + }, + ], + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/specification-extensions.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": {}, + "x-tensions": "specification extensions are prefixed with \`x-\`", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/style-defaults.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "mediaTypes": { + "encoding_object_defaults": { + "encoding": { + "allowReserved": { + "allowReserved": true, + "x-comment": "expecting default: style=form, explode=true", + }, + "explode": { + "explode": false, + "x-comment": "expecting defaults: style=form, allowReserved=false", + }, + "no_styles": { + "x-comment": "style, explode and allowReserved are not present, so contentType is used; no defaults expected as default contentType cannot be determined by the schema", + }, + "style_form": { + "style": "form", + "x-comment": "expecting defaults: explode=true, allowReserved=false", + }, + "style_spaceDelimited": { + "style": "spaceDelimited", + "x-comment": "expecting defaults: explode=false, allowReserved=false", + }, + }, + }, + }, + "parameters": { + "cookie_cookie": { + "in": "cookie", + "name": "cookie_cookie", + "schema": {}, + "style": "cookie", + "x-comment": "expecting defaults: required=false, deprecated=false, explode=true", + }, + "cookie_form": { + "in": "cookie", + "name": "cookie_form", + "schema": {}, + "x-comment": "expecting defaults: required=false, deprecated=false, style=form, explode=true, allowReserved=false", + }, + "cookie_media_type": { + "content": { + "text/*": { + "schema": {}, + }, + }, + "in": "cookie", + "name": "cookie_media_type", + "x-comment": "expecting defaults: required=false, deprecated=false", + }, + "header": { + "in": "path", + "name": "header", + "required": true, + "schema": {}, + "x-comment": "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false", + }, + "path_label": { + "in": "path", + "name": "path_label", + "required": true, + "schema": {}, + "style": "label", + "x-comment": "expecting defaults: deprecated=false, explode=false, allowReserved=false", + }, + "path_matrix": { + "in": "path", + "name": "path_matrix", + "required": true, + "schema": {}, + "style": "matrix", + "x-comment": "expecting defaults: deprecated=false, explode=false, allowReserved=false", + }, + "path_media_type": { + "content": { + "text/*": { + "schema": {}, + }, + }, + "in": "path", + "name": "path_media-type", + "required": true, + "x-comment": "expecting defaults: deprecated=false", + }, + "path_simple": { + "in": "path", + "name": "path_simple", + "required": true, + "schema": {}, + "x-comment": "expecting defaults: deprecated=false, style=simple, explode=false, allowReserved=false", + }, + "query_deepObject": { + "in": "query", + "name": "query_deepObject", + "schema": {}, + "style": "deepObject", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, allowReserved=false", + }, + "query_form": { + "in": "query", + "name": "query_form", + "schema": {}, + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, style=form, explode=true, allowReserved=false", + }, + "query_media_type": { + "content": { + "text/*": { + "schema": {}, + }, + }, + "in": "query", + "name": "query_media_type", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false", + }, + "query_pipeDelimited": { + "in": "query", + "name": "query_pipeDelimited", + "schema": {}, + "style": "pipeDelimited", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false", + }, + "query_spaceDelimited": { + "in": "query", + "name": "query_spaceDelimited", + "schema": {}, + "style": "spaceDelimited", + "x-comment": "expecting defaults: required=false, deprecated=false, allowEmptyValue=false, explode=false, allowReserved=false", + }, + }, + }, + "info": { + "title": "various permutations of parameter objects, with non-required values left to their defaults", + "version": "1.0.0", + }, + "openapi": "3.2.0", + }, + "loosened": "unchanged", + "problems": [ + { + "message": "OpenAPI 3.1.2 has no \`style: cookie\`.", + "pointer": "#/components/parameters/cookie_cookie/style", + }, + ], + }, +} +`; + +exports[`fixtures oai/3.2/tag-object-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": "as 3.1.0", + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": {}, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "paths": {}, + "tags": [ + { + "description": "Account update operations", + "name": "account-updates", + "x-displayName": "Account Updates", + }, + { + "description": "Operations available to the partners network", + "name": "partner", + "x-displayName": "Partner", + }, + { + "description": "Operations available to external consumers", + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com", + }, + "name": "external", + "x-displayName": "External", + }, + ], + "x-tagGroups": [ + { + "name": "Account Updates", + "tags": [ + "account-updates", + ], + }, + { + "name": "External", + "tags": [ + "partner", + "external", + ], + }, + ], + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/valid_schema_types.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "anything_boolean": {}, + "anything_object": {}, + "nothing_boolean": { + "not": {}, + }, + "nothing_object": { + "not": {}, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "anything_boolean": true, + "anything_object": {}, + "nothing_boolean": false, + "nothing_object": { + "not": {}, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "jsonSchemaDialect": "https://spec.openapis.org/oas/3.1/dialect/base", + "openapi": "3.1.2", + }, + "loosened": "unchanged", + "problems": [], + }, + "3.2.0": { + "document": { + "components": { + "schemas": { + "anything_boolean": true, + "anything_object": {}, + "nothing_boolean": false, + "nothing_object": { + "not": {}, + }, + }, + }, + "info": { + "title": "API", + "version": "1.0.0", + }, + "jsonSchemaDialect": "https://spec.openapis.org/oas/3.2/dialect/2026-02-26", + "openapi": "3.2.0", + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; + +exports[`fixtures oai/3.2/webhook-example.yaml 1`] = ` +{ + "3.0.0": "as 3.0.1", + "3.0.1": "as 3.0.2", + "3.0.2": "as 3.0.3", + "3.0.3": "as 3.0.4", + "3.0.4": { + "document": { + "components": { + "schemas": { + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + }, + }, + }, + "info": { + "title": "Webhook Example", + "version": "1.0.0", + }, + "openapi": "3.0.4", + "paths": {}, + "x-webhooks": { + "newPet": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + "description": "Information about a new pet in the system", + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully", + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, + "3.1.0": "as 3.1.1", + "3.1.1": "as 3.1.2", + "3.1.2": { + "document": { + "components": { + "schemas": { + "Pet": { + "properties": { + "id": { + "format": "int64", + "type": "integer", + }, + "name": { + "type": "string", + }, + "tag": { + "type": "string", + }, + }, + "required": [ + "id", + "name", + ], + }, + }, + }, + "info": { + "title": "Webhook Example", + "version": "1.0.0", + }, + "openapi": "3.1.2", + "webhooks": { + "newPet": { + "post": { + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Pet", + }, + }, + }, + "description": "Information about a new pet in the system", + }, + "responses": { + "200": { + "description": "Return a 200 status to indicate that the data was received successfully", + }, + }, + }, + }, + }, + }, + "loosened": "unchanged", + "problems": [], + }, +} +`; diff --git a/packages/redocly-plugin-downlevel/src/builders/drop-fields.ts b/packages/redocly-plugin-downlevel/src/builders/drop-fields.ts new file mode 100644 index 00000000..d997a877 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/builders/drop-fields.ts @@ -0,0 +1,21 @@ +import type { Transform } from "../layer.ts"; + +/** + * Removes fields the lower version does not define and whose absence changes + * nothing a reader validates: annotations, and hints a reader may ignore. + * + * Keyed by Redocly node type, so a field is recognised by the object it is on. + */ +export function dropFields(fields: Record>): Transform { + return () => + Object.fromEntries( + Object.entries(fields).map(([type, names]) => [ + type, + { + leave: (node: Record) => { + for (const name of names) delete node[name]; + } + } + ]) + ); +} diff --git a/packages/redocly-plugin-downlevel/src/builders/extend-fields.ts b/packages/redocly-plugin-downlevel/src/builders/extend-fields.ts new file mode 100644 index 00000000..33fba12a --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/builders/extend-fields.ts @@ -0,0 +1,29 @@ +import type { Transform } from "../layer.ts"; + +/** + * Moves fields the lower version does not define into every extension that + * carries the same thing for readers of that version, keeping any the + * description already sets. + * + * Keyed by Redocly node type, then by field, so a field is recognised by the + * object it is on. + * + * https://spec.openapis.org/registry/extension/index.html + */ +export function extendFields(fields: Record>>): Transform { + return () => + Object.fromEntries( + Object.entries(fields).map(([type, extensions]) => [ + type, + { + leave: (node: Record) => { + for (const [name, targets] of Object.entries(extensions)) { + if (!(name in node)) continue; + for (const target of targets) node[target] ??= structuredClone(node[name]); + delete node[name]; + } + } + } + ]) + ); +} diff --git a/packages/redocly-plugin-downlevel/src/builders/inline-components.ts b/packages/redocly-plugin-downlevel/src/builders/inline-components.ts new file mode 100644 index 00000000..f7e8537c --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/builders/inline-components.ts @@ -0,0 +1,36 @@ +import type { Node, Transform } from "../layer.ts"; +import { resolvePointer } from "../pointer.ts"; + +/** + * Replaces every reference into `components[section]` with a copy of its target, + * then removes the section, for a component type the lower version lacks. + */ +export function inlineComponents(section: string): Transform { + return () => { + let root: Node; + + return { + Root: { + enter: (document) => { + root = document; + }, + leave: (document) => { + const components = document.components as Node | undefined; + if (components) delete components[section]; + } + }, + ref: { + enter: (node) => { + const reference = String(node.$ref); + if (!reference.startsWith(`#/components/${section}/`)) return; + + const target = resolvePointer(root, reference); + if (!target || typeof target !== "object") return; + + delete node.$ref; + Object.assign(node, structuredClone(target)); + } + } + }; + }; +} diff --git a/packages/redocly-plugin-downlevel/src/builders/report-fields.ts b/packages/redocly-plugin-downlevel/src/builders/report-fields.ts new file mode 100644 index 00000000..4173c385 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/builders/report-fields.ts @@ -0,0 +1,33 @@ +import type { UserContext } from "@redocly/openapi-core"; + +import type { Transform } from "../layer.ts"; + +type Fields = Record | true>; + +/** + * Reports fields, or particular values of them, that change what a reader + * accepts and that the lower version has no way to say. + * + * Keyed by Redocly node type, then by field: `true` reports the field whatever + * it holds, an array reports only those values. + */ +export function reportFields(fields: Record): Transform { + return ({ version }) => + Object.fromEntries( + Object.entries(fields).map(([type, reported]) => [ + type, + { + enter: (node: Record, { report, location }: UserContext) => { + for (const name of Object.keys(node)) { + const values = reported[name]; + if (values === undefined) continue; + if (values === true) + report({ message: `OpenAPI ${version} has no \`${name}\`.`, location: location.child(name) }); + else if (values.includes(node[name])) + report({ message: `OpenAPI ${version} has no \`${name}: ${String(node[name])}\`.`, location: location.child(name) }); + } + } + } + ]) + ); +} diff --git a/packages/redocly-plugin-downlevel/src/decorator.ts b/packages/redocly-plugin-downlevel/src/decorator.ts new file mode 100644 index 00000000..5a709ed7 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/decorator.ts @@ -0,0 +1,120 @@ +import { normalizeTypes, normalizeVisitors, unescapePointerFragment, walkDocument } from "@redocly/openapi-core"; +import type { Location, LocationObject, Oas3Decorator, Oas3Visitor, WalkContext } from "@redocly/openapi-core"; + +import type { Layer, Transform } from "./layer.ts"; +import { layers } from "./layers.ts"; + +export interface Options { + /** + * The version to write: a release such as `3.0.3`, or a minor version such as + * `3.0` for its latest release. + */ + version?: string; + /** + * Replace every `oneOf` and `anyOf` with one schema that accepts everything + * its members accept, for readers that take no unions. + */ + loosenUnions?: boolean; +} + +/** + * Maps a location in the bundled document back to the file it was written in, + * through the deepest node on its path that bundling walked. + */ +function locate(root: unknown, origins: WeakMap, { pointer }: LocationObject): Location | undefined { + const parts = (pointer ?? "#/").slice(2).split("/").filter(Boolean).map(unescapePointerFragment); + let node = root; + let found: Location | undefined; + let depth = 0; + + for (const [index, part] of [undefined, ...parts].entries()) { + if (index > 0) node = (node as Record | undefined)?.[part as string]; + if (!node || typeof node !== "object") break; + + const origin = origins.get(node); + if (origin) [found, depth] = [origin, index]; + } + + return depth < parts.length ? found?.child(parts.slice(depth)) : found; +} + +function reaches(version: string, target: string) { + return version === target || (target.split(".").length === 2 && version.startsWith(`${target}.`)); +} + +function plan(from: string, target: string): Array | undefined { + const chain: Array = []; + let version = from; + + while (!reaches(version, target)) { + const layer = layers.find((candidate) => candidate.version === version); + if (!layer) return undefined; + + chain.push(layer); + version = layer.writes; + } + + return chain; +} + +/** + * Rewrites the bundled description as an earlier OpenAPI version, one release + * at a time, for readers that cannot take the version it is written in. + * + * Runs once bundling has finished, so every reference is internal. Each layer + * runs all its checks, then its transforms, and the run ends at the first layer + * that reports anything. + */ +export const openapi: Oas3Decorator = ({ version: target, loosenUnions = false }: Options) => { + const origins = new WeakMap(); + + return { + any: { + enter: (node, { location }) => { + if (node && typeof node === "object") origins.set(node, location); + } + }, + Root: { + leave: (root, { report, location, config }) => { + if (typeof target === "number") return report({ message: "Quote `version`: YAML reads an unquoted 3.0 as the number 3.", location }); + if (!target) return report({ message: "Set `version` to the OpenAPI version to write, such as `\"3.0\"`.", location }); + + const from = String(root.openapi); + const chain = plan(from, target); + if (!chain) + return report({ + message: `Cannot downlevel OpenAPI ${from} to ${target}.`, + location: location.child("openapi") + }); + + for (const layer of chain) { + const types = normalizeTypes(layer.types); + + const run = (transform: Transform) => { + const context: WalkContext = { problems: [], specVersion: layer.specVersion, config, visitorsData: {} }; + + walkDocument({ + document: { source: location.source, parsed: root }, + rootType: types.Root, + normalizedVisitors: normalizeVisitors( + [{ ruleId: "downlevel/openapi", severity: "error", visitor: transform({ version: layer.writes, loosenUnions }) as Oas3Visitor }], + types + ), + resolvedRefMap: new Map(), + ctx: context + }); + + for (const problem of context.problems) + report({ message: problem.message, location: locate(root, origins, problem.location[0]) ?? problem.location }); + return context.problems.length; + }; + + if (layer.checks.map(run).some((count) => count > 0)) return; + for (const transform of layer.transforms) if (run(transform) > 0) return; + + root.openapi = layer.writes; + } + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/downlevel.test.ts b/packages/redocly-plugin-downlevel/src/downlevel.test.ts new file mode 100644 index 00000000..14af368f --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/downlevel.test.ts @@ -0,0 +1,91 @@ +import { mkdtempSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; + +import { bundle, createConfig } from "@redocly/openapi-core"; +import { describe, expect, test } from "bun:test"; + +import { downlevel } from "./fixture.ts"; +import plugin from "./index.ts"; + +describe("planning", () => { + test("walks every release from 3.2.1 down to 3.0.0", async () => { + const { document, problems } = await downlevel( + { + openapi: "3.2.1", + servers: [{ url: "https://example.com", name: "production" }], + components: { schemas: { A: { type: ["string", "null"] } } } + }, + { version: "3.0.0" } + ); + expect(document).toStrictEqual({ + openapi: "3.0.0", + info: { title: "fixture", version: "1" }, + servers: [{ url: "https://example.com", "x-oai-name": "production" }], + paths: {}, + components: { schemas: { A: { type: "string", nullable: true } } } + }); + expect(problems).toStrictEqual([]); + }); + + test("takes a minor version to mean its latest release", async () => { + const { document } = await downlevel({ openapi: "3.2.1" }, { version: "3.1" }); + expect(document.openapi).toBe("3.1.2"); + }); + + test("stops at an exact release", async () => { + const { document } = await downlevel({ openapi: "3.2.1", components: { schemas: { A: { type: ["string", "null"] } } } }, { version: "3.1.1" }); + expect(document.openapi).toBe("3.1.1"); + expect(document.components?.schemas).toStrictEqual({ A: { type: ["string", "null"] } }); + }); + + test("leaves a description already at the target alone", async () => { + const { document, problems } = await downlevel( + { openapi: "3.0.3", components: { schemas: { A: { oneOf: [{ type: "string" }, { type: "integer" }] } } } }, + { version: "3.0.3", loosenUnions: true } + ); + expect(document.openapi).toBe("3.0.3"); + expect(document.components?.schemas).toStrictEqual({ A: { oneOf: [{ type: "string" }, { type: "integer" }] } }); + expect(problems).toStrictEqual([]); + }); + + test("reports a target it cannot reach", async () => { + const above = await downlevel({ openapi: "3.0.3" }, { version: "3.1" }); + const unknown = await downlevel({ openapi: "3.1.0" }, { version: "2.0" }); + const unreleased = await downlevel({ openapi: "3.1.9" }, { version: "3.0" }); + const major = await downlevel({ openapi: "3.1.0" }, { version: "3" }); + const missing = await downlevel({ openapi: "3.1.0" }, {}); + expect([above, unknown, unreleased, major, missing].map(({ problems }) => problems)).toStrictEqual([ + [{ severity: "error", pointer: "#/openapi", message: "Cannot downlevel OpenAPI 3.0.3 to 3.1." }], + [{ severity: "error", pointer: "#/openapi", message: "Cannot downlevel OpenAPI 3.1.0 to 2.0." }], + [{ severity: "error", pointer: "#/openapi", message: "Cannot downlevel OpenAPI 3.1.9 to 3.0." }], + [{ severity: "error", pointer: "#/openapi", message: "Cannot downlevel OpenAPI 3.1.0 to 3." }], + [{ severity: "error", pointer: "#/", message: "Set `version` to the OpenAPI version to write, such as `\"3.0\"`." }] + ]); + }); + + test("reports a version YAML read as a number", async () => { + const { document, problems } = await downlevel({ openapi: "3.1.0" }, { version: 3 as unknown as string }); + expect(document.openapi).toBe("3.1.0"); + expect(problems).toStrictEqual([ + { severity: "error", pointer: "#/", message: "Quote `version`: YAML reads an unquoted 3.0 as the number 3." } + ]); + }); +}); + +describe("reports", () => { + test("point at the file the construct is written in", async () => { + const directory = mkdtempSync(path.join(tmpdir(), "downlevel-")); + writeFileSync( + path.join(directory, "openapi.yaml"), + "openapi: 3.1.0\ninfo: {title: fixture, version: \"1\"}\npaths: {}\ncomponents:\n schemas:\n A:\n $ref: ./a.yaml\n" + ); + writeFileSync(path.join(directory, "a.yaml"), "type: object\nproperties:\n b:\n type: \"null\"\n"); + + const config = await createConfig({ plugins: [plugin()], decorators: { "downlevel/openapi": { version: "3.0" } } }); + const { problems } = await bundle({ ref: path.join(directory, "openapi.yaml"), config }); + expect(problems.map(({ location: [{ source, pointer }] }) => ({ file: path.basename(source.absoluteRef), pointer }))).toStrictEqual([ + { file: "a.yaml", pointer: "#/properties/b/type" } + ]); + }); +}); diff --git a/packages/redocly-plugin-downlevel/src/fixture.ts b/packages/redocly-plugin-downlevel/src/fixture.ts new file mode 100644 index 00000000..989347d3 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/fixture.ts @@ -0,0 +1,40 @@ +import { bundleFromString, createConfig } from "@redocly/openapi-core"; + +import type { Options } from "./decorator.ts"; +import plugin from "./index.ts"; + +type Document = { components?: Record>; paths?: Record } & Record; + +/** + * Bundles a description through `downlevel/openapi` and returns the result with + * its problems reduced to what a test asserts on. + */ +export async function downlevel(document: Record, options: Options) { + const config = await createConfig({ + plugins: [plugin()], + decorators: { "downlevel/openapi": { ...options } } + }); + const source = JSON.stringify({ info: { title: "fixture", version: "1" }, paths: {}, ...document }); + const { bundle, problems } = await bundleFromString({ source, config }); + + return { + document: bundle.parsed as Document, + problems: problems.map(({ message, severity, location }) => ({ message, severity, pointer: location[0]?.pointer })) + }; +} + +/** + * Runs one layer: from `openapi` to the release below it. + */ +export function layer(openapi: string, version: string, options: Omit = {}) { + const run = (document: Record) => downlevel({ openapi, ...document }, { version, ...options }); + + return Object.assign(run, { + schemas: async (schemas: Record) => { + const { document, problems } = await run({ components: { schemas } }); + return { schemas: document.components?.schemas ?? {}, problems }; + } + }); +} + +export const reference = (name: string) => ({ $ref: `#/components/schemas/${name}` }); diff --git a/packages/redocly-plugin-downlevel/src/fixtures.test.ts b/packages/redocly-plugin-downlevel/src/fixtures.test.ts new file mode 100644 index 00000000..7f765216 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/fixtures.test.ts @@ -0,0 +1,91 @@ +import { readdirSync } from "node:fs"; +import path from "node:path"; + +import { BaseResolver, bundle, createConfig, lintFromString } from "@redocly/openapi-core"; +import type { NormalizedProblem } from "@redocly/openapi-core"; +import { describe, expect, test } from "bun:test"; + +import plugin from "./index.ts"; +import { layers } from "./layers.ts"; + +const root = path.join(import.meta.dirname, "..", "fixtures"); + +const heldOut: Record = { + "oai/3.2/security-scheme-object-examples.yaml": + "Redocly cannot read it: `@redocly/openapi-core` types `DeviceAuthorization.scopes` as `mapOf('string')`, and a non-empty scope map throws `Unknown type name found: string`." +}; + +function offline() { + return new BaseResolver({ http: { headers: [], customFetch: async () => new Response(null, { status: 503, statusText: "offline" }) } }); +} + +const fixtures = readdirSync(root, { recursive: true, encoding: "utf8" }) + .filter((file) => file.endsWith(".yaml")) + .map((file) => file.split(path.sep).join("/")) + .sort(); + +function below(version: string): Array { + const releases: Array = []; + for (let layer = layers.find((candidate) => candidate.version === version); layer; layer = layers.find((candidate) => candidate.version === layer!.writes)) + releases.push(layer.writes); + return releases; +} + +async function downlevel(file: string, options?: { version: string; loosenUnions: boolean }) { + const config = await createConfig({ plugins: [plugin()], decorators: options ? { "downlevel/openapi": options } : {} }); + const { bundle: result, problems } = await bundle({ ref: path.join(root, file), config, externalRefResolver: offline() }); + return { + document: result.parsed as Record, + problems: problems.filter(({ ruleId }) => ruleId === "downlevel/openapi").map(({ message, location }) => ({ message, pointer: location[0]?.pointer })) + }; +} + +const lintConfig = await createConfig({ extends: ["minimal"] }); + +async function lintErrors(document: Record) { + const problems = await lintFromString({ source: JSON.stringify(document), absoluteRef: path.join(root, "linted.json"), config: lintConfig, externalRefResolver: offline() }); + return new Set(problems.filter(({ severity }) => severity === "error").map((problem: NormalizedProblem) => `${problem.ruleId} ${problem.location[0]?.pointer} ${problem.message}`)); +} + +const withoutVersion = ({ openapi: _, ...document }: Record) => document; + +describe("fixtures", () => { + for (const file of fixtures) { + if (heldOut[file]) { + test.skip(`${file}: ${heldOut[file]}`, () => {}); + continue; + } + + test(file, async () => { + const source = await downlevel(file); + const releases = below(String(source.document.openapi)); + const introduced: Array = []; + const snapshot: Record = {}; + let previous: { version: string; document: Record; problems: unknown; loosened: unknown } | undefined; + + const sourceErrors = await lintErrors(source.document); + + for (const version of releases) { + const plain = await downlevel(file, { version, loosenUnions: false }); + const loosened = await downlevel(file, { version, loosenUnions: true }); + + for (const { document, problems } of [plain, loosened]) { + if (problems.length > 0) continue; + for (const error of await lintErrors(document)) if (!sourceErrors.has(error)) introduced.push(`${version}: ${error}`); + } + + const loosenedEntry = Bun.deepEquals(loosened, plain) ? "unchanged" : loosened; + const sameDocument = previous !== undefined && Bun.deepEquals(withoutVersion(previous.document), withoutVersion(plain.document)); + const sameEntry = sameDocument && Bun.deepEquals(previous!.problems, plain.problems) && Bun.deepEquals(previous!.loosened, loosenedEntry); + + snapshot[version] = sameEntry + ? `as ${previous!.version}` + : { problems: plain.problems, document: sameDocument ? `as ${previous!.version}` : plain.document, loosened: loosenedEntry }; + previous = { version, document: plain.document, problems: plain.problems, loosened: loosenedEntry }; + } + + expect(introduced).toStrictEqual([]); + expect(snapshot).toMatchSnapshot(); + }, 60_000); + } +}); diff --git a/packages/redocly-plugin-downlevel/src/index.ts b/packages/redocly-plugin-downlevel/src/index.ts new file mode 100644 index 00000000..68561822 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/index.ts @@ -0,0 +1,16 @@ +import type { Plugin } from "@redocly/openapi-core"; + +import { openapi } from "./decorator.ts"; + +export type { Options } from "./decorator.ts"; + +/** + * Registers `downlevel/openapi`, which rewrites a bundled OpenAPI 3.x + * description as an earlier 3.x release. + */ +export default function plugin(): Plugin { + return { + id: "downlevel", + decorators: { oas3: { openapi } } + }; +} diff --git a/packages/redocly-plugin-downlevel/src/layer.ts b/packages/redocly-plugin-downlevel/src/layer.ts new file mode 100644 index 00000000..86dee557 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/layer.ts @@ -0,0 +1,49 @@ +import type { NodeType, UserContext } from "@redocly/openapi-core"; + +export type Node = Record; + +type Visit = (node: Node, context: UserContext) => void; + +/** + * A Redocly visitor over plain JSON: keyed by Redocly's node type names, such as + * `Schema` or `Operation`, plus `ref` for every `$ref`. + */ +export type Visitor = Partial>; + +export interface TransformOptions { + /** + * The version the layer writes, for messages that name it. + */ + version: string; + loosenUnions: boolean; +} + +/** + * A Redocly visitor factory. Each transform runs as its own walk over the whole + * bundled description, so it reads a document every earlier transform has + * finished with. + */ +export type Transform = (options: TransformOptions) => Visitor; + +/** + * Rewrites a description in `version` as the release one below it, `writes`. + */ +export interface Layer { + version: string; + writes: string; + /** + * The type tree for `version`, which the layer's transforms walk. + */ + types: Record; + specVersion: "oas3_0" | "oas3_1" | "oas3_2"; + /** + * Report what `writes` cannot say or would read differently, and change + * nothing. All of them run, so every problem is reported at once. + */ + checks: Array; + /** + * Rewrite the description, in order. The first to report ends the run: the + * ones after it would meet a construct it could not lower. + */ + transforms: Array; +} diff --git a/packages/redocly-plugin-downlevel/src/layers.ts b/packages/redocly-plugin-downlevel/src/layers.ts new file mode 100644 index 00000000..f10cc6a4 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/layers.ts @@ -0,0 +1,26 @@ +import { layer as from301 } from "./3.0.1/index.ts"; +import { layer as from302 } from "./3.0.2/index.ts"; +import { layer as from303 } from "./3.0.3/index.ts"; +import { layer as from304 } from "./3.0.4/index.ts"; +import { layer as from310 } from "./3.1.0/index.ts"; +import { layer as from311 } from "./3.1.1/index.ts"; +import { layer as from312 } from "./3.1.2/index.ts"; +import { layer as from320 } from "./3.2.0/index.ts"; +import { layer as from321 } from "./3.2.1/index.ts"; +import type { Layer } from "./layer.ts"; + +/** + * One layer per OpenAPI release, each named after the release it reads and + * writing the release below it. 3.0.0, the first 3.x release, has none. + */ +export const layers: Array = [ + from321, + from320, + from312, + from311, + from310, + from304, + from303, + from302, + from301 +]; diff --git a/packages/redocly-plugin-downlevel/src/pointer.ts b/packages/redocly-plugin-downlevel/src/pointer.ts new file mode 100644 index 00000000..58260836 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/pointer.ts @@ -0,0 +1,36 @@ +import { unescapePointerFragment } from "@redocly/openapi-core"; + +import type { Node } from "./layer.ts"; + +/** + * Follows a local JSON Pointer reference (`#/...`) through the bundled document. + * Returns undefined for any other reference, or one that leads nowhere. + * + * https://www.rfc-editor.org/rfc/rfc6901 + */ +export function resolvePointer(root: unknown, reference: string): unknown { + if (!reference.startsWith("#/")) return undefined; + + let node = root; + for (const part of reference.slice(2).split("/")) { + if (!node || typeof node !== "object") return undefined; + node = (node as Node)[unescapePointerFragment(part)]; + } + return node; +} + +/** + * Follows `$ref` until it reaches a schema that is not one. + */ +export function resolveSchema(root: unknown, schema: Node): Node { + const seen = new Set(); + let node = schema; + + while (typeof node.$ref === "string" && !seen.has(node)) { + seen.add(node); + const target = resolvePointer(root, node.$ref); + if (!target || typeof target !== "object") return node; + node = target as Node; + } + return node; +} diff --git a/packages/redocly-plugin-downlevel/src/transforms/pin-form-encoding.ts b/packages/redocly-plugin-downlevel/src/transforms/pin-form-encoding.ts new file mode 100644 index 00000000..cda61bf5 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/transforms/pin-form-encoding.ts @@ -0,0 +1,36 @@ +import type { Node, Transform } from "../layer.ts"; +import { resolveSchema } from "../pointer.ts"; + +/** + * 3.0.4 and 3.1.1 say an object property of an + * `application/x-www-form-urlencoded` body is sent as JSON unless `encoding` + * says otherwise; the releases before them described it as form style. Writing + * the `contentType` out keeps the later reading in the earlier release. + * + * https://spec.openapis.org/oas/v3.0.4#encoding-application-x-www-form-urlencoded + */ +export const pinFormEncoding: Transform = () => { + let root: Node; + const resolve = (schema: Node): Node => resolveSchema(root, schema); + + return { + Root: { + enter: (document) => { + root = document; + } + }, + MediaType: { + leave: (node, { key }) => { + if (key !== "application/x-www-form-urlencoded" || !node.schema) return; + + const properties = resolve(node.schema as Node).properties as Record | undefined; + for (const [name, property] of Object.entries(properties ?? {})) { + if (resolve(property).type !== "object") continue; + + const encoding = (node.encoding ??= {}) as Record; + encoding[name] ??= { contentType: "application/json" }; + } + } + } + }; +}; diff --git a/packages/redocly-plugin-downlevel/src/transforms/report-namespace-fragments.ts b/packages/redocly-plugin-downlevel/src/transforms/report-namespace-fragments.ts new file mode 100644 index 00000000..5c0c8e49 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/transforms/report-namespace-fragments.ts @@ -0,0 +1,18 @@ +import type { Transform } from "../layer.ts"; + +/** + * 3.0.4 and 3.1.1 relaxed an XML `namespace` from an absolute URI to a + * non-relative one, which may carry a fragment. The releases before them + * cannot hold one that does. + * + * https://spec.openapis.org/oas/v3.0.4#xml-object + */ +export const reportNamespaceFragments: Transform = ({ version }) => ({ + Xml: { + enter: (xml, { report, location }) => { + const namespace = xml.namespace; + if (typeof namespace === "string" && URL.canParse(namespace) && new URL(namespace).hash !== "") + report({ message: `OpenAPI ${version} requires \`namespace\` to be an absolute URI, without a fragment.`, location: location.child("namespace") }); + } + } +}); diff --git a/packages/redocly-plugin-downlevel/src/transforms/report-relative-urls.ts b/packages/redocly-plugin-downlevel/src/transforms/report-relative-urls.ts new file mode 100644 index 00000000..3982e5a5 --- /dev/null +++ b/packages/redocly-plugin-downlevel/src/transforms/report-relative-urls.ts @@ -0,0 +1,32 @@ +import type { UserContext } from "@redocly/openapi-core"; + +import type { Transform } from "../layer.ts"; + +/** + * Releases disagree on what a relative URL in the description's metadata is + * relative to: 3.0.3 and 3.1.0 resolve it against the Server Object, 3.0.4 + * leaves it to the implementation, and 3.1.1 onward against the document's own + * URI. An absolute URL means the same in all of them; a relative one is + * reported, since the base it was written against is not in the document. + * + * https://spec.openapis.org/oas/v3.0.3#relative-references-in-urls + * https://spec.openapis.org/oas/v3.1.1#relative-references-in-api-description-uris + */ +export const reportRelativeUrls: Transform = ({ version }) => { + const check = (fields: Array) => ({ + enter: (node: Record, { report, location }: UserContext) => { + for (const field of fields) { + const value = node[field]; + if (typeof value === "string" && !URL.canParse(value)) + report({ message: `OpenAPI ${version} resolves a relative URL against a different base.`, location: location.child(field) }); + } + } + }); + + return { + Info: check(["termsOfService"]), + Contact: check(["url"]), + License: check(["url"]), + ExternalDocs: check(["url"]) + }; +}; diff --git a/packages/redocly-plugin-downlevel/tsconfig.build.json b/packages/redocly-plugin-downlevel/tsconfig.build.json new file mode 100644 index 00000000..90c038ed --- /dev/null +++ b/packages/redocly-plugin-downlevel/tsconfig.build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "types": ["node"], + "declaration": true, + "noEmit": false, + "outDir": "dist" + }, + "exclude": ["src/**/*.test.ts", "src/fixture.ts"] +} diff --git a/packages/redocly-plugin-downlevel/tsconfig.json b/packages/redocly-plugin-downlevel/tsconfig.json new file mode 100644 index 00000000..17574f17 --- /dev/null +++ b/packages/redocly-plugin-downlevel/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "es2023", + "module": "nodenext", + "moduleResolution": "nodenext", + "types": ["node", "bun"], + "allowImportingTsExtensions": true, + "strict": true, + "rewriteRelativeImportExtensions": true, + "noEmit": true, + "verbatimModuleSyntax": true, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 23056fcf..404cfdf9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,50 +15,32 @@ importers: specifier: ^1.11.1 version: 1.11.1 '@apidevtools/json-schema-ref-parser': - specifier: ^15.1.2 - version: 15.1.2(@types/json-schema@7.0.15) + specifier: ^15.5.2 + version: 15.5.2(@types/json-schema@7.0.15) '@ariesclark/eslint-config': specifier: ^3.1.1 - version: 3.1.1(@eslint-react/eslint-plugin@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(supports-color@7.2.0)))(eslint@9.39.1(supports-color@7.2.0))(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.20.6)(typescript@6.0.3)(yaml@2.8.2) + version: 3.1.1(@eslint-react/eslint-plugin@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.5(supports-color@7.2.0)))(eslint@9.39.5(supports-color@7.2.0))(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.23.15)(typescript@6.0.3)(yaml@2.9.1) + '@cspell/eslint-plugin': + specifier: ^10.3.3 + version: 10.3.3(eslint@9.39.5(supports-color@7.2.0)) '@eslint-react/eslint-plugin': - specifier: ^2.3.9 - version: 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + specifier: ^2.13.0 + version: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) '@jamesacarr/eslint-formatter-github-actions': specifier: ^0.2.0 version: 0.2.0 '@redocly/cli': - specifier: ^2.46.0 - version: 2.49.0 + specifier: ^2.54.3 + version: 2.54.3 '@redocly/openapi-core': - specifier: ^2.41.2 - version: 2.49.0 - '@stoplight/spectral-cli': - specifier: ^6.15.0 - version: 6.15.0 - '@stoplight/spectral-core': - specifier: ^1.20.0 - version: 1.20.0 - '@stoplight/spectral-formats': - specifier: ^1.8.2 - version: 1.8.2 - '@stoplight/spectral-formatters': - specifier: ^1.5.0 - version: 1.5.0 - '@stoplight/spectral-functions': - specifier: ^1.10.1 - version: 1.10.1 - '@stoplight/spectral-parsers': - specifier: ^1.0.5 - version: 1.0.5 - '@stoplight/spectral-rulesets': - specifier: ^1.22.0 - version: 1.22.0 + specifier: ^2.54.3 + version: 2.54.3 '@types/bun': - specifier: ^1.3.3 - version: 1.3.3 + specifier: ^1.4.2 + version: 1.4.2 '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^24.13.6 + version: 24.13.6 '@types/pluralize': specifier: ^0.0.33 version: 0.0.33 @@ -66,14 +48,11 @@ importers: specifier: ^5.4.4 version: 5.4.4 cspell: - specifier: ^9.3.2 - version: 9.3.2 - cspell-lib: - specifier: ^9.3.2 - version: 9.3.2 + specifier: ^9.8.0 + version: 9.8.0 eslint: - specifier: ^9.39.1 - version: 9.39.1(supports-color@7.2.0) + specifier: ^9.39.5 + version: 9.39.5(supports-color@7.2.0) httpexec: specifier: ^0.0.2 version: 0.0.2 @@ -81,8 +60,8 @@ importers: specifier: ^8.0.0 version: 8.0.0 semver: - specifier: ^7.7.3 - version: 7.7.3 + specifier: ^7.8.5 + version: 7.8.5 totp-generator: specifier: ^2.0.1 version: 2.0.1 @@ -90,6 +69,21 @@ importers: specifier: ^6.0.3 version: 6.0.3 + packages/redocly-plugin-downlevel: + devDependencies: + '@redocly/openapi-core': + specifier: ^2.54.3 + version: 2.54.3 + '@types/bun': + specifier: ^1.4.2 + version: 1.4.2 + '@types/node': + specifier: ^24.13.6 + version: 24.13.6 + typescript: + specifier: ^6.0.3 + version: 6.0.3 + packages: '@actions/artifact@5.0.2': @@ -174,8 +168,8 @@ packages: '@antfu/utils@0.7.10': resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} - '@apidevtools/json-schema-ref-parser@15.1.2': - resolution: {integrity: sha512-54vnqDyGsDAVM0LOIdGMnfVyCN1NlqoGnHEGpMfaDBLMvClfT4j2XbJgvfuF0Ca0kxT6Gb7xUgS5W1I14QqjiQ==} + '@apidevtools/json-schema-ref-parser@15.5.2': + resolution: {integrity: sha512-B+C9Ok0DF/rjANIUHgwcV5/d4C72MB7f2IbKFL8jDGcGq2qn3yr893s8vAn2kbhmyaelAin0JK8EKF9P1+y7aQ==} engines: {node: '>=20'} peerDependencies: '@types/json-schema': ^7.0.15 @@ -192,9 +186,6 @@ packages: eslint-plugin-tailwindcss: optional: true - '@asyncapi/specs@6.10.0': - resolution: {integrity: sha512-vB5oKLsdrLUORIZ5BXortZTlVyGWWMC1Nud/0LtgxQ3Yn2738HigAD6EVqScvpPsDUI/bcLVsYEXN4dtXQHVng==} - '@azure/abort-controller@2.2.0': resolution: {integrity: sha512-fNAjWnA/nZ2jz31kxR/AqRaUT8ewHBw/WuBIosK0moMy1C9e5ValbDfFdIxJzVOOYaYkV/b2F1S4H/aHiqfVQg==} engines: {node: '>=22.0.0'} @@ -203,8 +194,8 @@ packages: resolution: {integrity: sha512-IUZydyTUkDnYdstOW9pFOOUQlBjAepK5teihDE3x6yxsPJs/hsAaaYpeGxdxrgtOiJbBKSjKW7MDk7AEhb4LRg==} engines: {node: '>=22.0.0'} - '@azure/core-client@1.11.0': - resolution: {integrity: sha512-JjQWO6akOck45PH/XBrxzsQGAiKrfFl4m5iggJ0ItMIz5omRufOXWpqCPpdjKN3vKDzlSUvFjaMb7Zwf0gvAdA==} + '@azure/core-client@1.11.1': + resolution: {integrity: sha512-2QygG2F76ZpMP2eMztiJvAiFMu71M9rDeU7vO/QKg5Css7MgM4frUOslFjhVjRhbGaCNPtz/S8M6y46/fFKVuQ==} engines: {node: '>=22.0.0'} '@azure/core-http-compat@2.5.0': @@ -250,16 +241,16 @@ packages: resolution: {integrity: sha512-bttzuhQiCIwrkzjPDA+AtAR7dg19L/CC6ztcqJ5LfvWpXuys9mHp0UQ0udYnoUvv9SCT9KTR5kqFvFr0e6k0lQ==} engines: {node: '>=22.0.0'} - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} engines: {node: '>=6.9.0'} '@babel/parser@7.28.5': @@ -267,19 +258,19 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/runtime@7.28.4': - resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} '@babel/types@7.28.5': resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} - '@bufbuild/protobuf@2.13.0': - resolution: {integrity: sha512-acq7c49vxfm1ggJ95P70TX7ABDM0vxr1SYD3BB0o0jnBLB4OAqeHyKuN+cD3w80gXEDQ2zxHpR6CUeA+O/aU9g==} + '@bufbuild/protobuf@2.15.0': + resolution: {integrity: sha512-DAheWUkVr/SJTWCc+lg9dhY0eN4SaWlf4+bG1KzHeXbnqt0AfB/NX0Z+VunGlM1ki1B4zVvye27MpKh/svySUA==} - '@bufbuild/protoplugin@2.13.0': - resolution: {integrity: sha512-32eMChKaL/A8Hh5AfMmXSdnuyznN85uoEjoyWiWeRrvtQOtpqX/v1R9PDe0g9vMIgzznK9inMT3CUaal0kjLUQ==} + '@bufbuild/protoplugin@2.15.0': + resolution: {integrity: sha512-vZhRoqB/jTHATqItRvJQf1zbxdrGRRhiusGty4+lKcfEFODG0PMXky2Ezv4WHHS6oSxq+5qShITuE7K1/82SuQ==} '@clack/core@0.4.1': resolution: {integrity: sha512-Pxhij4UXg8KSr7rPek6Zowm+5M22rbd2g1nfojHJkxp5YkFqiZ2+YLEM/XGVIzvGOcM0nqjIFxrpDwWRZYWYjA==} @@ -287,107 +278,139 @@ packages: '@clack/prompts@0.9.1': resolution: {integrity: sha512-JIpyaboYZeWYlyP0H+OoPPxd6nqueG/CmN6ixBiNFsIDHREevjIf0n0Ohh5gr5C8pEDknzgvz+pIJ8dMhzWIeg==} - '@cspell/cspell-bundled-dicts@9.3.2': - resolution: {integrity: sha512-OmKzq/0FATHU671GKMzBrTyLdm25Wnziva7h4ylumVn1wnwWsXGef5bgXD7iuApqfqH9SzxsU0NtTB8m8vwEHQ==} + '@cspell/cspell-bundled-dicts@10.3.3': + resolution: {integrity: sha512-aX40uWqTN44EM81R/Xj/NMIbgdtBM0ulKPTDKhVJYIbCJarISLoxaJkERs9dHB5AwrDZViC6BXcpVYnoRV1kXg==} + engines: {node: '>=22.18.0'} + + '@cspell/cspell-bundled-dicts@9.8.0': + resolution: {integrity: sha512-MpXFpVyBPfJQ1YuVotljqUaGf6lWuf+fuWBBgs0PHFYTSjRPWuIxviAaCDnup/CJLLH60xQL4IlcQe4TOjzljw==} engines: {node: '>=20'} - '@cspell/cspell-json-reporter@9.3.2': - resolution: {integrity: sha512-YRgpeHN9uY8kUlIw9q+8zJ0tRTAJMbfBTGzCq9Puah09NeMWlRMFPUkXVrkdic6NA7etboZ+zEdoZwRO9EmhiA==} + '@cspell/cspell-json-reporter@9.8.0': + resolution: {integrity: sha512-nqUaSo9T7l8KrE22gc7ZIs+zvP7ak1i7JqGdRs8sGvh2Ijqj43qYQLePgb1b/vm8a1bavnc51m+vf05hpd3g3Q==} engines: {node: '>=20'} - '@cspell/cspell-pipe@9.3.2': - resolution: {integrity: sha512-REF7ibG79WLEynIMUss/IRDCdYEb1nlE1rj/gt2CbPFzLa6t5MRwW2lajEvXS6/WgbMtsTVHAWi3ALqJzCwxng==} + '@cspell/cspell-performance-monitor@10.3.3': + resolution: {integrity: sha512-RfHwlk45TwYS2oNuHUGH562NgKEFLotG9LHYjkTiPKC8tZfqaoBKT1BHK/g7H5XUe5L8/nhN0ycxI0bZ3InShA==} + engines: {node: '>=22.18.0'} + + '@cspell/cspell-performance-monitor@9.8.0': + resolution: {integrity: sha512-IsrXYzn23yJICIQ915ACdf+2lNEcFNTu5BIQt3khHOsGVvZ9/AZYpu9Dk825vUyZG7RHg2Oi6dYNiJtULG4ouQ==} + engines: {node: '>=20.18'} + + '@cspell/cspell-pipe@10.3.3': + resolution: {integrity: sha512-ZZ0dgTKbvWyb5cb4rhWTP9KCdyEGaIzc55Qvz6+mPWDTd/cQthsH4SECitZtWgzY8o/kLmlCEOrkqgli5kAHBQ==} + engines: {node: '>=22.18.0'} + + '@cspell/cspell-pipe@9.8.0': + resolution: {integrity: sha512-ISEUD8PHYkd2Ktafc6hFfIXdGKYUvthA09NbwwZsWmOqYyk4wWKHZKqyyxD+BcrFwOyMOJcD8OEvIjkRQp2SJw==} engines: {node: '>=20'} - '@cspell/cspell-resolver@9.3.2': - resolution: {integrity: sha512-jLN2Aa/vxm8+IBvTd884SwPEfjxnDwIEPBT3hmqgLlKuUHQ3FMG27lsM4Ik9L2KWBXMgV/wGz4BaxfhKI41Ttw==} + '@cspell/cspell-resolver@10.3.3': + resolution: {integrity: sha512-zy+3lykifrK3z6RW93mi5BLCdn4aPM1/ovfy8ekJO2I43FxpevbtNFfSoU1/ZYpWPAgEbz9CUjbMkWE7pgK+HA==} + engines: {node: '>=22.18.0'} + + '@cspell/cspell-resolver@9.8.0': + resolution: {integrity: sha512-PZJj56BZpKfMxOzWkyt7b+aIXObe+8Ku/zLI4xDXPSuQPENbHBFHfPIZx68CyGEkanKxZ1ewKVx/FT1FUy+wDA==} engines: {node: '>=20'} - '@cspell/cspell-service-bus@9.3.2': - resolution: {integrity: sha512-/rB8LazM0JzKL+AvZa5fEpLutmwy5QFMpzw8HJd+rDGkzb5r79hURWSRo84QArgaskUqA9XlOHSieDE9pt+WAA==} + '@cspell/cspell-service-bus@10.3.3': + resolution: {integrity: sha512-zGQgksLrM36TinrflZvx3bp3DSRHog1wl4HZAYvVtp74eqZromUDoW0lziFFrumZnld+p92l8GSrXptnvYhjog==} + engines: {node: '>=22.18.0'} + + '@cspell/cspell-service-bus@9.8.0': + resolution: {integrity: sha512-P45sd2nqwcqhulBBbQnZB/JNcobecTrP4Ky3vmEq0cprsvavc+ZoHF9U2Ql5ghMSUzjrF2n1aNzZ8cH4IlsnKg==} engines: {node: '>=20'} - '@cspell/cspell-types@9.3.2': - resolution: {integrity: sha512-l4H8bMAmdzCbXHO8y1JZiAKszrPEiuLFKWrbhCacHF0iP+PIc/yuQp7cO70m0p70vArRfih6kgGyHFaCy47CfA==} + '@cspell/cspell-types@10.3.3': + resolution: {integrity: sha512-sLw1ik9qrPc2NZJ93Y6eKXd2r5jpiu7ciOl2fVsvKo11GU6MmOqx7J9UJ3uUy5+xo6Zvpo/6JGD030l8OiYUOw==} + engines: {node: '>=22.18.0'} + + '@cspell/cspell-types@9.8.0': + resolution: {integrity: sha512-7Ge4UD6SCA49Tcc3+GTlz3Xn4cqVUAXtDO0u9IeHvJgkN3Me2Rw2GB/CtGmhKST3YeEeZMX7ww09TdHMUJlehw==} engines: {node: '>=20'} + '@cspell/cspell-worker@9.8.0': + resolution: {integrity: sha512-W8FLdE3MXPLbWtAXciILQhk9CHd6Mt+HRjZHM8m+dwE1Bc2TAjUai8kIxsdhHUq58p7gYY2ekr5sg1uYOUgTAA==} + engines: {node: '>=20.18'} + '@cspell/dict-ada@4.1.1': resolution: {integrity: sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==} '@cspell/dict-al@1.1.1': resolution: {integrity: sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==} - '@cspell/dict-aws@4.0.16': - resolution: {integrity: sha512-a681zShZbtTo947NvTYGLer95ZDQw1ROKvIFydak1e0OlfFCsNdtcYTupn0nbbYs53c9AO7G2DU8AcNEAnwXPA==} + '@cspell/dict-aws@4.0.17': + resolution: {integrity: sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==} - '@cspell/dict-bash@4.2.2': - resolution: {integrity: sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==} + '@cspell/dict-bash@4.2.3': + resolution: {integrity: sha512-ljUZoKHbDqw5Sx0qpL2qTUlmkmr+vhZH/sCNrNaBZKTbdgiswErSnIF1jRbGmEitJNxHRHWsuZyVgnTGfVO1Yw==} - '@cspell/dict-companies@3.2.7': - resolution: {integrity: sha512-fEyr3LmpFKTaD0LcRhB4lfW1AmULYBqzg4gWAV0dQCv06l+TsA+JQ+3pZJbUcoaZirtgsgT3dL3RUjmGPhUH0A==} + '@cspell/dict-companies@3.2.13': + resolution: {integrity: sha512-mBJeYzCkiiWgNQxKg7zyQOpFPwcXO4IAzXGbOEFfcQ4Q0G5Fa7Kqd8z+gvnvSK7NPWKJaFmiApC6I0cka02qmQ==} - '@cspell/dict-cpp@6.0.14': - resolution: {integrity: sha512-dkmpSwvVfVdtoZ4mW/CK2Ep1v8mJlp6uiKpMNbSMOdJl4kq28nQS4vKNIX3B2bJa0Ha5iHHu+1mNjiLeO3g7Xg==} + '@cspell/dict-cpp@7.1.2': + resolution: {integrity: sha512-bkR33oE+ToyD1hwSV4XeEUB9oDkizHRX03CrQfj23tX4VUVbie5vkEHzlKVhcw/Q+fO2dtV/Vz4f6O5M4a2iZQ==} '@cspell/dict-cryptocurrencies@5.0.5': resolution: {integrity: sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==} - '@cspell/dict-csharp@4.0.7': - resolution: {integrity: sha512-H16Hpu8O/1/lgijFt2lOk4/nnldFtQ4t8QHbyqphqZZVE5aS4J/zD/WvduqnLY21aKhZS6jo/xF5PX9jyqPKUA==} + '@cspell/dict-csharp@4.0.8': + resolution: {integrity: sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==} - '@cspell/dict-css@4.0.18': - resolution: {integrity: sha512-EF77RqROHL+4LhMGW5NTeKqfUd/e4OOv6EDFQ/UQQiFyWuqkEKyEz0NDILxOFxWUEVdjT2GQ2cC7t12B6pESwg==} + '@cspell/dict-css@4.1.2': + resolution: {integrity: sha512-+ylGoKdwZ2sVOCOnU2Eq5wDZx+RaVX3HoKyNHGGsFvhSw6IidQ6tH/mAPKBDofViHJoWCPNlklE0lTr6MDG3QA==} - '@cspell/dict-dart@2.3.1': - resolution: {integrity: sha512-xoiGnULEcWdodXI6EwVyqpZmpOoh8RA2Xk9BNdR7DLamV/QMvEYn8KJ7NlRiTSauJKPNkHHQ5EVHRM6sTS7jdg==} + '@cspell/dict-dart@2.3.2': + resolution: {integrity: sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==} - '@cspell/dict-data-science@2.0.12': - resolution: {integrity: sha512-vI/mg6cI28IkFcpeINS7cm5M9HWemmXSTnxJiu3nmc4VAGx35SXIEyuLGBcsVzySvDablFYf4hsEpmg1XpVsUQ==} + '@cspell/dict-data-science@2.0.16': + resolution: {integrity: sha512-M72mxv5asuAnORurz4iXRJ+Tw9XBq6eu7D2Ne7biP0Z1RciKGNxXWu9JycA/KlVvK1hAlKj/fANlXhuEWpXKFg==} - '@cspell/dict-django@4.1.5': - resolution: {integrity: sha512-AvTWu99doU3T8ifoMYOMLW2CXKvyKLukPh1auOPwFGHzueWYvBBN+OxF8wF7XwjTBMMeRleVdLh3aWCDEX/ZWg==} + '@cspell/dict-django@4.1.6': + resolution: {integrity: sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==} - '@cspell/dict-docker@1.1.16': - resolution: {integrity: sha512-UiVQ5RmCg6j0qGIxrBnai3pIB+aYKL3zaJGvXk1O/ertTKJif9RZikKXCEgqhaCYMweM4fuLqWSVmw3hU164Iw==} + '@cspell/dict-docker@1.1.17': + resolution: {integrity: sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==} - '@cspell/dict-dotnet@5.0.10': - resolution: {integrity: sha512-ooar8BP/RBNP1gzYfJPStKEmpWy4uv/7JCq6FOnJLeD1yyfG3d/LFMVMwiJo+XWz025cxtkM3wuaikBWzCqkmg==} + '@cspell/dict-dotnet@5.0.15': + resolution: {integrity: sha512-j2MUKPlzMeDy/mnb1EjmtkX8e6VzZdw60Qyf6vPlp7WZhUwwp2LBlKOWx7+hASjP6k4a0nDpmn77G+4upxvbZA==} '@cspell/dict-elixir@4.0.8': resolution: {integrity: sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==} - '@cspell/dict-en-common-misspellings@2.1.8': - resolution: {integrity: sha512-vDsjRFPQGuAADAiitf82z9Mz3DcqKZi6V5hPAEIFkLLKjFVBcjUsSq59SfL59ElIFb76MtBO0BLifdEbBj+DoQ==} + '@cspell/dict-en-common-misspellings@2.2.2': + resolution: {integrity: sha512-gu0zS7nm0jgVA2EswgWOR8od8wbNYVgcGzo0pGaDqcSkKS4WhABehLOwbyI0NIEVB+ME6SmckLVGk7g+VD1C6A==} - '@cspell/dict-en-gb-mit@3.1.14': - resolution: {integrity: sha512-b+vEerlHP6rnNf30tmTJb7JZnOq4WAslYUvexOz/L3gDna9YJN3bAnwRJ3At3bdcOcMG7PTv3Pi+C73IR22lNg==} + '@cspell/dict-en-gb-mit@3.1.29': + resolution: {integrity: sha512-mInExsCFZui0f9Vg/MToWfQZzwMfPgHX8BCYdZNdXWbYz+jITXcnvssbdUkui/DVbriZVJ74Zu9bv2jOEqTCNA==} - '@cspell/dict-en_us@4.4.24': - resolution: {integrity: sha512-JE+/H2YicHJTneRmgH4GSI21rS+1yGZVl1jfOQgl8iHLC+yTTMtCvueNDMK94CgJACzYAoCsQB70MqiFJJfjLQ==} + '@cspell/dict-en_us@4.4.40': + resolution: {integrity: sha512-TGyOaWP1dD28GRHH2Lt04ciMZC8Z6UX+5kJsi04pbQHq6uRxv14/bBVCBeSsajUXRZsJYUqXyHaHB9O0ODuFuQ==} - '@cspell/dict-filetypes@3.0.14': - resolution: {integrity: sha512-KSXaSMYYNMLLdHEnju1DyRRH3eQWPRYRnOXpuHUdOh2jC44VgQoxyMU7oB3NAhDhZKBPCihabzECsAGFbdKfEA==} + '@cspell/dict-filetypes@3.0.18': + resolution: {integrity: sha512-yU7RKD/x1IWmDLzWeiItMwgV+6bUcU/af23uS0+uGiFUbsY1qWV/D4rxlAAO6Z7no3J2z8aZOkYIOvUrJq0Rcw==} '@cspell/dict-flutter@1.1.1': resolution: {integrity: sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==} - '@cspell/dict-fonts@4.0.5': - resolution: {integrity: sha512-BbpkX10DUX/xzHs6lb7yzDf/LPjwYIBJHJlUXSBXDtK/1HaeS+Wqol4Mlm2+NAgZ7ikIE5DQMViTgBUY3ezNoQ==} + '@cspell/dict-fonts@4.0.6': + resolution: {integrity: sha512-aR/0csY01dNb0A1tw/UmN9rKgHruUxsYsvXu6YlSBJFu60s26SKr/k1o4LavpHTQ+lznlYMqAvuxGkE4Flliqw==} '@cspell/dict-fsharp@1.1.1': resolution: {integrity: sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==} - '@cspell/dict-fullstack@3.2.7': - resolution: {integrity: sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg==} + '@cspell/dict-fullstack@3.2.9': + resolution: {integrity: sha512-diZX+usW5aZ4/b2T0QM/H/Wl9aNMbdODa1Jq0ReBr/jazmNeWjd+PyqeVgzd1joEaHY+SAnjrf/i9CwKd2ZtWQ==} '@cspell/dict-gaming-terms@1.1.2': resolution: {integrity: sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==} - '@cspell/dict-git@3.0.7': - resolution: {integrity: sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w==} + '@cspell/dict-git@3.1.1': + resolution: {integrity: sha512-XvuGVYj9YEu4EzntqyhH8XlTRyy57C6j8oxkIbUQfR2UYzxZGAP77XHl7qY7eC/40r/haDwnBaccyFR6BRmUCg==} - '@cspell/dict-golang@6.0.24': - resolution: {integrity: sha512-rY7PlC3MsHozmjrZWi0HQPUl0BVCV0+mwK0rnMT7pOIXqOe4tWCYMULDIsEk4F0gbIxb5badd2dkCPDYjLnDgA==} + '@cspell/dict-golang@6.0.29': + resolution: {integrity: sha512-EZCgfxrr5lPnYQLmSvB6YtpfoDFt2KKxAD4ppq2xGSIgDFXAF7Mv4doiXIFUQaynCBIEfAMl3f/uDfrIUo4fyQ==} '@cspell/dict-google@1.0.9': resolution: {integrity: sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==} @@ -395,11 +418,11 @@ packages: '@cspell/dict-haskell@4.0.6': resolution: {integrity: sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==} - '@cspell/dict-html-symbol-entities@4.0.4': - resolution: {integrity: sha512-afea+0rGPDeOV9gdO06UW183Qg6wRhWVkgCFwiO3bDupAoyXRuvupbb5nUyqSTsLXIKL8u8uXQlJ9pkz07oVXw==} + '@cspell/dict-html-symbol-entities@4.0.5': + resolution: {integrity: sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==} - '@cspell/dict-html@4.0.12': - resolution: {integrity: sha512-JFffQ1dDVEyJq6tCDWv0r/RqkdSnV43P2F/3jJ9rwLgdsOIXwQbXrz6QDlvQLVvNSnORH9KjDtenFTGDyzfCaA==} + '@cspell/dict-html@4.0.16': + resolution: {integrity: sha512-9B6/Cpb5YVcYgsEAlKudun1yd4ONllYS/ZibKLYea2apPR+l2vQdARnPrP9kTqa7NUNfRKl7m9Fb6k9rjimnow==} '@cspell/dict-java@5.0.12': resolution: {integrity: sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==} @@ -407,14 +430,14 @@ packages: '@cspell/dict-julia@1.1.1': resolution: {integrity: sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==} - '@cspell/dict-k8s@1.0.12': - resolution: {integrity: sha512-2LcllTWgaTfYC7DmkMPOn9GsBWsA4DZdlun4po8s2ysTP7CPEnZc1ZfK6pZ2eI4TsZemlUQQ+NZxMe9/QutQxg==} + '@cspell/dict-k8s@1.0.13': + resolution: {integrity: sha512-ELGkS13k7K/NEfVimBSrxVTfqXvOF/Kvxj4I62YxRm8bvHbfoXgrGaOx28lPiNRz+dmu+yYtvuXbnURKtYbC6g==} '@cspell/dict-kotlin@1.1.1': resolution: {integrity: sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==} - '@cspell/dict-latex@4.0.4': - resolution: {integrity: sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA==} + '@cspell/dict-latex@5.1.0': + resolution: {integrity: sha512-qxT4guhysyBt0gzoliXYEBYinkAdEtR2M7goRaUH0a7ltCsoqqAeEV8aXYRIdZGcV77gYSobvu3jJL038tlPAw==} '@cspell/dict-lorem-ipsum@4.0.5': resolution: {integrity: sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==} @@ -425,52 +448,52 @@ packages: '@cspell/dict-makefile@1.0.5': resolution: {integrity: sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==} - '@cspell/dict-markdown@2.0.12': - resolution: {integrity: sha512-ufwoliPijAgWkD/ivAMC+A9QD895xKiJRF/fwwknQb7kt7NozTLKFAOBtXGPJAB4UjhGBpYEJVo2elQ0FCAH9A==} + '@cspell/dict-markdown@2.0.18': + resolution: {integrity: sha512-KLRSwVrwKDz4n7bl2XQjzvaBZbGgx5QKkP5Ok1b24xaO3TpXsLhAbAn1mItvFlI2tF6Rkt83iYjQcYppywuf5Q==} peerDependencies: - '@cspell/dict-css': ^4.0.18 - '@cspell/dict-html': ^4.0.12 - '@cspell/dict-html-symbol-entities': ^4.0.4 + '@cspell/dict-css': ^4.1.2 + '@cspell/dict-html': ^4.0.16 + '@cspell/dict-html-symbol-entities': ^4.0.5 '@cspell/dict-typescript': ^3.2.3 - '@cspell/dict-monkeyc@1.0.11': - resolution: {integrity: sha512-7Q1Ncu0urALI6dPTrEbSTd//UK0qjRBeaxhnm8uY5fgYNFYAG+u4gtnTIo59S6Bw5P++4H3DiIDYoQdY/lha8w==} + '@cspell/dict-monkeyc@1.1.2': + resolution: {integrity: sha512-4VzwdSUVqyUVmAKAzMkVwVa7AkvSi1l1OHdQr58MWq4VR4NQDO8sVQSibd2PMxruXTkxJt9UwVQVHgaaVTiV1Q==} - '@cspell/dict-node@5.0.8': - resolution: {integrity: sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg==} + '@cspell/dict-node@5.0.9': + resolution: {integrity: sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==} - '@cspell/dict-npm@5.2.24': - resolution: {integrity: sha512-R+s2SC7tQCxmV6nZxkmwdR2ruSDerAkbBjIAuAcH9ZXdpacTghSDcHJtSyBYnbcLFq8Bdp3cGB+J6vCRbw3pyw==} + '@cspell/dict-npm@5.2.50': + resolution: {integrity: sha512-JZhJb0wrWpqnzDBM1VG8f6zZPRCOo6YMxct0hFhgBnbOTIHQiqZf9S1BSXCRMmmQlAWqFXjKNDp+rf7ZiJcO9w==} - '@cspell/dict-php@4.1.0': - resolution: {integrity: sha512-dTDeabyOj7eFvn2Q4Za3uVXM2+SzeFMqX8ly2P0XTo4AzbCmI2hulFD/QIADwWmwiRrInbbf8cxwFHNIYrXl4w==} + '@cspell/dict-php@4.1.3': + resolution: {integrity: sha512-41oKzl7rLVrrVZA/Gs0ESnP6KliEX7c+IwaaNmOL3PAoHasFDVEmIFeENIzuDdM12UcHT+MlLkAm3Qw/lS/ERA==} - '@cspell/dict-powershell@5.0.15': - resolution: {integrity: sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==} + '@cspell/dict-powershell@5.0.17': + resolution: {integrity: sha512-khOoIdBgKRk2scnr7888pf70yJ1Tr3RGdnYcAN0MJ2vtaNRKoOTCFc13gXUkNDHwEyhMI1h9oz3KsT180F2amw==} - '@cspell/dict-public-licenses@2.0.15': - resolution: {integrity: sha512-cJEOs901H13Pfy0fl4dCD1U+xpWIMaEPq8MeYU83FfDZvellAuSo4GqWCripfIqlhns/L6+UZEIJSOZnjgy7Wg==} + '@cspell/dict-public-licenses@2.0.16': + resolution: {integrity: sha512-EQRrPvEOmwhwWezV+W7LjXbIBjiy6y/shrET6Qcpnk3XANTzfvWflf9PnJ5kId/oKWvihFy0za0AV1JHd03pSQ==} - '@cspell/dict-python@4.2.22': - resolution: {integrity: sha512-rgF7DuleVK2lkzlw33jjEfxS2a0CU5kwAhOqf5B6XkuaPbqZ/0g0LBCdwglAGccYu7sBuvxRS8Yubk+ytSAFTg==} + '@cspell/dict-python@4.5.2': + resolution: {integrity: sha512-CFcTDGN/ycn45WXC5ZZ06pG09WbGKMpPm1rkMuqMP98/jwjw3iiK8c0izWRd8x027n1rOZ9kJ8f9Sd+bQ22HJg==} '@cspell/dict-r@2.1.1': resolution: {integrity: sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==} - '@cspell/dict-ruby@5.0.9': - resolution: {integrity: sha512-H2vMcERMcANvQshAdrVx0XoWaNX8zmmiQN11dZZTQAZaNJ0xatdJoSqY8C8uhEMW89bfgpN+NQgGuDXW2vmXEw==} + '@cspell/dict-ruby@5.1.4': + resolution: {integrity: sha512-Slw1dLY/pW5liJ5Fle+MIPphIdleZkIM6STDoXCN7sy298GfbfT34sJTcSZcXzZJVXiCEAvlLp+s1YNr6DuWNg==} - '@cspell/dict-rust@4.0.12': - resolution: {integrity: sha512-z2QiH+q9UlNhobBJArvILRxV8Jz0pKIK7gqu4TgmEYyjiu1TvnGZ1tbYHeu9w3I/wOP6UMDoCBTty5AlYfW0mw==} + '@cspell/dict-rust@4.1.2': + resolution: {integrity: sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==} - '@cspell/dict-scala@5.0.8': - resolution: {integrity: sha512-YdftVmumv8IZq9zu1gn2U7A4bfM2yj9Vaupydotyjuc+EEZZSqAafTpvW/jKLWji2TgybM1L2IhmV0s/Iv9BTw==} + '@cspell/dict-scala@5.0.11': + resolution: {integrity: sha512-+D59847Y61KZ0MBoXJzBMtOXfFhezEb6ShjvJlL7bnryyy6iBwAfozbz7OJAe+KrEpYm+GlVV7Wy4FmJSgxBag==} - '@cspell/dict-shell@1.1.2': - resolution: {integrity: sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==} + '@cspell/dict-shell@1.2.0': + resolution: {integrity: sha512-PVctvT22lJ49niMiakO8xieY7ELCAzjSqhejWR7bAMb5AZ9F4WDEs+XdGMnoVHWeXq7K5rcepLPmEJb+37zzIw==} - '@cspell/dict-software-terms@5.1.14': - resolution: {integrity: sha512-Eu9h090hxHJiqzVFS0WxOZbYXnmb7F1RFIUEg4Nru+D/78bXVDH4b8BiKGVFNRljaieNQRAHaryzdaKJRCH6ZA==} + '@cspell/dict-software-terms@5.4.5': + resolution: {integrity: sha512-5PgLJNdaFKeA6iklB0XXjmgNaoLJJqf54oRTD1raG/mgwojVlRnWE1G7x4QH9Gz07h3B3+lMDv1F57Xxs4jang==} '@cspell/dict-sql@2.2.1': resolution: {integrity: sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==} @@ -481,8 +504,8 @@ packages: '@cspell/dict-swift@2.0.6': resolution: {integrity: sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==} - '@cspell/dict-terraform@1.1.3': - resolution: {integrity: sha512-gr6wxCydwSFyyBKhBA2xkENXtVFToheqYYGFvlMZXWjviynXmh+NK/JTvTCk/VHk3+lzbO9EEQKee6VjrAUSbA==} + '@cspell/dict-terraform@1.1.4': + resolution: {integrity: sha512-Ere42ilvMFvQA4GlcN0OKlruMPR6EsvaB+iTHzj2xc+NJGRK64V7yApUcWrOrSgTiM/vhWXPIsK3OMfiAiNdmA==} '@cspell/dict-typescript@3.2.3': resolution: {integrity: sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==} @@ -493,355 +516,385 @@ packages: '@cspell/dict-zig@1.0.0': resolution: {integrity: sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ==} - '@cspell/dynamic-import@9.3.2': - resolution: {integrity: sha512-au7FyuIHUNI2r9sO3pUBKVTeD/v7c9x/nPUStaAK1bG4rdKt4w+/jUY2IaldAraW5w29z528BboXbiV87SM1kw==} + '@cspell/dynamic-import@10.3.3': + resolution: {integrity: sha512-9/V6879khIUrZVsB3lV1Xv1uENvrurAdfLkj1A659RSjc4cGao3ZfWZ6iEV3hRRoroO6616xlvpE/Fd9ojTBtw==} + engines: {node: '>=22.18.0'} + + '@cspell/dynamic-import@9.8.0': + resolution: {integrity: sha512-wMgb32lqG9g6lCipUQsY9Bk5idXPDz7wvzOqEsU1M2HmNYmdE1wfPoRpfQfsVL965iG3+6h8QLr2+8FKpweFEQ==} engines: {node: '>=20'} - '@cspell/filetypes@9.3.2': - resolution: {integrity: sha512-0bUxQlmJPRHZrRQD7adbc4lFizO8tGD/6+1cBgU3kV3+NVrpr12y4jU8twCSChhYibZyPr7bnvhkM3cQgb8RzA==} + '@cspell/eslint-plugin@10.3.3': + resolution: {integrity: sha512-OATL0AwQADvJvRus8kuJRTepiHeuqb4bd8GCTPgji8pA04B1Ir93cWq486UA7PYxZsgD3SDLs3n3yOb7pnf9Mg==} + engines: {node: '>=22.18.0'} + peerDependencies: + eslint: ^8 || ^9 || ^10 + + '@cspell/filetypes@10.3.3': + resolution: {integrity: sha512-HFKLXlgeIn+r4qEdBkJNVbmNCMphDGrF/42BHBssydYaeS4j3eWQqsSg+rWNHFJDfK0gsHPuxRjWORbp4F9hzQ==} + engines: {node: '>=22.18.0'} + + '@cspell/filetypes@9.8.0': + resolution: {integrity: sha512-yHvtYn9qt6zykua77sNzTcf7HrG/dpo/+2pCMGSrfSrQypSNT6FUFvMS04W7kwhP86U1GkCjppNykXuoH3cqug==} engines: {node: '>=20'} - '@cspell/strong-weak-map@9.3.2': - resolution: {integrity: sha512-pFcmOTWCoFMRETb9PCkCmaiZiLb5i2qOZmGH/p/tFEH8kIYhMGfhaulnXwKwS+Ke6PKceQd2YL98bGmo8hL4aQ==} + '@cspell/rpc@10.3.3': + resolution: {integrity: sha512-VcAqdtyer/CT/bq5gs4i7V61+sQgjXn+aGA6bVq9qUyivieX7Yo/Ue3reN81UWdsj7whlK++oBaf1Ds4alhFOw==} + engines: {node: '>=22.18.0'} + + '@cspell/rpc@9.8.0': + resolution: {integrity: sha512-t4lHEa254W+PePXNQ1noW7QhQxz/mhsJ9X8LEt0ILzBbPWCJzN+JuaM7EiolIPiwxtfxpMwKx9482kt4eTja7A==} + engines: {node: '>=20.18'} + + '@cspell/strong-weak-map@10.3.3': + resolution: {integrity: sha512-cXMVHROQtAIraRc62dQ1nX5h4vlc7O1EUT+GotiTx+BuwSTiMgBr/zue1pr+yQXoltExQUUuudSNsLRf/wZn5A==} + engines: {node: '>=22.18.0'} + + '@cspell/strong-weak-map@9.8.0': + resolution: {integrity: sha512-HocksAqZ0JcWA5oWO7TIlOCftXVGkPGzbeFlCRRrjJpZmYQH+4NdeEXyQC6T89NGocp45td/CgyBcAaFMy1N9w==} engines: {node: '>=20'} - '@cspell/url@9.3.2': - resolution: {integrity: sha512-TobUlZl7Z7VehhNOMNAg1ABuGizieseftlG94OZJ934JptOhK8TC/1o2ldKrbDH50jyt6E7rPTMV2BW/vWuTzQ==} + '@cspell/url@10.3.3': + resolution: {integrity: sha512-ZhsdSzfwXA/TuyqDb0nl+A9Kfd0W+rBIDdPxeXLvVsKFCtxVDa0zUYyhWhrtT9RtsPZQfRqPTkr+DsfWOzu4EA==} + engines: {node: '>=22.18.0'} + + '@cspell/url@9.8.0': + resolution: {integrity: sha512-LY1lFiZLTQF/ma1ilfKmRmFmEOw0RfYhyl0UMhY7/d93b+kiDMhxP/9Qir4+5LyiRncaE3++ZcWno9Hya+ssRg==} engines: {node: '>=20'} - '@emnapi/core@1.7.1': - resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + '@emnapi/core@1.10.0': + resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==} - '@emnapi/runtime@1.7.1': - resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + '@emnapi/runtime@1.10.0': + resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} - '@emnapi/wasi-threads@1.1.0': - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} '@es-joy/jsdoccomment@0.50.2': resolution: {integrity: sha512-YAdE/IJSpwbOTiaURNCKECdAwqrJuFiZhylmesBcIRawtYKnBR2wxPhoIewMg+Yu+QuYvHfJNReWpoxGBKOChA==} engines: {node: '>=18'} - '@esbuild/aix-ppc64@0.25.12': - resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.27.0': - resolution: {integrity: sha512-KuZrd2hRjz01y5JK9mEBSD3Vj3mbCvemhT466rSuJYeE/hjuBrHfjjcjMdTm/sz7au+++sdbJZJmuBwQLuw68A==} + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.25.12': - resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.27.0': - resolution: {integrity: sha512-CC3vt4+1xZrs97/PKDkl0yN7w8edvU2vZvAFGD16n9F0Cvniy5qvzRXjfO1l94efczkkQE6g1x0i73Qf5uthOQ==} + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.25.12': - resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-arm@0.27.0': - resolution: {integrity: sha512-j67aezrPNYWJEOHUNLPj9maeJte7uSMM6gMoxfPC9hOg8N02JuQi/T7ewumf4tNvJadFkvLZMlAq73b9uwdMyQ==} + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.25.12': - resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/android-x64@0.27.0': - resolution: {integrity: sha512-wurMkF1nmQajBO1+0CJmcN17U4BP6GqNSROP8t0X/Jiw2ltYGLHpEksp9MpoBqkrFR3kv2/te6Sha26k3+yZ9Q==} + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.25.12': - resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.27.0': - resolution: {integrity: sha512-uJOQKYCcHhg07DL7i8MzjvS2LaP7W7Pn/7uA0B5S1EnqAirJtbyw4yC5jQ5qcFjHK9l6o/MX9QisBg12kNkdHg==} + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.25.12': - resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.27.0': - resolution: {integrity: sha512-8mG6arH3yB/4ZXiEnXof5MK72dE6zM9cDvUcPtxhUZsDjESl9JipZYW60C3JGreKCEP+p8P/72r69m4AZGJd5g==} + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.25.12': - resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.27.0': - resolution: {integrity: sha512-9FHtyO988CwNMMOE3YIeci+UV+x5Zy8fI2qHNpsEtSF83YPBmE8UWmfYAQg6Ux7Gsmd4FejZqnEUZCMGaNQHQw==} + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.25.12': - resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.27.0': - resolution: {integrity: sha512-zCMeMXI4HS/tXvJz8vWGexpZj2YVtRAihHLk1imZj4efx1BQzN76YFeKqlDr3bUWI26wHwLWPd3rwh6pe4EV7g==} + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.25.12': - resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.27.0': - resolution: {integrity: sha512-AS18v0V+vZiLJyi/4LphvBE+OIX682Pu7ZYNsdUHyUKSoRwdnOsMf6FDekwoAFKej14WAkOef3zAORJgAtXnlQ==} + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.25.12': - resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.27.0': - resolution: {integrity: sha512-t76XLQDpxgmq2cNXKTVEB7O7YMb42atj2Re2Haf45HkaUpjM2J0UuJZDuaGbPbamzZ7bawyGFUkodL+zcE+jvQ==} + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.25.12': - resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.27.0': - resolution: {integrity: sha512-Mz1jxqm/kfgKkc/KLHC5qIujMvnnarD9ra1cEcrs7qshTUSksPihGrWHVG5+osAIQ68577Zpww7SGapmzSt4Nw==} + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.25.12': - resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.27.0': - resolution: {integrity: sha512-QbEREjdJeIreIAbdG2hLU1yXm1uu+LTdzoq1KCo4G4pFOLlvIspBm36QrQOar9LFduavoWX2msNFAAAY9j4BDg==} + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.25.12': - resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.27.0': - resolution: {integrity: sha512-sJz3zRNe4tO2wxvDpH/HYJilb6+2YJxo/ZNbVdtFiKDufzWq4JmKAiHy9iGoLjAV7r/W32VgaHGkk35cUXlNOg==} + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.25.12': - resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.27.0': - resolution: {integrity: sha512-z9N10FBD0DCS2dmSABDBb5TLAyF1/ydVb+N4pi88T45efQ/w4ohr/F/QYCkxDPnkhkp6AIpIcQKQ8F0ANoA2JA==} + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.25.12': - resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.27.0': - resolution: {integrity: sha512-pQdyAIZ0BWIC5GyvVFn5awDiO14TkT/19FTmFcPdDec94KJ1uZcmFs21Fo8auMXzD4Tt+diXu1LW1gHus9fhFQ==} + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.25.12': - resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.27.0': - resolution: {integrity: sha512-hPlRWR4eIDDEci953RI1BLZitgi5uqcsjKMxwYfmi4LcwyWo2IcRP+lThVnKjNtk90pLS8nKdroXYOqW+QQH+w==} + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.25.12': - resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.27.0': - resolution: {integrity: sha512-1hBWx4OUJE2cab++aVZ7pObD6s+DK4mPGpemtnAORBvb5l/g5xFGk0vc0PjSkrDs0XaXj9yyob3d14XqvnQ4gw==} + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.25.12': - resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-arm64@0.27.0': - resolution: {integrity: sha512-6m0sfQfxfQfy1qRuecMkJlf1cIzTOgyaeXaiVaaki8/v+WB+U4hc6ik15ZW6TAllRlg/WuQXxWj1jx6C+dfy3w==} + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.25.12': - resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.27.0': - resolution: {integrity: sha512-xbbOdfn06FtcJ9d0ShxxvSn2iUsGd/lgPIO2V3VZIPDbEaIj1/3nBBe1AwuEZKXVXkMmpr6LUAgMkLD/4D2PPA==} + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.25.12': - resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-arm64@0.27.0': - resolution: {integrity: sha512-fWgqR8uNbCQ/GGv0yhzttj6sU/9Z5/Sv/VGU3F5OuXK6J6SlriONKrQ7tNlwBrJZXRYk5jUhuWvF7GYzGguBZQ==} + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.25.12': - resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.27.0': - resolution: {integrity: sha512-aCwlRdSNMNxkGGqQajMUza6uXzR/U0dIl1QmLjPtRbLOx3Gy3otfFu/VjATy4yQzo9yFDGTxYDo1FfAD9oRD2A==} + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.25.12': - resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/openharmony-arm64@0.27.0': - resolution: {integrity: sha512-nyvsBccxNAsNYz2jVFYwEGuRRomqZ149A39SHWk4hV0jWxKM0hjBPm3AmdxcbHiFLbBSwG6SbpIcUbXjgyECfA==} + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.25.12': - resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.27.0': - resolution: {integrity: sha512-Q1KY1iJafM+UX6CFEL+F4HRTgygmEW568YMqDA5UV97AuZSm21b7SXIrRJDwXWPzr8MGr75fUZPV67FdtMHlHA==} + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.25.12': - resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.27.0': - resolution: {integrity: sha512-W1eyGNi6d+8kOmZIwi/EDjrL9nxQIQ0MiGqe/AWc6+IaHloxHSGoeRgDRKHFISThLmsewZ5nHFvGFWdBYlgKPg==} + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.25.12': - resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.27.0': - resolution: {integrity: sha512-30z1aKL9h22kQhilnYkORFYt+3wp7yZsHWus+wSKAJR8JtdfI76LJ4SBdMsCopTR3z/ORqVu5L1vtnHZWVj4cQ==} + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.25.12': - resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.27.0': - resolution: {integrity: sha512-aIitBcjQeyOhMTImhLZmtxfdOcuNRpwlPNmlFKPcHQYPhEssw75Cl1TSXJXpMkzaua9FUetx/4OQKq7eJul5Cg==} + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} engines: {node: '>=18'} cpu: [x64] os: [win32] - '@eslint-community/eslint-plugin-eslint-comments@4.5.0': - resolution: {integrity: sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg==} + '@eslint-community/eslint-plugin-eslint-comments@4.8.1': + resolution: {integrity: sha512-vafrdi15JHBFh1qWOAucyJwlEEuhdoMof28jOdKdgnwZ7bXwd6v4wzHYSmAVLwnx0yc7bqAtfJ0EZQV1WAzV/Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0 - '@eslint-community/eslint-utils@4.9.0': - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + '@eslint-community/eslint-utils@4.10.1': + resolution: {integrity: sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 @@ -850,43 +903,43 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-react/ast@2.3.9': - resolution: {integrity: sha512-/RiruPxlQs6CMLJ8tiNT1jV8Zq4u80MTWYkNFz2PP9pht23bdcpngDKFoz8RQYDPt71dwiRURHiQAF75v8bIIw==} + '@eslint-react/ast@2.13.0': + resolution: {integrity: sha512-43+5gmqV3MpatTzKnu/V2i/jXjmepvwhrb9MaGQvnXHQgq9J7/C7VVCCcwp6Rvp2QHAFquAAdvQDSL8IueTpeA==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/core@2.3.9': - resolution: {integrity: sha512-pIkrGuQWyW/GgrAp0kC7nv/Jn53Xjs1/rbBqUcUYvEZnVKuUifnlXQtnmioOEj9PYsuWuOxAPijExrnNavm73w==} + '@eslint-react/core@2.13.0': + resolution: {integrity: sha512-m62XDzkf1hpzW4sBc7uh7CT+8rBG2xz/itSADuEntlsg4YA7Jhb8hjU6VHf3wRFDwyfx5VnbV209sbJ7Azey0Q==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/eff@2.3.9': - resolution: {integrity: sha512-pkRWIPnH/jedRn5ZMEA0nDPn5BFuUHKOORbR+hfrAMFp4c3o+1/P1G/eB0vSQvAHAZdPwLZXdgxydz+2rbb8nQ==} + '@eslint-react/eff@2.13.0': + resolution: {integrity: sha512-rEH2R8FQnUAblUW+v3ZHDU1wEhatbL1+U2B1WVuBXwSKqzF7BGaLqCPIU7o9vofumz5MerVfaCtJgI8jYe2Btg==} engines: {node: '>=20.19.0'} - '@eslint-react/eslint-plugin@2.3.9': - resolution: {integrity: sha512-wKeXNa0vc8ACmvBoZPnRZ+s/z0KEmMKRxpOfRthcBvd0TPMIprohT/uwBXd8k15/j3CmaYe74pJFVVagJY3U3g==} + '@eslint-react/eslint-plugin@2.13.0': + resolution: {integrity: sha512-iaMXpqnJCTW7317hg8L4wx7u5aIiPzZ+d1p59X8wXFgMHzFX4hNu4IfV8oygyjmWKdLsjKE9sEpv/UYWczlb+A==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/shared@2.3.9': - resolution: {integrity: sha512-LVtD76ycDC7D4OFKDQ8jyATTVxz986J+e9nzydyEUtEf1l+WYiOivPBeJUAs6JEySBl24nO76oEHDABw6l4hig==} + '@eslint-react/shared@2.13.0': + resolution: {integrity: sha512-IOloCqrZ7gGBT4lFf9+0/wn7TfzU7JBRjYwTSyb9SDngsbeRrtW95ZpgUpS8/jen1wUEm6F08duAooTZ2FtsWA==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - '@eslint-react/var@2.3.9': - resolution: {integrity: sha512-Bc36K8Lw6KV/5NMaEaFS7as4kgSgZ1wElFejgUEBPZnhUVmq2mITV1BsnMoMYM4jojnkMN80WNALyhONjOx9Jw==} + '@eslint-react/var@2.13.0': + resolution: {integrity: sha512-dM+QaeiHR16qPQoJYg205MkdHYSWVa2B7ore5OFpOPlSwqDV3tLW7I+475WjbK7potq5QNPTxRa7VLp9FGeQqA==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' '@eslint/compat@1.4.1': @@ -898,8 +951,8 @@ packages: eslint: optional: true - '@eslint/config-array@0.21.1': - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/config-helpers@0.4.2': @@ -918,12 +971,12 @@ packages: resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + '@eslint/eslintrc@3.3.7': + resolution: {integrity: sha512-F42g89Qd5oAWtp0k0nnSrjziAKza7w8SVT4mStc18LZMaRb4J1HQAHLCalEtDCxrTuksx7NU9qsmeLwpOfPqWw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.39.1': - resolution: {integrity: sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==} + '@eslint/js@9.39.5': + resolution: {integrity: sha512-QywQuszQh77pIXCsq998c8hbhSTI/azTty1Z6N53dmAudKHhy573j3yvRLsX2BSp8YpLtoCEG8E9DJe+8zUh4A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/markdown@6.6.0': @@ -946,12 +999,16 @@ packages: resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + '@humanfs/core@0.19.2': + resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.8': + resolution: {integrity: sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==} engines: {node: '>=18.18.0'} - '@humanfs/node@0.16.7': - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + '@humanfs/types@0.15.0': + resolution: {integrity: sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==} engines: {node: '>=18.18.0'} '@humanwhocodes/module-importer@1.0.1': @@ -962,14 +1019,6 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} - '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -984,48 +1033,29 @@ packages: resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@jsep-plugin/assignment@1.3.0': - resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 - - '@jsep-plugin/regex@1.0.4': - resolution: {integrity: sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==} - engines: {node: '>= 10.16.0'} - peerDependencies: - jsep: ^0.4.0||^1.0.0 + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + resolution: {integrity: sha512-oTXEIha4SsuXdTA4Iyskj0kpdx2yVXdhd75c2v3xGrHFfVMsbhTPZU/nMPL4sWKo4pBHm3aucLaqGlF696dTyQ==} + engines: {node: ^22.20 || ^24.12 || >=25} + cpu: [x64] + os: [linux] + libc: [glibc] - '@jsep-plugin/ternary@1.1.4': - resolution: {integrity: sha512-ck5wiqIbqdMX6WRQztBL7ASDty9YLgJ3sSAK5ZpBzXeySvFGCzIvM6UiAI4hTZ22fEcYQVV/zhUbNscggW+Ukg==} - engines: {node: '>= 10.16.0'} + '@napi-rs/wasm-runtime@1.2.4': + resolution: {integrity: sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} peerDependencies: - jsep: ^0.4.0||^1.0.0 - - '@napi-rs/wasm-runtime@0.2.12': - resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 '@nodable/entities@3.0.0': resolution: {integrity: sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==} - '@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'} - '@octokit/auth-token@4.0.0': resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} engines: {node: '>= 18'} @@ -1092,9 +1122,9 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@pkgr/core@0.2.9': - resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@pkgr/core@0.3.6': + resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} + engines: {node: ^14.18.0 || >=16.0.0} '@protobuf-ts/plugin@2.11.1': resolution: {integrity: sha512-HyuprDcw0bEEJqkOWe1rnXUP0gwYLij8YhPuZyZk6cJbIgc/Q0IFgoHQxOXNIXAcXM4Sbehh6kjVnCzasElw1A==} @@ -1113,286 +1143,185 @@ packages: '@redocly/ajv@8.18.3': resolution: {integrity: sha512-l42u0of3hY98sN2A+M4qTX1O/KrpgGH32Hu9kP2GtHyD5Dfqq86PKFLe5dwaD8DEnNmlOlll2BAmeEtf0DaySg==} - '@redocly/cli@2.49.0': - resolution: {integrity: sha512-87UuARXYrPIiHhd/UriamL4BApuPgB0E91coBtoPG6PK4giTwiuo3dI4RoyMGhsC7TwgAnL8PJuhCwGymgwbVA==} + '@redocly/cli@2.54.3': + resolution: {integrity: sha512-tgjCjKm9NjcbN0N04dylwUw8eZzematq07JHm+dVyPkAfA/eZEN57En7jpUYrPvwOb53MJLfDB/0qJ5iz/4eHQ==} engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} hasBin: true - '@redocly/config@0.53.1': - resolution: {integrity: sha512-aOldTWynKS3ZM6u8WkL72d94QBobITv9X6UECiZykgVjdLiAqV737bPVLGKJYPWf0Ryf3zSHgUYALjCj66BkdA==} + '@redocly/config@0.57.0': + resolution: {integrity: sha512-mpxsAe0/PzfD0B03oeJUaNUNMaJPPyqznfIJtl7YMn+Fw0Qo14+ZRl16sab+jZVZSiYPYtMYLunGZZozXPvyRw==} - '@redocly/openapi-core@2.49.0': - resolution: {integrity: sha512-EoawTPEubDThlHGwJCwHDZgCuEYGWt4iFMDorSWWnSB8ZK1/8PAowohB1U6qumgcuTu0Md0BYSgueL1TNgF7qw==} + '@redocly/openapi-core@2.54.3': + resolution: {integrity: sha512-8RXEKuDnqhJhYB2vw0eZpowr2P/aytYTHcHmwk5Yb8WKNwokwM7dHnrIBwb7zwovzWYFvLI5RJ+d1FXUvjFjyg==} engines: {node: '>=22.12.0 || >=20.19.0 <21.0.0', npm: '>=10'} - '@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 - - '@rollup/rollup-android-arm-eabi@4.53.3': - resolution: {integrity: sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==} + '@rollup/rollup-android-arm-eabi@4.63.4': + resolution: {integrity: sha512-I+BSHzTAhKN2n7ZwGZsegGcZjDpLqFOMAtJz/u6uFGe0pUFbq56dEHjqJV/ZUdRJtNXNxA+hREUatZBvMR3Oiw==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.53.3': - resolution: {integrity: sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==} + '@rollup/rollup-android-arm64@4.63.4': + resolution: {integrity: sha512-pu3BdjS2LtEzRu2elmGzS3fIeWSZy4BMDIaLNwjorO76+k2d0LMluijhsDx3KQyQBQ/lLUZCQA9/s6csvUfuhw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.53.3': - resolution: {integrity: sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==} + '@rollup/rollup-darwin-arm64@4.63.4': + resolution: {integrity: sha512-xfSrj9MHnWK9GaSqT9U0ImHtH/N8WZlHLx4cZHiuLcqs640hvZ3hLPd5UR2AZS57FaE8HrRUSpltbZdWRxHiDA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.53.3': - resolution: {integrity: sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==} + '@rollup/rollup-darwin-x64@4.63.4': + resolution: {integrity: sha512-bqU99PLJb/dqb3S0GIMdeuyAEETSUgZBoqXYd3Sd+WCsV+MmPhnN6JrotWyir31+QgH7EvvE5/mwGJlEoci8Fw==} cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.53.3': - resolution: {integrity: sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==} + '@rollup/rollup-freebsd-arm64@4.63.4': + resolution: {integrity: sha512-JinsFZ5G40oXQb+sUuiA5x689vhr6dDYK0H0NL+rwKdL6CqnmYN8PE4ZwfRSoIjrCxqTQG/SLfTtSvHeGxoVlw==} cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.53.3': - resolution: {integrity: sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==} + '@rollup/rollup-freebsd-x64@4.63.4': + resolution: {integrity: sha512-GAdA4UxpiNm27cLHr2GqXBpAD0x9FqwYBY7/YSP0Ss0/PNi4k8gbviqpIpYbVSRBaS2ZcegXEzgTQMbRNCwxCw==} cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': - resolution: {integrity: sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==} + '@rollup/rollup-linux-arm-gnueabihf@4.63.4': + resolution: {integrity: sha512-qDd6NoA1znaLjp4jR5U/KWCdLAKDJNB8W9ChbbDaKbo0xA+Atln5HK6LFCZ4oJQpemtRZA288DCirFRjrspptw==} cpu: [arm] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm-musleabihf@4.53.3': - resolution: {integrity: sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==} + '@rollup/rollup-linux-arm-musleabihf@4.63.4': + resolution: {integrity: sha512-WtB5Tz5KTNINb8ZA+8sQ7bmjuS1JrRT7YverYIhUGdWWDlpzVWmIwuZE+jidkEXUn1l0zrEkaIMa8dHF3NGcsA==} cpu: [arm] os: [linux] libc: [musl] - '@rollup/rollup-linux-arm64-gnu@4.53.3': - resolution: {integrity: sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==} + '@rollup/rollup-linux-arm64-gnu@4.63.4': + resolution: {integrity: sha512-VcQ3L1tjnkKzWjryAVaFhHEWcqOfICX9uxVVoDzm2t0DpgKRHd2zOpVrJc0xsWeBZcBFyYROCIBdyR/fS174pg==} cpu: [arm64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-arm64-musl@4.53.3': - resolution: {integrity: sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==} + '@rollup/rollup-linux-arm64-musl@4.63.4': + resolution: {integrity: sha512-6+ZQX6P5s0cMDN2Ypb8Lbm2+/sZYmZjdaYny992ujUU9UKi/4CWoJWsl1pNvjWJHNHGK51m+jKGLlh1ylb2ifQ==} cpu: [arm64] os: [linux] libc: [musl] - '@rollup/rollup-linux-loong64-gnu@4.53.3': - resolution: {integrity: sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==} + '@rollup/rollup-linux-loong64-gnu@4.63.4': + resolution: {integrity: sha512-D72ZnvkFkBXOfzMMQLcwfPLyGkKb7HZ9/mf97B7v6/P5Lbv4oFOtSY/uHbS8lH6uKUOxoKiuokdb50XZSzzbJw==} cpu: [loong64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-ppc64-gnu@4.53.3': - resolution: {integrity: sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==} + '@rollup/rollup-linux-loong64-musl@4.63.4': + resolution: {integrity: sha512-piU6BxeqA3O9KSu3kRCIQQtNqFFaTu21SEV4FwaRZowpnj3bLaWPZHw+xFqCs0XlJ+aOH3PTRWGoglH+mKA/OA==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-ppc64-gnu@4.63.4': + resolution: {integrity: sha512-/5PGpHwqt2EEEOUs1XwzubE/ucr0dWDQ+to3zqi4Ds7EWpwtQ79wXc4JBoxqj/OwpawTsKWzJxHfSuBOq3DrWA==} cpu: [ppc64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-gnu@4.53.3': - resolution: {integrity: sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==} + '@rollup/rollup-linux-ppc64-musl@4.63.4': + resolution: {integrity: sha512-cX3beZDLWt7G2oJF+nhChiT+qtaihs+S2xi7ziGmVB+2pwPng6D0Ed0HmElQOgv2UsUmSJJLGwpBao/3TDx3VA==} + cpu: [ppc64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-riscv64-gnu@4.63.4': + resolution: {integrity: sha512-1uz2mGWHyptR7DgHHrlbdRAjXK7v7elGZ9lMja910/RP+ZYbX6xAmCiU9UZSX4hqmgtHMv6lr5l3kq1HIOpcag==} cpu: [riscv64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-riscv64-musl@4.53.3': - resolution: {integrity: sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==} + '@rollup/rollup-linux-riscv64-musl@4.63.4': + resolution: {integrity: sha512-nLS8topojxyz7SRpKR2IODRpQ0XPZ+xaOXvT3+hqK/Uy8Lo5HFgkkIBiIrCu5tL5YqzTvgovGw55PwpahTAGig==} cpu: [riscv64] os: [linux] libc: [musl] - '@rollup/rollup-linux-s390x-gnu@4.53.3': - resolution: {integrity: sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==} + '@rollup/rollup-linux-s390x-gnu@4.63.4': + resolution: {integrity: sha512-gs7DRKotr3l3q+jGPQBjH0ng1FjlEDm5ueQrkw5JtQvtLyEIcLASqAEaor56BhkKRzk+IcQzrcanBdb/bBQn8g==} cpu: [s390x] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-gnu@4.53.3': - resolution: {integrity: sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==} + '@rollup/rollup-linux-x64-gnu@4.63.4': + resolution: {integrity: sha512-791ET7W17NnScOZM7h4dX5hYspxE28htPFsb1awY/NRR8+PRNkS53e475rDdxXXDrP+kwnCcNWg9CX5ztn/Aqw==} cpu: [x64] os: [linux] libc: [glibc] - '@rollup/rollup-linux-x64-musl@4.53.3': - resolution: {integrity: sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==} + '@rollup/rollup-linux-x64-musl@4.63.4': + resolution: {integrity: sha512-iwZQRcmj7g88g3tzefIrQY7qvmuA/cfYwhrDtTBhsmukO4U2huVO5W+86XacUMRvdSFVAc6kZUZy21JaRwiB9w==} cpu: [x64] os: [linux] libc: [musl] - '@rollup/rollup-openharmony-arm64@4.53.3': - resolution: {integrity: sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==} + '@rollup/rollup-openbsd-x64@4.63.4': + resolution: {integrity: sha512-dVHFp9gRWrdTpnqQuGfCwd7hOQDatK1VCP2iWhLY/cGrOQs/ucFzJ6A5SRqbXX12ZDI8EUuejSM5kwg+ja7Png==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.63.4': + resolution: {integrity: sha512-t3NlauOW6gxZVVFcBEnO62Cb4wbyDFL416gTg1uFI/2tgqYQlf69FbSE115Ajre9I+c26Lk4mcmdFUsS/DGifQ==} cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.53.3': - resolution: {integrity: sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==} + '@rollup/rollup-win32-arm64-msvc@4.63.4': + resolution: {integrity: sha512-xWuIaSye5FWZF8+UYtVEcHtRJDN5kN9Kfgxx3Kq8XIov9KSKbc1fiqQCm90SKrgQbUXZelbnUhnlUJmfSE7P9A==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.53.3': - resolution: {integrity: sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==} + '@rollup/rollup-win32-ia32-msvc@4.63.4': + resolution: {integrity: sha512-9ALJJUOg/ZflMJepVo2PlgsGxSaxN7SQ4Z8GoZfVlarWr6r3rkHUNsd/zAio7p4YMtChSMXPionxej4Hkf6CXQ==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-gnu@4.53.3': - resolution: {integrity: sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==} + '@rollup/rollup-win32-x64-gnu@4.63.4': + resolution: {integrity: sha512-blj9z5qx/Pv4WU0W1NMFDB97e0JH5ed+aZGywW8WCvp/NhWX/4PFAq5uu6Q0AebNn+Vo6KzUYDT++JzTT5ojlQ==} cpu: [x64] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.53.3': - resolution: {integrity: sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==} + '@rollup/rollup-win32-x64-msvc@4.63.4': + resolution: {integrity: sha512-Erx822VRBwLa124shbj+wNXe//BOgMEctDV0m1aqTQdNO1S69DgNUCFKC1RCeZfixs1J31l6igk1ziyXErbigQ==} cpu: [x64] os: [win32] - '@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.15.0': - resolution: {integrity: sha512-FVeQIuqQQnnLfa8vy+oatTKUve7uU+3SaaAfdjpX/B+uB1NcfkKRJYhKT9wMEehDRaMPL5AKIRYMCFerdEbIpw==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - hasBin: true - - '@stoplight/spectral-core@1.20.0': - resolution: {integrity: sha512-5hBP81nCC1zn1hJXL/uxPNRKNcB+/pEIHgCjPRpl/w/qy9yC9ver04tw1W0l/PMiv0UeB5dYgozXVQ4j5a6QQQ==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-formats@1.8.2': - resolution: {integrity: sha512-c06HB+rOKfe7tuxg0IdKDEA5XnjL2vrn/m/OVIIxtINtBzphZrOgtRn7epQ5bQF5SWp84Ue7UJWaGgDwVngMFw==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-formatters@1.5.0': - resolution: {integrity: sha512-lR7s41Z00Mf8TdXBBZQ3oi2uR8wqAtR6NO0KA8Ltk4FSpmAy0i6CKUmJG9hZQjanTnGmwpQkT/WP66p1GY3iXA==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-functions@1.10.1': - resolution: {integrity: sha512-obu8ZfoHxELOapfGsCJixKZXZcffjg+lSoNuttpmUFuDzVLT3VmH8QkPXfOGOL5Pz80BR35ClNAToDkdnYIURg==} - 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.6.3': - resolution: {integrity: sha512-AQFRO6OCKg8SZJUupnr3+OzI1LrMieDTEUHsYgmaRpNiDRPvzImE3bzM1KyQg99q58kTQyZ8kpr7sG8Lp94RRA==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-ruleset-migrator@1.11.3': - resolution: {integrity: sha512-+9Y1zFxYmSsneT5FPkgS1IlRQs0VgtdMT77f5xf6vzje9ezyhfs7oXwbZOCSZjEJew8iVZBKQtiOFndcBrdtqg==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-rulesets@1.22.0': - resolution: {integrity: sha512-l2EY2jiKKLsvnPfGy+pXC0LeGsbJzcQP5G/AojHgf+cwN//VYxW1Wvv4WKFx/CLmLxc42mJYF2juwWofjWYNIQ==} - engines: {node: ^16.20 || ^18.18 || >= 20.17} - - '@stoplight/spectral-runtime@1.1.4': - resolution: {integrity: sha512-YHbhX3dqW0do6DhiPSgSGQzr6yQLlWybhKwWx0cqxjMwxej3TqLv3BXMfIUYFKKUqIwH4Q2mV8rrMM8qD2N0rQ==} - 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'} - '@stylistic/eslint-plugin@2.13.0': resolution: {integrity: sha512-RnO1SaiCFHn666wNz2QfZEFxvmiNRqhzaMXHXxXXKt+MEP7aajlPxUSMIQpKAaJfverpovEYqjBOXDq6dDcaOQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.40.0' - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - - '@types/bun@1.3.3': - resolution: {integrity: sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g==} - - '@types/debug@4.1.12': - resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@tybys/wasm-util@0.10.4': + resolution: {integrity: sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==} - '@types/es-aggregate-error@1.0.6': - resolution: {integrity: sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg==} + '@types/bun@1.4.2': + resolution: {integrity: sha512-GimotNn7+ZV0uVArItBbriZsR1oNf0+WTzPkdcFrzShI7k2norL0uzEaJT8T33dWr7O/c9ZDuAFQrctKCi72oQ==} - '@types/estree@0.0.39': - resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + '@types/debug@4.1.13': + resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/markdown-escape@1.1.3': - resolution: {integrity: sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw==} - '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@24.10.1': - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@24.13.6': + resolution: {integrity: sha512-SGrw/h3KPFshy3OE6ZL53LMBG5vGQQ8/gIpiqz/kRZhPJ7HgwCEs8LBuNtWLa8dvGZVpSF7+Bf+c11HUrCb/yg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -1400,72 +1329,66 @@ packages: '@types/pluralize@0.0.33': resolution: {integrity: sha512-JOqsl+ZoCpP4e8TDke9W79FDcSgPAR0l6pixx2JHkhnRjvShyYiAYw2LVsnA7K08Y6DeOnaU6ujmENO4os/cYg==} - '@types/sarif@2.1.7': - resolution: {integrity: sha512-kRz0VEkJqWLf1LLVN4pT1cg1Z9wAuvI6L97V3m2f5B76Tg8d413ddvLBPTEHAZJlnn4XSvu0FkZtViCQGVyrXQ==} - '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - '@types/urijs@1.19.26': - resolution: {integrity: sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg==} - - '@typescript-eslint/eslint-plugin@8.48.0': - resolution: {integrity: sha512-XxXP5tL1txl13YFtrECECQYeZjBZad4fyd3cFV4a19LkAY/bIp9fev3US4S5fDVV2JaYFiKAZ/GRTOLer+mbyQ==} + '@typescript-eslint/eslint-plugin@8.70.0': + resolution: {integrity: sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.48.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser': ^8.70.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.48.0': - resolution: {integrity: sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==} + '@typescript-eslint/parser@8.70.0': + resolution: {integrity: sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.48.0': - resolution: {integrity: sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==} + '@typescript-eslint/project-service@8.70.0': + resolution: {integrity: sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.48.0': - resolution: {integrity: sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==} + '@typescript-eslint/scope-manager@8.70.0': + resolution: {integrity: sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.48.0': - resolution: {integrity: sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==} + '@typescript-eslint/tsconfig-utils@8.70.0': + resolution: {integrity: sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.48.0': - resolution: {integrity: sha512-zbeVaVqeXhhab6QNEKfK96Xyc7UQuoFWERhEnj3mLVnUWrQnv15cJNseUni7f3g557gm0e46LZ6IJ4NJVOgOpw==} + '@typescript-eslint/type-utils@8.70.0': + resolution: {integrity: sha512-NUMKIhYVaVIVLnRL9CRt+VVcuLgSHUCpXn4/+K8wql+vdInUzvx8BjUO1oJ7cG9shjFJKtF8F8Hh2kCh3/KBVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.48.0': - resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==} + '@typescript-eslint/types@8.70.0': + resolution: {integrity: sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.48.0': - resolution: {integrity: sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==} + '@typescript-eslint/typescript-estree@8.70.0': + resolution: {integrity: sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <6.0.0' + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.48.0': - resolution: {integrity: sha512-yTJO1XuGxCsSfIVt1+1UrLHtue8xz16V8apzPYI06W0HbEbEWHxHXgZaAgavIkoh+GeV6hKKd5jm0sS6OYxWXQ==} + '@typescript-eslint/utils@8.70.0': + resolution: {integrity: sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <6.0.0' + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.48.0': - resolution: {integrity: sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==} + '@typescript-eslint/visitor-keys@8.70.0': + resolution: {integrity: sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@typescript/vfs@1.6.4': @@ -1473,121 +1396,141 @@ packages: peerDependencies: typescript: '*' - '@typespec/ts-http-runtime@0.3.8': - resolution: {integrity: sha512-bLMpVcWZNzq6lYOybwFwOAR1IXKcHnhUNqYeHjl1bET/qE3jFPFH+p8Wrh3rU4xwdnifPxmKNESBYnvnmc75aA==} + '@typespec/ts-http-runtime@0.3.9': + resolution: {integrity: sha512-edSdeAqkdxBVzA1yL1LrLCml1YjyCVvPMtMqJpbF+6K609tHe8V6sQUzFQSGcYNhcuhOceZtjvN32+mpIth30A==} engines: {node: '>=22.0.0'} - '@unrs/resolver-binding-android-arm-eabi@1.11.1': - resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} + '@unrs/resolver-binding-android-arm-eabi@1.12.2': + resolution: {integrity: sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==} cpu: [arm] os: [android] - '@unrs/resolver-binding-android-arm64@1.11.1': - resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==} + '@unrs/resolver-binding-android-arm64@1.12.2': + resolution: {integrity: sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==} cpu: [arm64] os: [android] - '@unrs/resolver-binding-darwin-arm64@1.11.1': - resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==} + '@unrs/resolver-binding-darwin-arm64@1.12.2': + resolution: {integrity: sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==} cpu: [arm64] os: [darwin] - '@unrs/resolver-binding-darwin-x64@1.11.1': - resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==} + '@unrs/resolver-binding-darwin-x64@1.12.2': + resolution: {integrity: sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==} cpu: [x64] os: [darwin] - '@unrs/resolver-binding-freebsd-x64@1.11.1': - resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==} + '@unrs/resolver-binding-freebsd-x64@1.12.2': + resolution: {integrity: sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==} cpu: [x64] os: [freebsd] - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': - resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==} + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': + resolution: {integrity: sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': - resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==} + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': + resolution: {integrity: sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': - resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': + resolution: {integrity: sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==} cpu: [arm64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': - resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': + resolution: {integrity: sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==} cpu: [arm64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': - resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': + resolution: {integrity: sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': + resolution: {integrity: sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==} + cpu: [loong64] + os: [linux] + libc: [musl] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': + resolution: {integrity: sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==} cpu: [ppc64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': - resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': + resolution: {integrity: sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==} cpu: [riscv64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': - resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': + resolution: {integrity: sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==} cpu: [riscv64] os: [linux] libc: [musl] - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': - resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': + resolution: {integrity: sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==} cpu: [s390x] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': - resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + resolution: {integrity: sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==} cpu: [x64] os: [linux] libc: [glibc] - '@unrs/resolver-binding-linux-x64-musl@1.11.1': - resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + resolution: {integrity: sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==} cpu: [x64] os: [linux] libc: [musl] - '@unrs/resolver-binding-wasm32-wasi@1.11.1': - resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + resolution: {integrity: sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==} + cpu: [arm64] + os: [openharmony] + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': + resolution: {integrity: sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': - resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==} + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': + resolution: {integrity: sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==} cpu: [arm64] os: [win32] - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': - resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==} + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': + resolution: {integrity: sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==} cpu: [ia32] os: [win32] - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': - resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==} + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': + resolution: {integrity: sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==} cpu: [x64] os: [win32] - '@vitest/eslint-plugin@1.5.0': - resolution: {integrity: sha512-j3uuIAPTYWYnSit9lspb08/EKsxEmGqjQf+Wpb1DQkxc+mMkhL58ZknDCgjYhY4Zu76oxZ0hVWTHlmRW0mJq5w==} + '@vitest/eslint-plugin@1.6.27': + resolution: {integrity: sha512-X1RCAfwbatG4GFbJ/1PIHP9MSZMt0JJThqbYID+vS4L783k6QGlLPe421wQE8dHXuGCcenVLsydiM4qzsYWxhg==} engines: {node: '>=18'} peerDependencies: + '@typescript-eslint/eslint-plugin': '*' eslint: '>=8.57.0' typescript: '>=5.0.0' vitest: '*' peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true typescript: optional: true vitest: @@ -1617,8 +1560,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} engines: {node: '>=0.4.0'} hasBin: true @@ -1626,27 +1569,6 @@ packages: resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} engines: {node: '>= 14'} - 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-formats@3.0.1: resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} peerDependencies: @@ -1655,18 +1577,15 @@ packages: ajv: optional: true - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + ansi-regex@6.3.0: + resolution: {integrity: sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ==} engines: {node: '>=12'} ansi-styles@4.3.0: @@ -1698,41 +1617,14 @@ packages: 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'} - array-timsort@1.0.3: resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} - 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'} - async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - - b4a@1.8.1: - resolution: {integrity: sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==} + b4a@1.9.0: + resolution: {integrity: sha512-dpfcF9fDNR6++cthXR67iyhgqWy9CBouAvIWhIntzBG6cvK/cnIPiZQjBwi/ZqjjBEDGfoNDtmB0kTjroOJ3pQ==} peerDependencies: react-native-b4a: '*' peerDependenciesMeta: @@ -1742,16 +1634,20 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.9.1: - resolution: {integrity: sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + bare-events@2.9.2: + resolution: {integrity: sha512-AIPKioV7/Y/8KfZ3AAhjPJxLLbY49S64Ym5DakZlUg75qQiTgUq9hEJoEwa4eUezPUlXRy/i5NpsKvo9jgKmoA==} peerDependencies: bare-abort-controller: '*' peerDependenciesMeta: bare-abort-controller: optional: true - bare-fs@4.8.0: - resolution: {integrity: sha512-fM+MhCvdQhZ7NV6S95a07gPSqjIYKn6mFaXfx266wN3ajZGl/+1AzH+ubkXQ0fFZvOe2nk9VHkzdYkQE5zMV3Q==} + bare-fs@4.8.1: + resolution: {integrity: sha512-N1nnXdHZAOSstz0XiHikGS4HGMH4CnSwhqWdGQQMqqdvp4Jybm9sE3R1WVnpWVd4SFkc8ryPDBLViNLwiEqECg==} engines: {bare: '>=1.28.0'} peerDependencies: bare-buffer: '*' @@ -1759,11 +1655,11 @@ packages: bare-buffer: optional: true - bare-path@3.1.1: - resolution: {integrity: sha512-JprUlveX3QjApC1cTpsUOiscADftCGVWkzitbHsRqv84hzYwYHw2mbluddsq5TvI8mH/8Ov1f4BiMAdcB0oYnQ==} + bare-path@3.1.2: + resolution: {integrity: sha512-ZyKbsuuqK6Ag0K8pX6V5Txq6XeJRvY+wXucnFGRjiyVYP9YWDpIQugk/b+enRYrEYBJaqLzghRQpXPMR7341Nw==} - bare-stream@2.13.3: - resolution: {integrity: sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ==} + bare-stream@2.13.4: + resolution: {integrity: sha512-PcrQ8lVLbiJscNm1Kez+Yp4Gy4AHGcN1lzwjvf5NybWen7VvEgUfyfnXYJ2zNqWnzOfCb1Abq6lH8ti0syQszA==} peerDependencies: bare-abort-controller: '*' bare-buffer: '*' @@ -1776,14 +1672,15 @@ packages: bare-events: optional: true - bare-url@2.5.1: - resolution: {integrity: sha512-cD5ciQuKlx+eumTCfqbfiL+fhQm+dHbVNB/cX4+d+I/nx4JsVop9VoFEPAs5RJ6I84QR6bZIBjpd2kjDOYeWcg==} + bare-url@2.5.4: + resolution: {integrity: sha512-Gxa7UVWBr0/edU1b+TJhn/AZvMQUj9OGspvYsaTYQrAbZA4BOTZGL3LiZxvD+CeMlDH4juwD84+eTAp/bLYW5g==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.8.31: - resolution: {integrity: sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==} + baseline-browser-mapping@2.11.25: + resolution: {integrity: sha512-gMmEShwwq7FJqMwvfRwvCl00v4kN+KOfJqXn+f4nrufak5gNHJOksd/60Dvjuz7sI8Y5WiSFBa8FEYr+zoyqCw==} + engines: {node: '>=6.0.0'} hasBin: true before-after-hook@2.2.3: @@ -1792,8 +1689,8 @@ packages: binary@0.3.0: resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} - birecord@0.1.1: - resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==} + birecord@0.1.2: + resolution: {integrity: sha512-5PAPTTmMpMEb+GuMb5DebfBkipRGyIW9+gtwEBSoDA9xkhHILm04+hZQ702pMksu3d8YAuGkmgTzQWcKqTPScA==} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -1801,18 +1698,18 @@ packages: bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + brace-expansion@1.1.21: + resolution: {integrity: sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==} - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@2.1.7: + resolution: {integrity: sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} - browserslist@4.28.0: - resolution: {integrity: sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==} + browserslist@4.29.0: + resolution: {integrity: sha512-3GSvyjvDI4Dur1Meg2BekJquu5uF+9R9a1+5M1Mde192eZoXbeXjzgOsgqPS2V8D5wrrip0gR5Hf/GhWQ9ZzaA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true @@ -1831,11 +1728,8 @@ packages: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} - builtins@1.0.3: - resolution: {integrity: sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ==} - - bun-types@1.3.3: - resolution: {integrity: sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ==} + bun-types@1.4.2: + resolution: {integrity: sha512-bxV1FgK7yBIzjRe5zBozIM4Bem11ZJcCXSrjWRG3YWLt8yFDePu4cLjpebO8OvPeIE9trbyPF4fuj3Cia4Fj3w==} bundle-require@5.1.0: resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} @@ -1847,24 +1741,12 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - call-bind-apply-helpers@1.0.2: - resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} - engines: {node: '>= 0.4'} - - call-bind@1.0.8: - resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} - engines: {node: '>= 0.4'} - - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001757: - resolution: {integrity: sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==} + caniuse-lite@1.0.30001810: + resolution: {integrity: sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==} ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} @@ -1894,21 +1776,18 @@ packages: resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} engines: {node: '>= 14.16.0'} - ci-info@4.3.1: - resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} + ci-info@4.4.0: + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} engines: {node: '>=8'} clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} - clear-module@4.1.2: - resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} + clear-module@4.1.3: + resolution: {integrity: sha512-XdLrg7BnbXKntyrbs2dNjDN9CVoTQ+WV0i7jT5/r9ahzAaSDSzC9e2OVZB/QVwbxBb1/1AeObzjlxsYk5HFvww==} engines: {node: '>=8'} - 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'} @@ -1923,24 +1802,29 @@ packages: colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} - commander@14.0.2: - resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} - comment-json@4.4.1: - resolution: {integrity: sha512-r1To31BQD5060QdkC+Iheai7gHwoSZobzunqkf2/kQ6xIAfJyrKNAFUwdKvkK7Qgu7pVTKQEa7ok7Ed3ycAJgg==} + comment-json@4.6.2: + resolution: {integrity: sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==} + engines: {node: '>= 6'} + + comment-json@5.0.0: + resolution: {integrity: sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw==} engines: {node: '>= 6'} comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} - commondir@1.0.1: - resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + comment-parser@1.4.9: + resolution: {integrity: sha512-+2AvZKjJaNq9GQljm3tr0utwrig5BL+jgJGvz5rDpGKNIp+ojcRXWUwBbh/sGIi1QCprR6PsKFakub+w1v+4hQ==} + engines: {node: '>= 12.0.0'} compare-versions@6.1.1: resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} @@ -1955,15 +1839,16 @@ packages: confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - confbox@0.2.2: - resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} + confbox@0.3.1: + resolution: {integrity: sha512-cKUSoKa8YxFZZSmraVi7onONx3amu77ngK3kGpsYHDH7drPwCRkQE1RYMPlLRrMtnciRj274XNRxcHxnKmDSnA==} consola@3.4.2: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - core-js-compat@3.47.0: - resolution: {integrity: sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==} + core-js-compat@3.50.0: + resolution: {integrity: sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==} + engines: {node: '>=6.4.0'} core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} @@ -1981,43 +1866,76 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - cspell-config-lib@9.3.2: - resolution: {integrity: sha512-zXhmA4rqgWQRTVijI+g/mgiep76TvTO4d+P3CHwcqLG57BKVzoW+jkO4qDLC+Neh4b8+CcNWEIr3w16BfuEJAA==} + cspell-config-lib@10.3.3: + resolution: {integrity: sha512-6u5s+LLLqXxhhtSDz/ft40LIZ2u4YxEPJxaOnojXleMZzDxSQskyuAG72R2vIjJOYjxevK0vb/f3rnZ+cSmnVw==} + engines: {node: '>=22.18.0'} + + cspell-config-lib@9.8.0: + resolution: {integrity: sha512-gMJBAgYPvvO+uDFLUcGWaTu6/e+r8mm4GD4rQfWa/yV4F9fj+yOYLIMZqLWRvT1moHZX1FxyVvUbJcmZ1gfebg==} engines: {node: '>=20'} - cspell-dictionary@9.3.2: - resolution: {integrity: sha512-E3YhOhZzZt1a+AEbFV2B3THCyZ576PDg0mDNUDrU1Y65SyIhf4DC6itfPoAb6R3FI/DI218RqWZg/FTT8lJ2gA==} + cspell-dictionary@10.3.3: + resolution: {integrity: sha512-uHYhIfByu1iB2tBZdxbCAh8mMqMrxcWi/u5d1kdXBPqCa5QpsFv316CaUNgcU/pmDp6ZAti4QhXbk0gSsKdIiA==} + engines: {node: '>=22.18.0'} + + cspell-dictionary@9.8.0: + resolution: {integrity: sha512-QW4hdkWcrxZA1QNqi26U0S/U3/V+tKCm7JaaesEJW2F6Ao+23AbHVwidyAVtXaEhGkn6PxB+epKrrAa6nE69qA==} engines: {node: '>=20'} - cspell-gitignore@9.3.2: - resolution: {integrity: sha512-G2bLR+Dfb9GX4Sdm75GfCCa9V/sQYkRbLckuCuVmJxvcDB0xfczAtb6TfAXIziF3oUI6cOB1g+PoNLWBelcK5w==} + cspell-gitignore@9.8.0: + resolution: {integrity: sha512-SDUa1DmSfT20+JH7XtyzcEL9KfurneoR/XbmlrtPQZP/LUHXh3yz4x/0vFIkEFXNWdSckY0QdWTz8DaxClCf4Q==} engines: {node: '>=20'} hasBin: true - cspell-glob@9.3.2: - resolution: {integrity: sha512-TuSupENEKyOCupOUZ3vnPxaTOghxY/rD1JIkb8e5kjzRprYVilO/rYqEk/52iLwJVd+4Npe8fNhR3KhU7u/UUg==} - engines: {node: '>=20'} + cspell-glob@10.3.3: + resolution: {integrity: sha512-oxqYJHjlZ+OzA5YDF2NCWvKNGJmuuvyqv+QZ7BYPOx3bkuouAK2q4GNme0lVHL6Vbj0tPgBY67eAMESz45r3yw==} + engines: {node: '>=22.18.0'} - cspell-grammar@9.3.2: - resolution: {integrity: sha512-ysonrFu9vJvF/derDlEjUfmvLeCfNOWPh00t6Yh093AKrJFoWQiyaS/5bEN/uB5/n1sa4k3ItnWvuTp3+YuZsA==} + cspell-glob@9.8.0: + resolution: {integrity: sha512-Uvj/iHXs+jpsJyIEnhEoJTWXb1GVyZ9T05L5JFtZfsQNXrh8SRDQPscjxbg4okKr63N7WevfioQum/snHNYvmw==} engines: {node: '>=20'} + + cspell-grammar@10.3.3: + resolution: {integrity: sha512-cCGp22tH7Q8I6xmoxvI654FQrIXKz+AZ1XOuPgBbjFCsu6Fl8y27HM+9I9GbzrsGykyT+7cSpdhGID6Ay7Rn+w==} + engines: {node: '>=22.18.0'} hasBin: true - cspell-io@9.3.2: - resolution: {integrity: sha512-ahoULCp0j12TyXXmIcdO/7x65A/2mzUQO1IkOC65OXEbNT+evt0yswSO5Nr1F6kCHDuEKc46EZWwsYAzj78pMg==} + cspell-grammar@9.8.0: + resolution: {integrity: sha512-01XMq2vhPS0Gvxnfed9uvOwH+3cXddHYxW0PwCE+SZdcC6TN8yM6glByuLt1qFustAmQVE5GSr7uAY9o4pZQRg==} engines: {node: '>=20'} + hasBin: true + + cspell-io@10.3.3: + resolution: {integrity: sha512-ifhTJgf8ISAvyB8i5NMTVXkRP4JvsoB6XOWtXPg8wqpBiGWHk2o/eGgNn8iap9dLWHU7GRxkE4R9Qdw5nXfuTg==} + engines: {node: '>=22.18.0'} - cspell-lib@9.3.2: - resolution: {integrity: sha512-kdk11kib68zNANNICuOA8h4oA9kENQUAdeX/uvT4+7eHbHHV8WSgjXm4k4o/pRIbg164UJTX/XxKb/65ftn5jw==} + cspell-io@9.8.0: + resolution: {integrity: sha512-JINaEWQEzR4f2upwdZOFcft+nBvQgizJfrOLszxG3p+BIzljnGklqE/nUtLFZpBu0oMJvuM/Fd+GsWor0yP7Xw==} engines: {node: '>=20'} - cspell-trie-lib@9.3.2: - resolution: {integrity: sha512-1Af7Mq9jIccFQyJl/ZCcqQbtJwuDqpQVkk8xfs/92x4OI6gW1iTVRMtsrh0RTw1HZoR8aQD7tRRCiLPf/D+UiQ==} + cspell-lib@10.3.3: + resolution: {integrity: sha512-KyJpUJu66COyz3ZW1hbJsTfJYJheoc/EEiMbKFSxJUIbbbX8byN2dVF3eq2t+t2Q5dORrQ2OnnfYwpw2WbKZzw==} + engines: {node: '>=22.18.0'} + + cspell-lib@9.8.0: + resolution: {integrity: sha512-G2TtPcye5QE5ev3YgWq42UOJLpTZ6naO/47oIm+jmeSYbgnbcOSThnEE7uMycx+TTNOz/vJVFpZmQyt0bWCftw==} engines: {node: '>=20'} - cspell@9.3.2: - resolution: {integrity: sha512-3xFyVSTYrYa/QJzLfzsCRMkMXqOsytP8E26DuGrVMJQoLPFmbOXNNtnMu4wrtr17QVloxpvutW77U4vb2L/LDQ==} + cspell-trie-lib@10.3.3: + resolution: {integrity: sha512-NgdfYr4UvoAdG+ZYwi/WnXiGwOCU5azD7FciV03+dstkXA1ZxNWC7UjMjt4NtZvK/HfCSSLlUnMzLmCGX2TO9g==} + engines: {node: '>=22.18.0'} + peerDependencies: + '@cspell/cspell-types': 10.3.3 + + cspell-trie-lib@9.8.0: + resolution: {integrity: sha512-GXIyqxya8QLp6SjKsAN9w3apvt1Ww7GKcZvTBaP76OfLoyb1QC6unwmObY2cZs1manCntGwHrgU6vFNuXnTzpw==} engines: {node: '>=20'} + peerDependencies: + '@cspell/cspell-types': 9.8.0 + + cspell@9.8.0: + resolution: {integrity: sha512-qL0VErMSn8BDxaPxcV+9uenffgjPS+5Jfz+m4rCsvYjzLwr7AaaJBWWSV2UiAe/4cturae8n8qzxiGnbbazkRw==} + engines: {node: '>=20.18'} hasBin: true cssesc@3.0.0: @@ -2025,21 +1943,6 @@ packages: engines: {node: '>=4'} hasBin: true - 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'} - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -2049,24 +1952,12 @@ packages: supports-color: optional: true - decode-named-character-reference@1.2.0: - resolution: {integrity: sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==} + decode-named-character-reference@1.3.0: + resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - 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'} - deprecation@2.3.1: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} @@ -2081,15 +1972,11 @@ packages: resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - dunder-proto@1.0.1: - resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} - engines: {node: '>= 0.4'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.260: - resolution: {integrity: sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==} + electron-to-chromium@1.5.433: + resolution: {integrity: sha512-5lCAbyZBjtmUt/RAGHRqrL2q0oEFRThDAsZHHDn9XHa89Qw7gMYOeSicBTy+AHfvo0r6vwsZvqNJTQIQy1BLzA==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -2097,56 +1984,32 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enhanced-resolve@5.18.3: - resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} + enhanced-resolve@5.25.1: + resolution: {integrity: sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==} engines: {node: '>=10.13.0'} entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - env-paths@3.0.0: - resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + env-paths@4.0.0: + resolution: {integrity: sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==} + engines: {node: '>=20'} error-ex@1.3.4: resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} - es-abstract@1.24.0: - resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} - 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.1: - resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} - 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'} - - esbuild@0.25.12: - resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} engines: {node: '>=18'} hasBin: true - esbuild@0.27.0: - resolution: {integrity: sha512-jd0f4NHbD6cALCyGElNpGAOtWxSq46l9X/sWB0Nzd5er4Kz2YTm+Vl0qKFT9KUJvD8+fiO8AvoHhFvEatfVixA==} + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} engines: {node: '>=18'} hasBin: true @@ -2198,13 +2061,13 @@ packages: unrs-resolver: optional: true - eslint-json-compat-utils@0.2.1: - resolution: {integrity: sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg==} + eslint-json-compat-utils@0.2.3: + resolution: {integrity: sha512-RbBmDFyu7FqnjE8F0ZxPNzx5UaptdeS9Uu50r7A+D7s/+FCX+ybiyViYEgFUaFIFqSWJgZRTpL5d8Kanxxl2lQ==} engines: {node: '>=12'} peerDependencies: '@eslint/json': '*' eslint: '*' - jsonc-eslint-parser: ^2.4.0 + jsonc-eslint-parser: ^2.4.0 || ^3.0.0 peerDependenciesMeta: '@eslint/json': optional: true @@ -2230,12 +2093,12 @@ packages: peerDependencies: eslint: '>=8' - eslint-plugin-import-x@4.16.1: - resolution: {integrity: sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ==} + eslint-plugin-import-x@4.17.1: + resolution: {integrity: sha512-4cdstYkKCyjumM2Q9NSI03K8D2a9F4Ssz33K2lv2hQa4KmR9jPLwk3uWGtNvclfqBrPGfGuMBwsGMbe6dMRbfg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/utils': ^8.0.0 - eslint: ^8.57.0 || ^9.0.0 + '@typescript-eslint/utils': ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 eslint-import-resolver-node: '*' peerDependenciesMeta: '@typescript-eslint/utils': @@ -2249,20 +2112,20 @@ packages: peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - eslint-plugin-jsonc@2.21.0: - resolution: {integrity: sha512-HttlxdNG5ly3YjP1cFMP62R4qKLxJURfBZo2gnMY+yQojZxkLyOpY1H1KRTKBmvQeSG9pIpSGEhDjE17vvYosg==} + eslint-plugin-jsonc@2.21.1: + resolution: {integrity: sha512-dbNR5iEnQeORwsK2WZzr3QaMtFCY3kKJVMRHPzUpKzMhmVy2zIpVgFDpX8MNoIdoqz6KCpCfOJavhfiSbZbN+w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' - eslint-plugin-n@17.23.1: - resolution: {integrity: sha512-68PealUpYoHOBh332JLLD9Sj7OQUDkFpmcfqt8R9sySfFSeuGJjMTJQvCRRB96zO3A/PELRLkPrzsHmzEFQQ5A==} + eslint-plugin-n@17.24.0: + resolution: {integrity: sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: '>=8.23.0' - eslint-plugin-no-only-tests@3.3.0: - resolution: {integrity: sha512-brcKcxGnISN2CcVhXJ/kEQlNa0MEfGRtwKtWA16SkqXHKitaKIMrfemJKLKX1YqDU5C/5JY3PvZXd5jEW04e0Q==} + eslint-plugin-no-only-tests@3.4.0: + resolution: {integrity: sha512-4S3/9Nb7A2tiMcpzEQE9bQSlpeOz6WJkgryBuou/SA8W2x2c8Zf4j0NvTKBjv6qNhF9T79tmkecm/0CHqV0UGg==} engines: {node: '>=5.0.0'} eslint-plugin-perfectionist@4.15.1: @@ -2271,25 +2134,25 @@ packages: peerDependencies: eslint: '>=8.45.0' - eslint-plugin-react-dom@2.3.9: - resolution: {integrity: sha512-xflcmWONib2KN54bJ25AvrYSPrp0qDWwWoG+tZJWD7xe0OcvC42zpERKyMuqTMuXfKPJNUOs2ZB1z6e3HNRviw==} + eslint-plugin-react-dom@2.13.0: + resolution: {integrity: sha512-+2IZzQ1WEFYOWatW+xvNUqmZn55YBCufzKA7hX3XQ/8eu85Mp4vnlOyNvdVHEOGhUnGuC6+9+zLK+IlEHKdKLQ==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - eslint-plugin-react-hooks-extra@2.3.9: - resolution: {integrity: sha512-ImANssr1gfBNMahqCufe2nhb1CZpqMBjKYgwtYF6u0pV11UXnGj181MW+YBEPEB+qIN4NK3hKxSsQngQJPBfQQ==} - engines: {node: '>=20.0.0'} + eslint-plugin-react-hooks-extra@2.13.0: + resolution: {integrity: sha512-qIbha1nzuyhXM9SbEfrcGVqmyvQu7GAOB2sy9Y4Qo5S8nCqw4fSBxq+8lSce5Tk5Y7XzIkgHOhNyXEvUHRWFMQ==} + engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - eslint-plugin-react-naming-convention@2.3.9: - resolution: {integrity: sha512-3cxHcn6oA29awTQr20LCw9XBhms65giuHHclU3KyLtFVoHSX/LUJtXUpv/KezkhRiaavT8PmxGTGMZiGGY9vHw==} + eslint-plugin-react-naming-convention@2.13.0: + resolution: {integrity: sha512-uSd25JzSg2R4p81s3Wqck0AdwRlO9Yc+cZqTEXv7vW8exGGAM3mWnF6hgrgdqVJqBEGJIbS/Vx1r5BdKcY/MHA==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' eslint-plugin-react-refresh@0.4.24: @@ -2297,18 +2160,25 @@ packages: peerDependencies: eslint: '>=8.40' - eslint-plugin-react-web-api@2.3.9: - resolution: {integrity: sha512-AlSBt0ITf1nT1I6U4Kyj9GoFEpfLh8sR62sl+6uYSladmhPAKXMOSB7Ban7VX6jZcA7LHp+acKAJCv18fKxaUg==} + eslint-plugin-react-rsc@2.13.0: + resolution: {integrity: sha512-RaftgITDLQm1zIgYyvR51sBdy4FlVaXFts5VISBaKbSUB0oqXyzOPxMHasfr9BCSjPLKus9zYe+G/Hr6rjFLXQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.0.0' + + eslint-plugin-react-web-api@2.13.0: + resolution: {integrity: sha512-nmJbzIAte7PeAkp22CwcKEASkKi49MshSdiDGO1XuN3f4N4/8sBfDcWbQuLPde6JiuzDT/0+l7Gi8wwTHtR1kg==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' - eslint-plugin-react-x@2.3.9: - resolution: {integrity: sha512-G0Aqk7oHMVmMNnulpQ2nb/Iq2o9JNkk3WQT70zBVQJYIz6NUrXp/1ujL2+cXb5A8ZapEN53F0pP9ZoQRIzNhsA==} + eslint-plugin-react-x@2.13.0: + resolution: {integrity: sha512-cMNX0+ws/fWTgVxn52qAQbaFF2rqvaDAtjrPUzY6XOzPjY0rJQdR2tSlWJttz43r2yBfqu+LGvHlGpWL2wfpTQ==} engines: {node: '>=20.19.0'} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.0.0' eslint-plugin-regexp@2.10.0: @@ -2329,11 +2199,11 @@ packages: peerDependencies: eslint: '>=8.56.0' - eslint-plugin-unused-imports@4.3.0: - resolution: {integrity: sha512-ZFBmXMGBYfHttdRtOG9nFFpmUvMtbHSjsKrS20vdWdbfiVYsO3yA2SGYy9i9XmZJDfMGBflZGBCm70SEnFQtOA==} + eslint-plugin-unused-imports@4.4.1: + resolution: {integrity: sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ==} peerDependencies: '@typescript-eslint/eslint-plugin': ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0 - eslint: ^9.0.0 || ^8.0.0 + eslint: ^10.0.0 || ^9.0.0 || ^8.0.0 peerDependenciesMeta: '@typescript-eslint/eslint-plugin': optional: true @@ -2344,8 +2214,8 @@ packages: peerDependencies: eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 - eslint-plugin-yml@1.19.0: - resolution: {integrity: sha512-S+4GbcCWksFKAvFJtf0vpdiCkZZvDJCV4Zsi9ahmYkYOYcf+LRqqzvzkb/ST7vTYV6sFwXOvawzYyL/jFT2nQA==} + eslint-plugin-yml@1.19.1: + resolution: {integrity: sha512-bYkOxyEiXh9WxUhVYPELdSHxGG5pOjCSeJOVkfdIyj6tuiHDxrES2WAW1dBxn3iaZQey57XflwLtCYRcNPOiOg==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' @@ -2372,8 +2242,12 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.39.1: - resolution: {integrity: sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==} + eslint-visitor-keys@5.0.1: + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + + eslint@9.39.5: + resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true @@ -2400,8 +2274,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -2412,9 +2286,6 @@ packages: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - 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==} @@ -2433,45 +2304,35 @@ packages: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} - exsolve@1.0.8: - resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} + exsolve@1.1.1: + resolution: {integrity: sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==} fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-equals@5.3.3: - resolution: {integrity: sha512-/boTcHZeIAQ2r/tL11voclBHDeP9WPxLt+tyAbVSyyXuUFyh0Tne7gJZTqGbxnvj79TjLdCXLOY7UIPhyG5MTw==} + fast-equals@6.0.4: + resolution: {integrity: sha512-JiBeR0k76FIahi9zAtQR7X1jgZDKLE+fs5S9ryjOGYZWZCOcm8QiwgeahkFvaboS3i6PkGBopRznHKuKhm9zpg==} engines: {node: '>=6.0.0'} fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fast-memoize@2.5.2: - resolution: {integrity: sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw==} + fast-uri@3.1.8: + resolution: {integrity: sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==} - fast-uri@3.1.0: - resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-xml-builder@1.3.1: + resolution: {integrity: sha512-pIM/1n3ntFXKYrUZwW7QCK0gAW7XY+wzj1YMIV3tLDvPj/V+zTGJK5e3/4WJfwj0qWw2ElNXiTixda/R+3YSug==} - fast-xml-builder@1.3.0: - resolution: {integrity: sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ==} - - fast-xml-parser@5.10.1: - resolution: {integrity: sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw==} + fast-xml-parser@5.11.1: + resolution: {integrity: sha512-TBw6K/fxoQGGjCmZDw9w/ZwP3uDcnTM4YH/g+PFRWr8sbe5idXtxNN6vITh4+1ruCZaho6uBFurElsA7F0zzgw==} hasBin: true - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - fault@2.0.1: resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==} @@ -2488,10 +2349,6 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - find-up@4.1.0: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} @@ -2507,12 +2364,8 @@ packages: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} + flatted@3.4.4: + resolution: {integrity: sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==} foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} @@ -2522,13 +2375,6 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} - 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} @@ -2537,17 +2383,6 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - function.prototype.name@1.1.8: - resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} - 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'} - gensequence@8.0.8: resolution: {integrity: sha512-omMVniXEXpdx/vKxGnPRoO2394Otlze28TyxECbFVyoSpZ9H3EO7lemjcB12OpQJzRW4e5tt/dL1rOxry6aMHg==} engines: {node: '>=20'} @@ -2556,31 +2391,12 @@ packages: 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'} - - get-tsconfig@4.13.0: - resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==} + get-tsconfig@4.14.3: + resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==} github-slugger@2.0.0: resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} @@ -2590,13 +2406,9 @@ packages: deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - - global-directory@4.0.1: - resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} - engines: {node: '>=18'} + global-directory@5.0.0: + resolution: {integrity: sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w==} + engines: {node: '>=20'} globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} @@ -2610,17 +2422,9 @@ packages: resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} engines: {node: '>=18'} - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} - 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==} @@ -2631,40 +2435,17 @@ packages: resolution: {integrity: sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - 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.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} hosted-git-info@2.8.9: resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - hpagent@1.2.0: - resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} - engines: {node: '>=14'} - http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -2685,17 +2466,18 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - ignore@7.0.5: - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + ignore@7.0.9: + resolution: {integrity: sha512-brTTsvFRt5C1gGHtPst/281UjPD5t9fBqbgoMPlVWy11ZLTPfu7HxK4ZYqO9H7o/yC9rSTCI85EaQ4OoY12qYw==} engines: {node: '>= 4'} - immer@9.0.21: - resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} - import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-fresh@4.0.0: + resolution: {integrity: sha512-Fpi660c7VPDM3fPKYovStd9IP1CPOikf6v/dGxJJMmHPcwYQIMJ4W7kO1avBYEpMqkCh+Dx3Ln6H7VYqgztLjw==} + engines: {node: '>=22.15'} + import-meta-resolve@4.2.0: resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} @@ -2707,154 +2489,56 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - 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==} - ini@4.1.1: - resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - 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'} + ini@6.0.0: + resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} + engines: {node: ^20.17.0 || >=22.9.0} is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - 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-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} - is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - 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==} + is-core-module@2.17.0: + resolution: {integrity: sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==} 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-immutable-type@5.0.1: - resolution: {integrity: sha512-LkHEOGVZZXxGl8vDs+10k3DvP++SEoYEAJLRk6buTFi6kD7QekThV7xHS0j6gpnUCQ0zpud/gMDGiV4dQneLTg==} + is-immutable-type@5.0.4: + resolution: {integrity: sha512-tDf0vB9dJJt/1USS2nvHJb8UsIAhs+pF6z8UZLNdhrzB+PKMrdcN45je9jhuFpaJOjJpoRhueFmFrRs5g/TNMA==} peerDependencies: eslint: '*' typescript: '>=4.7.4' - 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-safe-filename@0.1.1: + resolution: {integrity: sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==} + engines: {node: '>=20'} is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - 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-unsafe@2.0.0: - resolution: {integrity: sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA==} - - 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'} + is-unsafe@2.0.2: + resolution: {integrity: sha512-HgbIHPBH0KHHCcjLfGsCvhtPTVxjaAZlXjwdz7/GQC40SjSe4sfQsar8J5VFo8JOSbarkpV0OLG95bbaNd9aAQ==} isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -2872,12 +2556,12 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + js-yaml@4.3.2: + resolution: {integrity: sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==} hasBin: true - js-yaml@5.4.1: - resolution: {integrity: sha512-28R/k+NAjeuf7+CKlTxWZVExJGwVVLwY06DgEnOMz2gEpfNkDcD7QvyiVPT0xy0XXhU8vHsd4Ot42OOPdJG7dQ==} + js-yaml@5.4.2: + resolution: {integrity: sha512-m+aqu+LwO1O6sIopafj8HUVl5aawITwZQe/yHpMCKjaWBaA/d07B/QdMb3529REftiU+RMMHL3Vlsw3hON7vWg==} hasBin: true jsdoc-type-pratt-parser@4.1.0: @@ -2888,10 +2572,6 @@ packages: resolution: {integrity: sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==} engines: {node: '>=12.0.0'} - jsep@1.4.0: - resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} - engines: {node: '>= 10.16.0'} - jsesc@0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true @@ -2920,25 +2600,10 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - jsonc-eslint-parser@2.4.1: - resolution: {integrity: sha512-uuPNLJkKN8NXAlZlQ6kmUF9qO+T6Kyd7oV4+/7yy8Jz6+MZNyhPq8EdLpdfnPVzUC8qSf1b4j1azKaGnFsjmsw==} + jsonc-eslint-parser@2.4.2: + resolution: {integrity: sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - jsonc-parser@2.2.1: - resolution: {integrity: sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==} - - jsonfile@6.2.0: - resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - - jsonpath-plus@10.3.0: - resolution: {integrity: sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==} - engines: {node: '>=18.0.0'} - hasBin: true - - jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} - jssha@3.3.2: resolution: {integrity: sha512-0RhFxzijV4W0qTXa97D5b6twAWXX7SEOpw8qzAZyZ+oeGOP9e84PnDSLjl7SBB1vBQ+chSUwsZR06i1AzA+nEA==} @@ -2952,10 +2617,6 @@ packages: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -2975,8 +2636,8 @@ packages: resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} engines: {node: '>=14'} - local-pkg@1.1.2: - resolution: {integrity: sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==} + local-pkg@1.2.1: + resolution: {integrity: sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==} engines: {node: '>=14'} locate-path@5.0.0: @@ -2990,11 +2651,8 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.topath@4.5.2: - resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==} - - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} @@ -3002,27 +2660,17 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - magic-string@0.25.9: - resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} - magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - markdown-escape@2.0.0: - resolution: {integrity: sha512-Trz4v0+XWlwy68LJIyw3bLbsJiC8XAbRCKF9DbEtZjyndKOGVx6n+wNB0VfoRmY2LKboQLeniap3xrb6LGSJ8A==} - markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - math-intrinsics@1.1.0: - resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} - engines: {node: '>= 0.4'} - mdast-util-find-and-replace@3.0.2: resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} - mdast-util-from-markdown@2.0.2: - resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + mdast-util-from-markdown@2.0.3: + resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} mdast-util-frontmatter@2.0.1: resolution: {integrity: sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==} @@ -3054,10 +2702,6 @@ packages: mdast-util-to-string@4.0.0: resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - micromark-core-commonmark@2.0.3: resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} @@ -3073,8 +2717,8 @@ packages: micromark-extension-gfm-strikethrough@2.1.0: resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - micromark-extension-gfm-table@2.1.1: - resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} + micromark-extension-gfm-table@2.1.2: + resolution: {integrity: sha512-pRzm4kDTu0MjlmBkxmS9yYhw60nncfcEwu9NNdPFSQEFXS95ZKyIIyTSHu/o3ReBUrLKYEq+7YaXCRn/bPB4MA==} micromark-extension-gfm-tagfilter@2.0.0: resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} @@ -3145,42 +2789,38 @@ packages: micromark@4.0.2: resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} - minimatch@10.1.1: - resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} - engines: {node: 20 || >=22} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} engines: {node: '>=10'} - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} engines: {node: '>=16 || 14 >=14.17'} minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true - mlly@1.8.0: - resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + mlly@1.8.2: + resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3205,25 +2845,9 @@ packages: resolution: {integrity: sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==} engines: {node: '>=18'} - 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-releases@2.0.27: - resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} - - node-sarif-builder@2.0.3: - resolution: {integrity: sha512-Pzr3rol8fvhG/oJjIq2NTVB0vmdNNlz22FENhhPojYRZ4/ee08CfK4YuKmuL54V9MLhI1kpzxfOJ/63LzmZzDg==} - engines: {node: '>=14'} + node-releases@2.0.56: + resolution: {integrity: sha512-x0InOIyzgdk+eyaWaRJFH5snEtiImgBgblZ2CyPrLmqqcuMQkEvcDPHbzqbD8eDsSeJbVOjn+crzyzHaM4D+/A==} + engines: {node: '>=18'} normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -3239,18 +2863,6 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - 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==} @@ -3258,10 +2870,6 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} - own-keys@1.0.1: - resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} - engines: {node: '>= 0.4'} - p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -3285,8 +2893,8 @@ packages: package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - package-manager-detector@1.5.0: - resolution: {integrity: sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==} + package-manager-detector@1.8.0: + resolution: {integrity: sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==} parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -3318,10 +2926,6 @@ packages: resolution: {integrity: sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ==} engines: {node: '>=14.0.0'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3342,14 +2946,6 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - picomatch@4.0.3: - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} - engines: {node: '>=12'} - picomatch@4.0.7: resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} engines: {node: '>=12'} @@ -3361,21 +2957,13 @@ packages: pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - pkg-types@2.3.0: - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + pkg-types@2.3.3: + resolution: {integrity: sha512-j/lCFdcppV0JxWpCEITdbDltBxPP6cHT+yNJ6Go2OgoSA9518X847X9z0p6LtA4Nc16+eQzCZjRrWanTGvHJ5w==} pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - 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'} - postcss-load-config@6.0.1: resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} engines: {node: '>= 18'} @@ -3394,8 +2982,8 @@ packages: yaml: optional: true - postcss-selector-parser@6.1.2: - resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + postcss-selector-parser@6.1.4: + resolution: {integrity: sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==} engines: {node: '>=4'} postcss@8.5.6: @@ -3406,9 +2994,6 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - printable-characters@1.0.42: - resolution: {integrity: sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==} - process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -3423,9 +3008,6 @@ packages: quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - read-pkg-up@7.0.1: resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} engines: {node: '>=8'} @@ -3452,10 +3034,6 @@ packages: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - regexp-ast-analysis@0.7.1: resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -3464,10 +3042,6 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - regjsparser@0.10.0: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true @@ -3480,10 +3054,6 @@ packages: 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-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -3495,49 +3065,22 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve@1.22.11: - resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + 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.79.2: - resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} - engines: {node: '>=10.0.0'} - hasBin: true - - rollup@4.53.3: - resolution: {integrity: sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==} + rollup@4.63.4: + resolution: {integrity: sha512-4U0liVayNIoLp3GFl1FcI8561WepLnZ1rqfraGh7S9B3Ur5F9S283y8Futii7RUU2C/97tOBmBy7nYvhoiOpbQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - 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==} - scslre@0.3.0: resolution: {integrity: sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ==} engines: {node: ^14.0.0 || >=16.0.0} @@ -3546,23 +3089,11 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true - semver@7.7.3: - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} engines: {node: '>=10'} hasBin: true - 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'} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -3571,53 +3102,25 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - 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.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-eval@1.0.1: - resolution: {integrity: sha512-LH7FpTAkeD+y5xQC4fzS+tFtaNlvt3Ib1zKzvhjv/Y+cioV4zIuw4IZr2yhRLu67CWL7FR9/6KXKnjRoZTvGGQ==} - engines: {node: '>=12'} - sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - smol-toml@1.5.2: - resolution: {integrity: sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==} + smol-toml@1.8.0: + resolution: {integrity: sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==} engines: {node: '>= 18'} source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - source-map@0.7.6: resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} engines: {node: '>= 12'} - sourcemap-codec@1.4.8: - resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} - deprecated: Please use @jridgewell/sourcemap-codec instead - spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -3630,8 +3133,8 @@ packages: spdx-expression-parse@4.0.0: resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} - spdx-license-ids@3.0.22: - resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + spdx-license-ids@3.0.24: + resolution: {integrity: sha512-cLS9TtWkIQFyLkJ3/5aFQAOHOSKTlOs/7WDut/XPSdjom1fJhUdkepeJAKXa9Y05+FabHd0sti+Et559vDtkpQ==} srvx@0.12.5: resolution: {integrity: sha512-IuvtDNQg5EIwv3c6dleyau7u8hCyGQ7D6+V/QM799Aud07z0wCUcurKLTRfyG33C8oUY+UWcVBFkfHMcbtmRLA==} @@ -3642,18 +3145,11 @@ packages: resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==} engines: {node: '>=12.0.0'} - stacktracey@2.1.8: - resolution: {integrity: sha512-Kpij9riA+UNg7TnphqjH7/CzctQ/owJGNbFkfEeve4Z4uxT5+JapVLFXcsurIfN34gnTWZNJ/f7NMG0E8JDzTw==} - - stop-iteration-iterator@1.1.0: - resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} - engines: {node: '>= 0.4'} - - streamx@2.28.0: - resolution: {integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==} + streamx@2.28.1: + resolution: {integrity: sha512-zEzXb0s5Cds7tqMH6rhZ05lcJydCWiQPEwiNngVqzsxCc962vLY4Uw+mW7od8kDH258k2Uz/JrOkdIAAhSh9VA==} - string-ts@2.2.1: - resolution: {integrity: sha512-Q2u0gko67PLLhbte5HmPfdOjNvUKbKQM+mCNQae6jE91DmoFHY6HH9GcdqCeNx87DZ2KKjiFxmA0R/42OneGWw==} + string-ts@2.3.1: + resolution: {integrity: sha512-xSJq+BS52SaFFAVxuStmx6n5aYZU571uYUnUrPXkPFCfdHyZMMlbP2v2Wx5sNBnAVzq/2+0+mcBLBa3Xa5ubYw==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -3663,18 +3159,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string.prototype.trim@1.2.10: - resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} - engines: {node: '>= 0.4'} - - string.prototype.trimend@1.0.9: - resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} - engines: {node: '>= 0.4'} - - string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -3685,8 +3169,8 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} strip-indent@3.0.0: @@ -3697,8 +3181,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strnum@2.4.1: - resolution: {integrity: sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg==} + strnum@2.4.2: + resolution: {integrity: sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==} sucrase@3.35.1: resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==} @@ -3713,16 +3197,16 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - synckit@0.11.11: - resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + synckit@0.11.13: + resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} - tapable@2.3.0: - resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} engines: {node: '>=6'} - tar-stream@3.2.0: - resolution: {integrity: sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg==} + tar-stream@3.2.1: + resolution: {integrity: sha512-nqsEO8zLZJvrOMdEwkA0QdCLFbetHMn95Zqu4fKwX+hkaTWJPZZOrxx/PwtxoK0MMGQmBQNRW3CPs8IFYQz4cQ==} teex@1.0.1: resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} @@ -3730,9 +3214,6 @@ packages: text-decoder@1.2.7: resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} - text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -3743,32 +3224,21 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - tinyexec@1.0.2: - resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} - engines: {node: '>=18'} - - tinyexec@1.3.0: - resolution: {integrity: sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==} + tinyexec@1.3.1: + resolution: {integrity: sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==} engines: {node: '>=18'} - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - - toml-eslint-parser@0.10.0: - resolution: {integrity: sha512-khrZo4buq4qVmsGzS5yQjKe/WsFvV8fGfOjDQN0q4iy9FjRfPWRgTFrU8u1R2iu/SfWLhY9WnCi4Jhdrcbtg+g==} + toml-eslint-parser@0.10.1: + resolution: {integrity: sha512-9mjy3frhioGIVGcwamlVlUyJ9x+WHw/TXiz9R4YOlmsIuBN43r9Dp8HZ35SF9EKjHrn3BUZj04CF+YqZ2oJ+7w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} totp-generator@2.0.1: resolution: {integrity: sha512-50DiKmv9zKTPzCgWOqQYVBMvxh+tpL9O3IUFIqzGUlFXzJyb/IQZac8bonXudvLbfuDY8laZ9qTDX+yAvTBNSQ==} - tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - traverse@0.3.9: resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} @@ -3779,8 +3249,8 @@ packages: ts-algebra@1.2.2: resolution: {integrity: sha512-kloPhf1hq3JbCPOTYoOWDKxebWjNb2o/LKnNfkWhxVVisFFmMJPPdJeGoGmM+iRLyoXAR61e08Pb+vUXINg8aA==} - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + ts-api-utils@2.5.0: + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -3796,9 +3266,6 @@ packages: ts-pattern@5.9.0: resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==} - tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -3821,8 +3288,8 @@ packages: typescript: optional: true - tsx@4.20.6: - resolution: {integrity: sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg==} + tsx@4.23.15: + resolution: {integrity: sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==} engines: {node: '>=18.0.0'} hasBin: true @@ -3846,22 +3313,6 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} - 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.7: - resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} - engines: {node: '>= 0.4'} - typescript@3.9.10: resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==} engines: {node: '>=4.2.0'} @@ -3877,22 +3328,18 @@ packages: engines: {node: '>=14.17'} hasBin: true - ufo@1.6.1: - resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + ufo@1.6.4: + resolution: {integrity: sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==} - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - - undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} undici@5.29.0: resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} - undici@6.28.0: - resolution: {integrity: sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==} + undici@6.28.1: + resolution: {integrity: sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA==} engines: {node: '>=18.17'} unist-util-is@6.0.1: @@ -3904,24 +3351,20 @@ packages: unist-util-visit-parents@6.0.2: resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} - unist-util-visit@5.0.0: - resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + unist-util-visit@5.1.0: + resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} universal-user-agent@6.0.1: resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - - unrs-resolver@1.11.1: - resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} + unrs-resolver@1.12.2: + resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==} unzip-stream@0.3.4: resolution: {integrity: sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw==} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + update-browserslist-db@1.3.3: + resolution: {integrity: sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' @@ -3929,27 +3372,17 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - urijs@1.19.11: - resolution: {integrity: sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==} - util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - utility-types@3.11.0: - resolution: {integrity: sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==} - engines: {node: '>= 4'} - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validate-npm-package-name@3.0.0: - resolution: {integrity: sha512-M6w37eVCMMouJ9V/sdPGnC5H4uDr73/+xdq0FBLO3TFFX1+7wiUY6Es328NN+y43tmY+doUdN9g9J21vqB7iLw==} + vscode-languageserver-textdocument@1.0.14: + resolution: {integrity: sha512-EQyqJMi552E4ZTf46izQ4Fj6XquqxCySR3J5ZSD1SisMf6RfpeOWHxGBE8Gr6V0/3GHIGdAzDn8F8+1nTGCnoQ==} - vscode-languageserver-textdocument@1.0.12: - resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} - - vscode-uri@3.1.0: - resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + vscode-uri@3.2.0: + resolution: {integrity: sha512-m2gXo3bn0G1kT9InzMf07fTbqMbGtyckj3bH5ktLO+1Ssv+yiATZ4dhwaQv9UZWxJh6E9IFGnQyjgWVDWVBDrg==} vue-eslint-parser@9.4.3: resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} @@ -3957,28 +3390,6 @@ packages: peerDependencies: eslint: '>=6.0.0' - 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.19: - resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} - engines: {node: '>= 0.4'} - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -4018,12 +3429,12 @@ packages: yaml-ast-parser@0.0.43: resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==} - yaml-eslint-parser@1.3.1: - resolution: {integrity: sha512-MdSgP9YA9QjtAO2+lt4O7V2bnH22LPnfeVLiQqjY3cOyn8dy/Ief8otjIe6SPPTK03nM7O3Yl0LTfWuF7l+9yw==} + yaml-eslint-parser@1.3.2: + resolution: {integrity: sha512-odxVsHAkZYYglR30aPYRY4nUGJnoJ2y1ww2HDvZALo0BDETv9kWbi16J52eHs+PWRNmF4ub6nZqfVOeesOvntg==} engines: {node: ^14.17.0 || >=16.0.0} - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + yaml@2.9.1: + resolution: {integrity: sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==} engines: {node: '>= 14.6'} hasBin: true @@ -4031,8 +3442,8 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + yargs@17.7.3: + resolution: {integrity: sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==} engines: {node: '>=12'} yocto-queue@0.1.0: @@ -4043,8 +3454,8 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} - zod@4.1.13: - resolution: {integrity: sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==} + zod@4.6.5: + resolution: {integrity: sha512-v5l/aFXZQeai4awLbOpSoHecE9UiMrnfx75tEXLjNonXVARxQ5mOeipTjROUchszUNCqnE+hqAMujRsRHsut2Q==} zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -4108,53 +3519,53 @@ snapshots: '@actions/http-client@3.0.2': dependencies: tunnel: 0.0.6 - undici: 6.28.0 + undici: 6.28.1 '@actions/io@1.1.3': {} '@actions/io@2.0.0': {} - '@antfu/eslint-config@3.16.0(@eslint-react/eslint-plugin@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(supports-color@7.2.0)))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@antfu/eslint-config@3.16.0(@eslint-react/eslint-plugin@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.5(supports-color@7.2.0)))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 0.9.1 - '@eslint-community/eslint-plugin-eslint-comments': 4.5.0(eslint@9.39.1(supports-color@7.2.0)) + '@eslint-community/eslint-plugin-eslint-comments': 4.8.1(eslint@9.39.5(supports-color@7.2.0)) '@eslint/markdown': 6.6.0(supports-color@7.2.0) - '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@vitest/eslint-plugin': 1.5.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - eslint-config-flat-gitignore: 1.0.1(eslint@9.39.1(supports-color@7.2.0)) + '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@vitest/eslint-plugin': 1.6.27(@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + eslint-config-flat-gitignore: 1.0.1(eslint@9.39.5(supports-color@7.2.0)) eslint-flat-config-utils: 1.1.0 - eslint-merge-processors: 1.0.0(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-antfu: 2.7.0(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-command: 2.1.0(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) - eslint-plugin-jsdoc: 50.8.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) - eslint-plugin-jsonc: 2.21.0(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-n: 17.23.1(eslint@9.39.1(supports-color@7.2.0))(typescript@6.0.3) - eslint-plugin-no-only-tests: 3.3.0 - eslint-plugin-perfectionist: 4.15.1(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-regexp: 2.10.0(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-toml: 0.12.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) - eslint-plugin-unicorn: 56.0.1(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-unused-imports: 4.3.0(@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0)) - eslint-plugin-vue: 9.33.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) - eslint-plugin-yml: 1.19.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) - eslint-processor-vue-blocks: 1.0.0(@vue/compiler-sfc@3.5.25)(eslint@9.39.1(supports-color@7.2.0)) + eslint-merge-processors: 1.0.0(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-antfu: 2.7.0(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-command: 2.1.0(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-import-x: 4.17.1(@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) + eslint-plugin-jsdoc: 50.8.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) + eslint-plugin-jsonc: 2.21.1(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-n: 17.24.0(eslint@9.39.5(supports-color@7.2.0))(typescript@6.0.3) + eslint-plugin-no-only-tests: 3.4.0 + eslint-plugin-perfectionist: 4.15.1(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-regexp: 2.10.0(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-toml: 0.12.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) + eslint-plugin-unicorn: 56.0.1(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-unused-imports: 4.4.1(@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0)) + eslint-plugin-vue: 9.33.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) + eslint-plugin-yml: 1.19.1(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) + eslint-processor-vue-blocks: 1.0.0(@vue/compiler-sfc@3.5.25)(eslint@9.39.5(supports-color@7.2.0)) globals: 15.15.0 - jsonc-eslint-parser: 2.4.1 - local-pkg: 1.1.2 + jsonc-eslint-parser: 2.4.2 + local-pkg: 1.2.1 parse-gitignore: 2.0.0 picocolors: 1.1.1 - toml-eslint-parser: 0.10.0 - vue-eslint-parser: 9.4.3(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) - yaml-eslint-parser: 1.3.1 - yargs: 17.7.2 + toml-eslint-parser: 0.10.1 + vue-eslint-parser: 9.4.3(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) + yaml-eslint-parser: 1.3.2 + yargs: 17.7.3 optionalDependencies: - '@eslint-react/eslint-plugin': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-react-refresh: 0.4.24(eslint@9.39.1(supports-color@7.2.0)) + '@eslint-react/eslint-plugin': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-refresh: 0.4.24(eslint@9.39.5(supports-color@7.2.0)) transitivePeerDependencies: - '@eslint/json' - '@typescript-eslint/utils' @@ -4166,24 +3577,25 @@ snapshots: '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.5.0 - tinyexec: 1.0.2 + package-manager-detector: 1.8.0 + tinyexec: 1.3.1 '@antfu/utils@0.7.10': {} - '@apidevtools/json-schema-ref-parser@15.1.2(@types/json-schema@7.0.15)': + '@apidevtools/json-schema-ref-parser@15.5.2(@types/json-schema@7.0.15)': dependencies: '@types/json-schema': 7.0.15 - js-yaml: 4.1.1 + js-yaml: 5.4.2 + undici: 6.28.1 - '@ariesclark/eslint-config@3.1.1(@eslint-react/eslint-plugin@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(supports-color@7.2.0)))(eslint@9.39.1(supports-color@7.2.0))(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.20.6)(typescript@6.0.3)(yaml@2.8.2)': + '@ariesclark/eslint-config@3.1.1(@eslint-react/eslint-plugin@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.5(supports-color@7.2.0)))(eslint@9.39.5(supports-color@7.2.0))(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.23.15)(typescript@6.0.3)(yaml@2.9.1)': dependencies: - '@antfu/eslint-config': 3.16.0(@eslint-react/eslint-plugin@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(supports-color@7.2.0)))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) + '@antfu/eslint-config': 3.16.0(@eslint-react/eslint-plugin@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(@vue/compiler-sfc@3.5.25)(eslint-plugin-react-refresh@0.4.24(eslint@9.39.5(supports-color@7.2.0)))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) eslint-flat-config-utils: 0.4.0 esno: 4.8.0 local-pkg: 0.5.1 - tsup: 8.5.1(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.20.6)(typescript@6.0.3)(yaml@2.8.2) + tsup: 8.5.1(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.23.15)(typescript@6.0.3)(yaml@2.9.1) transitivePeerDependencies: - '@eslint-react/eslint-plugin' - '@eslint/json' @@ -4212,10 +3624,6 @@ snapshots: - vitest - yaml - '@asyncapi/specs@6.10.0': - dependencies: - '@types/json-schema': 7.0.15 - '@azure/abort-controller@2.2.0': dependencies: tslib: 2.8.1 @@ -4228,7 +3636,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@azure/core-client@1.11.0(supports-color@7.2.0)': + '@azure/core-client@1.11.1(supports-color@7.2.0)': dependencies: '@azure/abort-controller': 2.2.0 '@azure/core-auth': 1.11.0(supports-color@7.2.0) @@ -4240,10 +3648,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@azure/core-http-compat@2.5.0(@azure/core-client@1.11.0(supports-color@7.2.0))(@azure/core-rest-pipeline@1.25.0(supports-color@7.2.0))': + '@azure/core-http-compat@2.5.0(@azure/core-client@1.11.1(supports-color@7.2.0))(@azure/core-rest-pipeline@1.25.0(supports-color@7.2.0))': dependencies: '@azure/abort-controller': 2.2.0 - '@azure/core-client': 1.11.0(supports-color@7.2.0) + '@azure/core-client': 1.11.1(supports-color@7.2.0) '@azure/core-rest-pipeline': 1.25.0(supports-color@7.2.0) '@azure/core-lro@2.7.2(supports-color@7.2.0)': @@ -4266,7 +3674,7 @@ snapshots: '@azure/core-tracing': 1.4.0 '@azure/core-util': 1.14.0(supports-color@7.2.0) '@azure/logger': 1.4.0(supports-color@7.2.0) - '@typespec/ts-http-runtime': 0.3.8(supports-color@7.2.0) + '@typespec/ts-http-runtime': 0.3.9(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -4278,19 +3686,19 @@ snapshots: '@azure/core-util@1.14.0(supports-color@7.2.0)': dependencies: '@azure/abort-controller': 2.2.0 - '@typespec/ts-http-runtime': 0.3.8(supports-color@7.2.0) + '@typespec/ts-http-runtime': 0.3.9(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color '@azure/core-xml@1.6.0': dependencies: - fast-xml-parser: 5.10.1 + fast-xml-parser: 5.11.1 tslib: 2.8.1 '@azure/logger@1.4.0(supports-color@7.2.0)': dependencies: - '@typespec/ts-http-runtime': 0.3.8(supports-color@7.2.0) + '@typespec/ts-http-runtime': 0.3.9(supports-color@7.2.0) tslib: 2.8.1 transitivePeerDependencies: - supports-color @@ -4299,8 +3707,8 @@ snapshots: dependencies: '@azure/abort-controller': 2.2.0 '@azure/core-auth': 1.11.0(supports-color@7.2.0) - '@azure/core-client': 1.11.0(supports-color@7.2.0) - '@azure/core-http-compat': 2.5.0(@azure/core-client@1.11.0(supports-color@7.2.0))(@azure/core-rest-pipeline@1.25.0(supports-color@7.2.0)) + '@azure/core-client': 1.11.1(supports-color@7.2.0) + '@azure/core-http-compat': 2.5.0(@azure/core-client@1.11.1(supports-color@7.2.0))(@azure/core-rest-pipeline@1.25.0(supports-color@7.2.0)) '@azure/core-lro': 2.7.2(supports-color@7.2.0) '@azure/core-paging': 1.7.0 '@azure/core-rest-pipeline': 1.25.0(supports-color@7.2.0) @@ -4308,17 +3716,17 @@ snapshots: '@azure/core-util': 1.14.0(supports-color@7.2.0) '@azure/core-xml': 1.6.0 '@azure/logger': 1.4.0(supports-color@7.2.0) - '@azure/storage-common': 12.5.0(@azure/core-client@1.11.0(supports-color@7.2.0))(supports-color@7.2.0) + '@azure/storage-common': 12.5.0(@azure/core-client@1.11.1(supports-color@7.2.0))(supports-color@7.2.0) events: 3.3.0 tslib: 2.8.1 transitivePeerDependencies: - supports-color - '@azure/storage-common@12.5.0(@azure/core-client@1.11.0(supports-color@7.2.0))(supports-color@7.2.0)': + '@azure/storage-common@12.5.0(@azure/core-client@1.11.1(supports-color@7.2.0))(supports-color@7.2.0)': dependencies: '@azure/abort-controller': 2.2.0 '@azure/core-auth': 1.11.0(supports-color@7.2.0) - '@azure/core-http-compat': 2.5.0(@azure/core-client@1.11.0(supports-color@7.2.0))(@azure/core-rest-pipeline@1.25.0(supports-color@7.2.0)) + '@azure/core-http-compat': 2.5.0(@azure/core-client@1.11.1(supports-color@7.2.0))(@azure/core-rest-pipeline@1.25.0(supports-color@7.2.0)) '@azure/core-rest-pipeline': 1.25.0(supports-color@7.2.0) '@azure/core-tracing': 1.4.0 '@azure/core-util': 1.14.0(supports-color@7.2.0) @@ -4329,32 +3737,32 @@ snapshots: - '@azure/core-client' - supports-color - '@babel/code-frame@7.27.1': + '@babel/code-frame@7.29.7': dependencies: - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 js-tokens: 4.0.0 picocolors: 1.1.1 '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} '@babel/parser@7.28.5': dependencies: '@babel/types': 7.28.5 - '@babel/runtime@7.28.4': {} + '@babel/runtime@7.29.7': {} '@babel/types@7.28.5': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 - '@bufbuild/protobuf@2.13.0': {} + '@bufbuild/protobuf@2.15.0': {} - '@bufbuild/protoplugin@2.13.0(supports-color@7.2.0)': + '@bufbuild/protoplugin@2.15.0(supports-color@7.2.0)': dependencies: - '@bufbuild/protobuf': 2.13.0 + '@bufbuild/protobuf': 2.15.0 '@typescript/vfs': 1.6.4(supports-color@7.2.0)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: @@ -4371,153 +3779,233 @@ snapshots: picocolors: 1.1.1 sisteransi: 1.0.5 - '@cspell/cspell-bundled-dicts@9.3.2': + '@cspell/cspell-bundled-dicts@10.3.3': + dependencies: + '@cspell/dict-ada': 4.1.1 + '@cspell/dict-al': 1.1.1 + '@cspell/dict-aws': 4.0.17 + '@cspell/dict-bash': 4.2.3 + '@cspell/dict-companies': 3.2.13 + '@cspell/dict-cpp': 7.1.2 + '@cspell/dict-cryptocurrencies': 5.0.5 + '@cspell/dict-csharp': 4.0.8 + '@cspell/dict-css': 4.1.2 + '@cspell/dict-dart': 2.3.2 + '@cspell/dict-data-science': 2.0.16 + '@cspell/dict-django': 4.1.6 + '@cspell/dict-docker': 1.1.17 + '@cspell/dict-dotnet': 5.0.15 + '@cspell/dict-elixir': 4.0.8 + '@cspell/dict-en-common-misspellings': 2.2.2 + '@cspell/dict-en-gb-mit': 3.1.29 + '@cspell/dict-en_us': 4.4.40 + '@cspell/dict-filetypes': 3.0.18 + '@cspell/dict-flutter': 1.1.1 + '@cspell/dict-fonts': 4.0.6 + '@cspell/dict-fsharp': 1.1.1 + '@cspell/dict-fullstack': 3.2.9 + '@cspell/dict-gaming-terms': 1.1.2 + '@cspell/dict-git': 3.1.1 + '@cspell/dict-golang': 6.0.29 + '@cspell/dict-google': 1.0.9 + '@cspell/dict-haskell': 4.0.6 + '@cspell/dict-html': 4.0.16 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-java': 5.0.12 + '@cspell/dict-julia': 1.1.1 + '@cspell/dict-k8s': 1.0.13 + '@cspell/dict-kotlin': 1.1.1 + '@cspell/dict-latex': 5.1.0 + '@cspell/dict-lorem-ipsum': 4.0.5 + '@cspell/dict-lua': 4.0.8 + '@cspell/dict-makefile': 1.0.5 + '@cspell/dict-markdown': 2.0.18(@cspell/dict-css@4.1.2)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.16)(@cspell/dict-typescript@3.2.3) + '@cspell/dict-monkeyc': 1.1.2 + '@cspell/dict-node': 5.0.9 + '@cspell/dict-npm': 5.2.50 + '@cspell/dict-php': 4.1.3 + '@cspell/dict-powershell': 5.0.17 + '@cspell/dict-public-licenses': 2.0.16 + '@cspell/dict-python': 4.5.2 + '@cspell/dict-r': 2.1.1 + '@cspell/dict-ruby': 5.1.4 + '@cspell/dict-rust': 4.1.2 + '@cspell/dict-scala': 5.0.11 + '@cspell/dict-shell': 1.2.0 + '@cspell/dict-software-terms': 5.4.5 + '@cspell/dict-sql': 2.2.1 + '@cspell/dict-svelte': 1.0.7 + '@cspell/dict-swift': 2.0.6 + '@cspell/dict-terraform': 1.1.4 + '@cspell/dict-typescript': 3.2.3 + '@cspell/dict-vue': 3.0.5 + '@cspell/dict-zig': 1.0.0 + + '@cspell/cspell-bundled-dicts@9.8.0': dependencies: '@cspell/dict-ada': 4.1.1 '@cspell/dict-al': 1.1.1 - '@cspell/dict-aws': 4.0.16 - '@cspell/dict-bash': 4.2.2 - '@cspell/dict-companies': 3.2.7 - '@cspell/dict-cpp': 6.0.14 + '@cspell/dict-aws': 4.0.17 + '@cspell/dict-bash': 4.2.3 + '@cspell/dict-companies': 3.2.13 + '@cspell/dict-cpp': 7.1.2 '@cspell/dict-cryptocurrencies': 5.0.5 - '@cspell/dict-csharp': 4.0.7 - '@cspell/dict-css': 4.0.18 - '@cspell/dict-dart': 2.3.1 - '@cspell/dict-data-science': 2.0.12 - '@cspell/dict-django': 4.1.5 - '@cspell/dict-docker': 1.1.16 - '@cspell/dict-dotnet': 5.0.10 + '@cspell/dict-csharp': 4.0.8 + '@cspell/dict-css': 4.1.2 + '@cspell/dict-dart': 2.3.2 + '@cspell/dict-data-science': 2.0.16 + '@cspell/dict-django': 4.1.6 + '@cspell/dict-docker': 1.1.17 + '@cspell/dict-dotnet': 5.0.15 '@cspell/dict-elixir': 4.0.8 - '@cspell/dict-en-common-misspellings': 2.1.8 - '@cspell/dict-en-gb-mit': 3.1.14 - '@cspell/dict-en_us': 4.4.24 - '@cspell/dict-filetypes': 3.0.14 + '@cspell/dict-en-common-misspellings': 2.2.2 + '@cspell/dict-en-gb-mit': 3.1.29 + '@cspell/dict-en_us': 4.4.40 + '@cspell/dict-filetypes': 3.0.18 '@cspell/dict-flutter': 1.1.1 - '@cspell/dict-fonts': 4.0.5 + '@cspell/dict-fonts': 4.0.6 '@cspell/dict-fsharp': 1.1.1 - '@cspell/dict-fullstack': 3.2.7 + '@cspell/dict-fullstack': 3.2.9 '@cspell/dict-gaming-terms': 1.1.2 - '@cspell/dict-git': 3.0.7 - '@cspell/dict-golang': 6.0.24 + '@cspell/dict-git': 3.1.1 + '@cspell/dict-golang': 6.0.29 '@cspell/dict-google': 1.0.9 '@cspell/dict-haskell': 4.0.6 - '@cspell/dict-html': 4.0.12 - '@cspell/dict-html-symbol-entities': 4.0.4 + '@cspell/dict-html': 4.0.16 + '@cspell/dict-html-symbol-entities': 4.0.5 '@cspell/dict-java': 5.0.12 '@cspell/dict-julia': 1.1.1 - '@cspell/dict-k8s': 1.0.12 + '@cspell/dict-k8s': 1.0.13 '@cspell/dict-kotlin': 1.1.1 - '@cspell/dict-latex': 4.0.4 + '@cspell/dict-latex': 5.1.0 '@cspell/dict-lorem-ipsum': 4.0.5 '@cspell/dict-lua': 4.0.8 '@cspell/dict-makefile': 1.0.5 - '@cspell/dict-markdown': 2.0.12(@cspell/dict-css@4.0.18)(@cspell/dict-html-symbol-entities@4.0.4)(@cspell/dict-html@4.0.12)(@cspell/dict-typescript@3.2.3) - '@cspell/dict-monkeyc': 1.0.11 - '@cspell/dict-node': 5.0.8 - '@cspell/dict-npm': 5.2.24 - '@cspell/dict-php': 4.1.0 - '@cspell/dict-powershell': 5.0.15 - '@cspell/dict-public-licenses': 2.0.15 - '@cspell/dict-python': 4.2.22 + '@cspell/dict-markdown': 2.0.18(@cspell/dict-css@4.1.2)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.16)(@cspell/dict-typescript@3.2.3) + '@cspell/dict-monkeyc': 1.1.2 + '@cspell/dict-node': 5.0.9 + '@cspell/dict-npm': 5.2.50 + '@cspell/dict-php': 4.1.3 + '@cspell/dict-powershell': 5.0.17 + '@cspell/dict-public-licenses': 2.0.16 + '@cspell/dict-python': 4.5.2 '@cspell/dict-r': 2.1.1 - '@cspell/dict-ruby': 5.0.9 - '@cspell/dict-rust': 4.0.12 - '@cspell/dict-scala': 5.0.8 - '@cspell/dict-shell': 1.1.2 - '@cspell/dict-software-terms': 5.1.14 + '@cspell/dict-ruby': 5.1.4 + '@cspell/dict-rust': 4.1.2 + '@cspell/dict-scala': 5.0.11 + '@cspell/dict-shell': 1.2.0 + '@cspell/dict-software-terms': 5.4.5 '@cspell/dict-sql': 2.2.1 '@cspell/dict-svelte': 1.0.7 '@cspell/dict-swift': 2.0.6 - '@cspell/dict-terraform': 1.1.3 + '@cspell/dict-terraform': 1.1.4 '@cspell/dict-typescript': 3.2.3 '@cspell/dict-vue': 3.0.5 '@cspell/dict-zig': 1.0.0 - '@cspell/cspell-json-reporter@9.3.2': + '@cspell/cspell-json-reporter@9.8.0': dependencies: - '@cspell/cspell-types': 9.3.2 + '@cspell/cspell-types': 9.8.0 - '@cspell/cspell-pipe@9.3.2': {} + '@cspell/cspell-performance-monitor@10.3.3': {} - '@cspell/cspell-resolver@9.3.2': + '@cspell/cspell-performance-monitor@9.8.0': {} + + '@cspell/cspell-pipe@10.3.3': {} + + '@cspell/cspell-pipe@9.8.0': {} + + '@cspell/cspell-resolver@10.3.3': + dependencies: + global-directory: 5.0.0 + + '@cspell/cspell-resolver@9.8.0': dependencies: - global-directory: 4.0.1 + global-directory: 5.0.0 + + '@cspell/cspell-service-bus@10.3.3': {} + + '@cspell/cspell-service-bus@9.8.0': {} + + '@cspell/cspell-types@10.3.3': {} - '@cspell/cspell-service-bus@9.3.2': {} + '@cspell/cspell-types@9.8.0': {} - '@cspell/cspell-types@9.3.2': {} + '@cspell/cspell-worker@9.8.0': + dependencies: + cspell-lib: 9.8.0 '@cspell/dict-ada@4.1.1': {} '@cspell/dict-al@1.1.1': {} - '@cspell/dict-aws@4.0.16': {} + '@cspell/dict-aws@4.0.17': {} - '@cspell/dict-bash@4.2.2': + '@cspell/dict-bash@4.2.3': dependencies: - '@cspell/dict-shell': 1.1.2 + '@cspell/dict-shell': 1.2.0 - '@cspell/dict-companies@3.2.7': {} + '@cspell/dict-companies@3.2.13': {} - '@cspell/dict-cpp@6.0.14': {} + '@cspell/dict-cpp@7.1.2': {} '@cspell/dict-cryptocurrencies@5.0.5': {} - '@cspell/dict-csharp@4.0.7': {} + '@cspell/dict-csharp@4.0.8': {} - '@cspell/dict-css@4.0.18': {} + '@cspell/dict-css@4.1.2': {} - '@cspell/dict-dart@2.3.1': {} + '@cspell/dict-dart@2.3.2': {} - '@cspell/dict-data-science@2.0.12': {} + '@cspell/dict-data-science@2.0.16': {} - '@cspell/dict-django@4.1.5': {} + '@cspell/dict-django@4.1.6': {} - '@cspell/dict-docker@1.1.16': {} + '@cspell/dict-docker@1.1.17': {} - '@cspell/dict-dotnet@5.0.10': {} + '@cspell/dict-dotnet@5.0.15': {} '@cspell/dict-elixir@4.0.8': {} - '@cspell/dict-en-common-misspellings@2.1.8': {} + '@cspell/dict-en-common-misspellings@2.2.2': {} - '@cspell/dict-en-gb-mit@3.1.14': {} + '@cspell/dict-en-gb-mit@3.1.29': {} - '@cspell/dict-en_us@4.4.24': {} + '@cspell/dict-en_us@4.4.40': {} - '@cspell/dict-filetypes@3.0.14': {} + '@cspell/dict-filetypes@3.0.18': {} '@cspell/dict-flutter@1.1.1': {} - '@cspell/dict-fonts@4.0.5': {} + '@cspell/dict-fonts@4.0.6': {} '@cspell/dict-fsharp@1.1.1': {} - '@cspell/dict-fullstack@3.2.7': {} + '@cspell/dict-fullstack@3.2.9': {} '@cspell/dict-gaming-terms@1.1.2': {} - '@cspell/dict-git@3.0.7': {} + '@cspell/dict-git@3.1.1': {} - '@cspell/dict-golang@6.0.24': {} + '@cspell/dict-golang@6.0.29': {} '@cspell/dict-google@1.0.9': {} '@cspell/dict-haskell@4.0.6': {} - '@cspell/dict-html-symbol-entities@4.0.4': {} + '@cspell/dict-html-symbol-entities@4.0.5': {} - '@cspell/dict-html@4.0.12': {} + '@cspell/dict-html@4.0.16': {} '@cspell/dict-java@5.0.12': {} '@cspell/dict-julia@1.1.1': {} - '@cspell/dict-k8s@1.0.12': {} + '@cspell/dict-k8s@1.0.13': {} '@cspell/dict-kotlin@1.1.1': {} - '@cspell/dict-latex@4.0.4': {} + '@cspell/dict-latex@5.1.0': {} '@cspell/dict-lorem-ipsum@4.0.5': {} @@ -4525,40 +4013,40 @@ snapshots: '@cspell/dict-makefile@1.0.5': {} - '@cspell/dict-markdown@2.0.12(@cspell/dict-css@4.0.18)(@cspell/dict-html-symbol-entities@4.0.4)(@cspell/dict-html@4.0.12)(@cspell/dict-typescript@3.2.3)': + '@cspell/dict-markdown@2.0.18(@cspell/dict-css@4.1.2)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.16)(@cspell/dict-typescript@3.2.3)': dependencies: - '@cspell/dict-css': 4.0.18 - '@cspell/dict-html': 4.0.12 - '@cspell/dict-html-symbol-entities': 4.0.4 + '@cspell/dict-css': 4.1.2 + '@cspell/dict-html': 4.0.16 + '@cspell/dict-html-symbol-entities': 4.0.5 '@cspell/dict-typescript': 3.2.3 - '@cspell/dict-monkeyc@1.0.11': {} + '@cspell/dict-monkeyc@1.1.2': {} - '@cspell/dict-node@5.0.8': {} + '@cspell/dict-node@5.0.9': {} - '@cspell/dict-npm@5.2.24': {} + '@cspell/dict-npm@5.2.50': {} - '@cspell/dict-php@4.1.0': {} + '@cspell/dict-php@4.1.3': {} - '@cspell/dict-powershell@5.0.15': {} + '@cspell/dict-powershell@5.0.17': {} - '@cspell/dict-public-licenses@2.0.15': {} + '@cspell/dict-public-licenses@2.0.16': {} - '@cspell/dict-python@4.2.22': + '@cspell/dict-python@4.5.2': dependencies: - '@cspell/dict-data-science': 2.0.12 + '@cspell/dict-data-science': 2.0.16 '@cspell/dict-r@2.1.1': {} - '@cspell/dict-ruby@5.0.9': {} + '@cspell/dict-ruby@5.1.4': {} - '@cspell/dict-rust@4.0.12': {} + '@cspell/dict-rust@4.1.2': {} - '@cspell/dict-scala@5.0.8': {} + '@cspell/dict-scala@5.0.11': {} - '@cspell/dict-shell@1.1.2': {} + '@cspell/dict-shell@1.2.0': {} - '@cspell/dict-software-terms@5.1.14': {} + '@cspell/dict-software-terms@5.4.5': {} '@cspell/dict-sql@2.2.1': {} @@ -4566,7 +4054,7 @@ snapshots: '@cspell/dict-swift@2.0.6': {} - '@cspell/dict-terraform@1.1.3': {} + '@cspell/dict-terraform@1.1.4': {} '@cspell/dict-typescript@3.2.3': {} @@ -4574,294 +4062,318 @@ snapshots: '@cspell/dict-zig@1.0.0': {} - '@cspell/dynamic-import@9.3.2': + '@cspell/dynamic-import@10.3.3': + dependencies: + '@cspell/url': 10.3.3 + import-meta-resolve: 4.2.0 + + '@cspell/dynamic-import@9.8.0': dependencies: - '@cspell/url': 9.3.2 + '@cspell/url': 9.8.0 import-meta-resolve: 4.2.0 - '@cspell/filetypes@9.3.2': {} + '@cspell/eslint-plugin@10.3.3(eslint@9.39.5(supports-color@7.2.0))': + dependencies: + '@cspell/cspell-types': 10.3.3 + '@cspell/url': 10.3.3 + cspell-lib: 10.3.3 + eslint: 9.39.5(supports-color@7.2.0) + synckit: 0.11.13 + + '@cspell/filetypes@10.3.3': {} + + '@cspell/filetypes@9.8.0': {} + + '@cspell/rpc@10.3.3': {} - '@cspell/strong-weak-map@9.3.2': {} + '@cspell/rpc@9.8.0': {} - '@cspell/url@9.3.2': {} + '@cspell/strong-weak-map@10.3.3': {} - '@emnapi/core@1.7.1': + '@cspell/strong-weak-map@9.8.0': {} + + '@cspell/url@10.3.3': {} + + '@cspell/url@9.8.0': {} + + '@emnapi/core@1.10.0': dependencies: - '@emnapi/wasi-threads': 1.1.0 + '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - '@emnapi/runtime@1.7.1': + '@emnapi/runtime@1.10.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/wasi-threads@1.1.0': + '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 optional: true '@es-joy/jsdoccomment@0.50.2': dependencies: - '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.48.0 + '@types/estree': 1.0.9 + '@typescript-eslint/types': 8.70.0 comment-parser: 1.4.1 - esquery: 1.6.0 + esquery: 1.7.0 jsdoc-type-pratt-parser: 4.1.0 - '@esbuild/aix-ppc64@0.25.12': + '@esbuild/aix-ppc64@0.27.7': optional: true - '@esbuild/aix-ppc64@0.27.0': + '@esbuild/aix-ppc64@0.28.2': optional: true - '@esbuild/android-arm64@0.25.12': + '@esbuild/android-arm64@0.27.7': optional: true - '@esbuild/android-arm64@0.27.0': + '@esbuild/android-arm64@0.28.2': optional: true - '@esbuild/android-arm@0.25.12': + '@esbuild/android-arm@0.27.7': optional: true - '@esbuild/android-arm@0.27.0': + '@esbuild/android-arm@0.28.2': optional: true - '@esbuild/android-x64@0.25.12': + '@esbuild/android-x64@0.27.7': optional: true - '@esbuild/android-x64@0.27.0': + '@esbuild/android-x64@0.28.2': optional: true - '@esbuild/darwin-arm64@0.25.12': + '@esbuild/darwin-arm64@0.27.7': optional: true - '@esbuild/darwin-arm64@0.27.0': + '@esbuild/darwin-arm64@0.28.2': optional: true - '@esbuild/darwin-x64@0.25.12': + '@esbuild/darwin-x64@0.27.7': optional: true - '@esbuild/darwin-x64@0.27.0': + '@esbuild/darwin-x64@0.28.2': optional: true - '@esbuild/freebsd-arm64@0.25.12': + '@esbuild/freebsd-arm64@0.27.7': optional: true - '@esbuild/freebsd-arm64@0.27.0': + '@esbuild/freebsd-arm64@0.28.2': optional: true - '@esbuild/freebsd-x64@0.25.12': + '@esbuild/freebsd-x64@0.27.7': optional: true - '@esbuild/freebsd-x64@0.27.0': + '@esbuild/freebsd-x64@0.28.2': optional: true - '@esbuild/linux-arm64@0.25.12': + '@esbuild/linux-arm64@0.27.7': optional: true - '@esbuild/linux-arm64@0.27.0': + '@esbuild/linux-arm64@0.28.2': optional: true - '@esbuild/linux-arm@0.25.12': + '@esbuild/linux-arm@0.27.7': optional: true - '@esbuild/linux-arm@0.27.0': + '@esbuild/linux-arm@0.28.2': optional: true - '@esbuild/linux-ia32@0.25.12': + '@esbuild/linux-ia32@0.27.7': optional: true - '@esbuild/linux-ia32@0.27.0': + '@esbuild/linux-ia32@0.28.2': optional: true - '@esbuild/linux-loong64@0.25.12': + '@esbuild/linux-loong64@0.27.7': optional: true - '@esbuild/linux-loong64@0.27.0': + '@esbuild/linux-loong64@0.28.2': optional: true - '@esbuild/linux-mips64el@0.25.12': + '@esbuild/linux-mips64el@0.27.7': optional: true - '@esbuild/linux-mips64el@0.27.0': + '@esbuild/linux-mips64el@0.28.2': optional: true - '@esbuild/linux-ppc64@0.25.12': + '@esbuild/linux-ppc64@0.27.7': optional: true - '@esbuild/linux-ppc64@0.27.0': + '@esbuild/linux-ppc64@0.28.2': optional: true - '@esbuild/linux-riscv64@0.25.12': + '@esbuild/linux-riscv64@0.27.7': optional: true - '@esbuild/linux-riscv64@0.27.0': + '@esbuild/linux-riscv64@0.28.2': optional: true - '@esbuild/linux-s390x@0.25.12': + '@esbuild/linux-s390x@0.27.7': optional: true - '@esbuild/linux-s390x@0.27.0': + '@esbuild/linux-s390x@0.28.2': optional: true - '@esbuild/linux-x64@0.25.12': + '@esbuild/linux-x64@0.27.7': optional: true - '@esbuild/linux-x64@0.27.0': + '@esbuild/linux-x64@0.28.2': optional: true - '@esbuild/netbsd-arm64@0.25.12': + '@esbuild/netbsd-arm64@0.27.7': optional: true - '@esbuild/netbsd-arm64@0.27.0': + '@esbuild/netbsd-arm64@0.28.2': optional: true - '@esbuild/netbsd-x64@0.25.12': + '@esbuild/netbsd-x64@0.27.7': optional: true - '@esbuild/netbsd-x64@0.27.0': + '@esbuild/netbsd-x64@0.28.2': optional: true - '@esbuild/openbsd-arm64@0.25.12': + '@esbuild/openbsd-arm64@0.27.7': optional: true - '@esbuild/openbsd-arm64@0.27.0': + '@esbuild/openbsd-arm64@0.28.2': optional: true - '@esbuild/openbsd-x64@0.25.12': + '@esbuild/openbsd-x64@0.27.7': optional: true - '@esbuild/openbsd-x64@0.27.0': + '@esbuild/openbsd-x64@0.28.2': optional: true - '@esbuild/openharmony-arm64@0.25.12': + '@esbuild/openharmony-arm64@0.27.7': optional: true - '@esbuild/openharmony-arm64@0.27.0': + '@esbuild/openharmony-arm64@0.28.2': optional: true - '@esbuild/sunos-x64@0.25.12': + '@esbuild/sunos-x64@0.27.7': optional: true - '@esbuild/sunos-x64@0.27.0': + '@esbuild/sunos-x64@0.28.2': optional: true - '@esbuild/win32-arm64@0.25.12': + '@esbuild/win32-arm64@0.27.7': optional: true - '@esbuild/win32-arm64@0.27.0': + '@esbuild/win32-arm64@0.28.2': optional: true - '@esbuild/win32-ia32@0.25.12': + '@esbuild/win32-ia32@0.27.7': optional: true - '@esbuild/win32-ia32@0.27.0': + '@esbuild/win32-ia32@0.28.2': optional: true - '@esbuild/win32-x64@0.25.12': + '@esbuild/win32-x64@0.27.7': optional: true - '@esbuild/win32-x64@0.27.0': + '@esbuild/win32-x64@0.28.2': optional: true - '@eslint-community/eslint-plugin-eslint-comments@4.5.0(eslint@9.39.1(supports-color@7.2.0))': + '@eslint-community/eslint-plugin-eslint-comments@4.8.1(eslint@9.39.5(supports-color@7.2.0))': dependencies: escape-string-regexp: 4.0.0 - eslint: 9.39.1(supports-color@7.2.0) - ignore: 5.3.2 + eslint: 9.39.5(supports-color@7.2.0) + ignore: 7.0.9 - '@eslint-community/eslint-utils@4.9.0(eslint@9.39.1(supports-color@7.2.0))': + '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(supports-color@7.2.0))': dependencies: - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.2': {} - '@eslint-react/ast@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@eslint-react/ast@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@eslint-react/eff': 2.3.9 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - string-ts: 2.2.1 + '@eslint-react/eff': 2.13.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + string-ts: 2.3.1 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@eslint-react/core@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/var': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - birecord: 0.1.1 - eslint: 9.39.1(supports-color@7.2.0) + '@eslint-react/core@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + dependencies: + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@eslint-react/eff@2.3.9': {} - - '@eslint-react/eslint-plugin@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - eslint-plugin-react-dom: 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-react-hooks-extra: 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-react-naming-convention: 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-react-web-api: 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-react-x: 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - ts-api-utils: 2.1.0(typescript@6.0.3) + '@eslint-react/eff@2.13.0': {} + + '@eslint-react/eslint-plugin@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + dependencies: + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + eslint-plugin-react-dom: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-hooks-extra: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-naming-convention: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-rsc: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-web-api: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-x: 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@eslint-react/shared@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@eslint-react/shared@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@eslint-react/eff': 2.3.9 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) + '@eslint-react/eff': 2.13.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) ts-pattern: 5.9.0 typescript: 6.0.3 - zod: 4.1.13 + zod: 4.6.5 transitivePeerDependencies: - supports-color - '@eslint-react/var@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@eslint-react/var@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@eslint/compat@1.4.1(eslint@9.39.1(supports-color@7.2.0))': + '@eslint/compat@1.4.1(eslint@9.39.5(supports-color@7.2.0))': dependencies: '@eslint/core': 0.17.0 optionalDependencies: - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) - '@eslint/config-array@0.21.1(supports-color@7.2.0)': + '@eslint/config-array@0.21.2(supports-color@7.2.0)': dependencies: '@eslint/object-schema': 2.1.7 debug: 4.4.3(supports-color@7.2.0) - minimatch: 3.1.2 + minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -4881,28 +4393,28 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1(supports-color@7.2.0)': + '@eslint/eslintrc@3.3.7(supports-color@7.2.0)': dependencies: - ajv: 6.12.6 + ajv: 6.15.0 debug: 4.4.3(supports-color@7.2.0) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.1 - minimatch: 3.1.2 + js-yaml: 4.3.2 + minimatch: 3.1.5 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - '@eslint/js@9.39.1': {} + '@eslint/js@9.39.5': {} '@eslint/markdown@6.6.0(supports-color@7.2.0)': dependencies: '@eslint/core': 0.14.0 '@eslint/plugin-kit': 0.3.5 github-slugger: 2.0.0 - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-frontmatter: 2.0.1(supports-color@7.2.0) mdast-util-gfm: 3.1.0(supports-color@7.2.0) micromark-extension-frontmatter: 2.0.0 @@ -4924,28 +4436,27 @@ snapshots: '@fastify/busboy@2.1.1': {} - '@humanfs/core@0.19.1': {} + '@humanfs/core@0.19.2': + dependencies: + '@humanfs/types': 0.15.0 - '@humanfs/node@0.16.7': + '@humanfs/node@0.16.8': dependencies: - '@humanfs/core': 0.19.1 + '@humanfs/core': 0.19.2 + '@humanfs/types': 0.15.0 '@humanwhocodes/retry': 0.4.3 + '@humanfs/types@0.15.0': {} + '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/retry@0.4.3': {} - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': - dependencies: - '@isaacs/balanced-match': 4.0.1 - '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 @@ -4956,51 +4467,30 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/sourcemap-codec': 1.6.0 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/sourcemap-codec@1.5.5': {} + '@jridgewell/sourcemap-codec@1.6.0': {} '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)': - dependencies: - jsep: 1.4.0 + '@jridgewell/sourcemap-codec': 1.6.0 - '@jsep-plugin/regex@1.0.4(jsep@1.4.0)': - dependencies: - jsep: 1.4.0 - - '@jsep-plugin/ternary@1.1.4(jsep@1.4.0)': - dependencies: - jsep: 1.4.0 + '@napi-rs/lzma-linux-x64-gnu@1.5.1': + optional: true - '@napi-rs/wasm-runtime@0.2.12': + '@napi-rs/wasm-runtime@1.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 - '@tybys/wasm-util': 0.10.1 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@tybys/wasm-util': 0.10.4 optional: true '@nodable/entities@3.0.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.19.1 - '@octokit/auth-token@4.0.0': {} '@octokit/core@5.2.2': @@ -5077,12 +4567,12 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@pkgr/core@0.2.9': {} + '@pkgr/core@0.3.6': {} '@protobuf-ts/plugin@2.11.1(supports-color@7.2.0)': dependencies: - '@bufbuild/protobuf': 2.13.0 - '@bufbuild/protoplugin': 2.13.0(supports-color@7.2.0) + '@bufbuild/protobuf': 2.15.0 + '@bufbuild/protoplugin': 2.15.0(supports-color@7.2.0) '@protobuf-ts/protoc': 2.11.1 '@protobuf-ts/runtime': 2.11.1 '@protobuf-ts/runtime-rpc': 2.11.1 @@ -5101,516 +4591,240 @@ snapshots: '@redocly/ajv@8.18.3': dependencies: fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 + fast-uri: 3.1.8 json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - '@redocly/cli@2.49.0': {} + '@redocly/cli@2.54.3': {} - '@redocly/config@0.53.1': + '@redocly/config@0.57.0': dependencies: json-schema-to-ts: 2.7.2 - '@redocly/openapi-core@2.49.0': + '@redocly/openapi-core@2.54.3': dependencies: '@redocly/ajv': 8.18.3 - '@redocly/config': 0.53.1 + '@redocly/config': 0.57.0 ajv: '@redocly/ajv@8.18.3' ajv-formats: 3.0.1(@redocly/ajv@8.18.3) colorette: 1.4.0 graphql: 16.14.2 js-levenshtein: 1.1.6 - js-yaml: 5.4.1 + js-yaml: 5.4.2 picomatch: 4.0.7 pluralize: 8.0.0 yaml-ast-parser: 0.0.43 - '@rollup/plugin-commonjs@22.0.2(rollup@2.79.2)': - dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.2) - 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.11 - rollup: 2.79.2 + '@rollup/rollup-android-arm-eabi@4.63.4': + optional: true - '@rollup/pluginutils@3.1.0(rollup@2.79.2)': - dependencies: - '@types/estree': 0.0.39 - estree-walker: 1.0.1 - picomatch: 2.3.1 - rollup: 2.79.2 + '@rollup/rollup-android-arm64@4.63.4': + optional: true - '@rollup/rollup-android-arm-eabi@4.53.3': + '@rollup/rollup-darwin-arm64@4.63.4': optional: true - '@rollup/rollup-android-arm64@4.53.3': + '@rollup/rollup-darwin-x64@4.63.4': optional: true - '@rollup/rollup-darwin-arm64@4.53.3': + '@rollup/rollup-freebsd-arm64@4.63.4': optional: true - '@rollup/rollup-darwin-x64@4.53.3': + '@rollup/rollup-freebsd-x64@4.63.4': optional: true - '@rollup/rollup-freebsd-arm64@4.53.3': + '@rollup/rollup-linux-arm-gnueabihf@4.63.4': optional: true - '@rollup/rollup-freebsd-x64@4.53.3': + '@rollup/rollup-linux-arm-musleabihf@4.63.4': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.53.3': + '@rollup/rollup-linux-arm64-gnu@4.63.4': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.53.3': + '@rollup/rollup-linux-arm64-musl@4.63.4': optional: true - '@rollup/rollup-linux-arm64-gnu@4.53.3': + '@rollup/rollup-linux-loong64-gnu@4.63.4': optional: true - '@rollup/rollup-linux-arm64-musl@4.53.3': + '@rollup/rollup-linux-loong64-musl@4.63.4': optional: true - '@rollup/rollup-linux-loong64-gnu@4.53.3': + '@rollup/rollup-linux-ppc64-gnu@4.63.4': optional: true - '@rollup/rollup-linux-ppc64-gnu@4.53.3': + '@rollup/rollup-linux-ppc64-musl@4.63.4': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.53.3': + '@rollup/rollup-linux-riscv64-gnu@4.63.4': optional: true - '@rollup/rollup-linux-riscv64-musl@4.53.3': + '@rollup/rollup-linux-riscv64-musl@4.63.4': optional: true - '@rollup/rollup-linux-s390x-gnu@4.53.3': + '@rollup/rollup-linux-s390x-gnu@4.63.4': optional: true - '@rollup/rollup-linux-x64-gnu@4.53.3': + '@rollup/rollup-linux-x64-gnu@4.63.4': optional: true - '@rollup/rollup-linux-x64-musl@4.53.3': + '@rollup/rollup-linux-x64-musl@4.63.4': optional: true - '@rollup/rollup-openharmony-arm64@4.53.3': + '@rollup/rollup-openbsd-x64@4.63.4': optional: true - '@rollup/rollup-win32-arm64-msvc@4.53.3': + '@rollup/rollup-openharmony-arm64@4.63.4': optional: true - '@rollup/rollup-win32-ia32-msvc@4.53.3': + '@rollup/rollup-win32-arm64-msvc@4.63.4': optional: true - '@rollup/rollup-win32-x64-gnu@4.53.3': + '@rollup/rollup-win32-ia32-msvc@4.63.4': optional: true - '@rollup/rollup-win32-x64-msvc@4.53.3': + '@rollup/rollup-win32-x64-gnu@4.63.4': optional: true - '@stoplight/better-ajv-errors@1.0.3(ajv@8.17.1)': - dependencies: - ajv: 8.17.1 - jsonpointer: 5.0.1 - leven: 3.1.0 + '@rollup/rollup-win32-x64-msvc@4.63.4': + optional: true - '@stoplight/json-ref-readers@1.2.2': + '@stylistic/eslint-plugin@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': 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.17.21 - 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.17.21 - safe-stable-stringify: 1.1.1 - - '@stoplight/ordered-object-literal@1.0.5': {} - - '@stoplight/path@1.3.2': {} - - '@stoplight/spectral-cli@6.15.0': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formatters': 1.5.0 - '@stoplight/spectral-parsers': 1.0.5 - '@stoplight/spectral-ref-resolver': 1.0.5 - '@stoplight/spectral-ruleset-bundler': 1.6.3 - '@stoplight/spectral-ruleset-migrator': 1.11.3 - '@stoplight/spectral-rulesets': 1.22.0 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - chalk: 4.1.2 - fast-glob: 3.2.12 - hpagent: 1.2.0 - lodash: 4.17.21 - pony-cause: 1.1.1 - stacktracey: 2.1.8 - tslib: 2.8.1 - yargs: 17.7.2 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-core@1.20.0': - dependencies: - '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@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.4 - '@stoplight/types': 13.6.0 - '@types/es-aggregate-error': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-errors: 3.0.0(ajv@8.17.1) - ajv-formats: 2.1.1(ajv@8.17.1) - es-aggregate-error: 1.0.14 - jsonpath-plus: 10.3.0 - lodash: 4.17.21 - lodash.topath: 4.5.2 - minimatch: 3.1.2 - nimma: 0.2.3 - pony-cause: 1.1.1 - simple-eval: 1.0.1 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-formats@1.8.2': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/spectral-core': 1.20.0 - '@types/json-schema': 7.0.15 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-formatters@1.5.0': - dependencies: - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@types/markdown-escape': 1.1.3 - chalk: 4.1.2 - cliui: 7.0.4 - lodash: 4.17.21 - 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.1': - dependencies: - '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.7 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formats': 1.8.2 - '@stoplight/spectral-runtime': 1.1.4 - ajv: 8.17.1 - ajv-draft-04: 1.0.0(ajv@8.17.1) - ajv-errors: 3.0.0(ajv@8.17.1) - ajv-formats: 2.1.1(ajv@8.17.1) - lodash: 4.17.21 - 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.4 - dependency-graph: 0.11.0 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-ruleset-bundler@1.6.3': - dependencies: - '@rollup/plugin-commonjs': 22.0.2(rollup@2.79.2) - '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formats': 1.8.2 - '@stoplight/spectral-functions': 1.10.1 - '@stoplight/spectral-parsers': 1.0.5 - '@stoplight/spectral-ref-resolver': 1.0.5 - '@stoplight/spectral-ruleset-migrator': 1.11.3 - '@stoplight/spectral-rulesets': 1.22.0 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@types/node': 24.10.1 - pony-cause: 1.1.1 - rollup: 2.79.2 - tslib: 2.8.1 - validate-npm-package-name: 3.0.0 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-ruleset-migrator@1.11.3': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/ordered-object-literal': 1.0.5 - '@stoplight/path': 1.3.2 - '@stoplight/spectral-functions': 1.10.1 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@stoplight/yaml': 4.2.3 - '@types/node': 24.10.1 - ajv: 8.17.1 - 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.0': - dependencies: - '@asyncapi/specs': 6.10.0 - '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.7 - '@stoplight/spectral-core': 1.20.0 - '@stoplight/spectral-formats': 1.8.2 - '@stoplight/spectral-functions': 1.10.1 - '@stoplight/spectral-runtime': 1.1.4 - '@stoplight/types': 13.20.0 - '@types/json-schema': 7.0.15 - ajv: 8.17.1 - ajv-formats: 2.1.1(ajv@8.17.1) - json-schema-traverse: 1.0.0 - leven: 3.1.0 - lodash: 4.17.21 - tslib: 2.8.1 - transitivePeerDependencies: - - encoding - - '@stoplight/spectral-runtime@1.1.4': - dependencies: - '@stoplight/json': 3.21.7 - '@stoplight/path': 1.3.2 - '@stoplight/types': 13.20.0 - abort-controller: 3.0.0 - lodash: 4.17.21 - 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 - - '@stylistic/eslint-plugin@2.13.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': - dependencies: - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - eslint-visitor-keys: 4.2.1 - espree: 10.4.0 - estraverse: 5.3.0 - picomatch: 4.0.3 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + estraverse: 5.3.0 + picomatch: 4.0.7 transitivePeerDependencies: - supports-color - typescript - '@tybys/wasm-util@0.10.1': + '@tybys/wasm-util@0.10.4': dependencies: tslib: 2.8.1 optional: true - '@types/bun@1.3.3': + '@types/bun@1.4.2': dependencies: - bun-types: 1.3.3 + bun-types: 1.4.2 - '@types/debug@4.1.12': + '@types/debug@4.1.13': dependencies: '@types/ms': 2.1.0 - '@types/es-aggregate-error@1.0.6': - dependencies: - '@types/node': 24.10.1 - - '@types/estree@0.0.39': {} - - '@types/estree@1.0.8': {} + '@types/estree@1.0.9': {} '@types/json-schema@7.0.15': {} - '@types/markdown-escape@1.1.3': {} - '@types/mdast@4.0.4': dependencies: '@types/unist': 3.0.3 '@types/ms@2.1.0': {} - '@types/node@24.10.1': + '@types/node@24.13.6': dependencies: - undici-types: 7.16.0 + undici-types: 7.18.2 '@types/normalize-package-data@2.4.4': {} '@types/pluralize@0.0.33': {} - '@types/sarif@2.1.7': {} - '@types/unist@3.0.3': {} - '@types/urijs@1.19.26': {} - - '@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.48.0 - eslint: 9.39.1(supports-color@7.2.0) - graphemer: 1.4.0 - ignore: 7.0.5 + '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.70.0 + eslint: 9.39.5(supports-color@7.2.0) + ignore: 7.0.9 natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@6.0.3) + ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/visitor-keys': 8.70.0 debug: 4.4.3(supports-color@7.2.0) - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.48.0(supports-color@7.2.0)(typescript@6.0.3)': + '@typescript-eslint/project-service@8.70.0(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@6.0.3) - '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 debug: 4.4.3(supports-color@7.2.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.48.0': + '@typescript-eslint/scope-manager@8.70.0': dependencies: - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/visitor-keys': 8.70.0 - '@typescript-eslint/tsconfig-utils@8.48.0(typescript@6.0.3)': + '@typescript-eslint/tsconfig-utils@8.70.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@typescript-eslint/type-utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) debug: 4.4.3(supports-color@7.2.0) - eslint: 9.39.1(supports-color@7.2.0) - ts-api-utils: 2.1.0(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.48.0': {} + '@typescript-eslint/types@8.70.0': {} - '@typescript-eslint/typescript-estree@8.48.0(supports-color@7.2.0)(typescript@6.0.3)': + '@typescript-eslint/typescript-estree@8.70.0(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@typescript-eslint/project-service': 8.48.0(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@6.0.3) - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/project-service': 8.70.0(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/visitor-keys': 8.70.0 debug: 4.4.3(supports-color@7.2.0) - minimatch: 9.0.5 - semver: 7.7.3 - tinyglobby: 0.2.15 - ts-api-utils: 2.1.0(typescript@6.0.3) + minimatch: 10.2.6 + semver: 7.8.5 + tinyglobby: 0.2.17 + ts-api-utils: 2.5.0(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/typescript-estree': 8.48.0(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) typescript: 6.0.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.48.0': + '@typescript-eslint/visitor-keys@8.70.0': dependencies: - '@typescript-eslint/types': 8.48.0 - eslint-visitor-keys: 4.2.1 + '@typescript-eslint/types': 8.70.0 + eslint-visitor-keys: 5.0.1 '@typescript/vfs@1.6.4(supports-color@7.2.0)(typescript@5.4.5)': dependencies: @@ -5619,7 +4833,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@typespec/ts-http-runtime@0.3.8(supports-color@7.2.0)': + '@typespec/ts-http-runtime@0.3.9(supports-color@7.2.0)': dependencies: http-proxy-agent: 7.0.2(supports-color@7.2.0) https-proxy-agent: 7.0.6(supports-color@7.2.0) @@ -5627,71 +4841,83 @@ snapshots: transitivePeerDependencies: - supports-color - '@unrs/resolver-binding-android-arm-eabi@1.11.1': + '@unrs/resolver-binding-android-arm-eabi@1.12.2': optional: true - '@unrs/resolver-binding-android-arm64@1.11.1': + '@unrs/resolver-binding-android-arm64@1.12.2': optional: true - '@unrs/resolver-binding-darwin-arm64@1.11.1': + '@unrs/resolver-binding-darwin-arm64@1.12.2': optional: true - '@unrs/resolver-binding-darwin-x64@1.11.1': + '@unrs/resolver-binding-darwin-x64@1.12.2': optional: true - '@unrs/resolver-binding-freebsd-x64@1.11.1': + '@unrs/resolver-binding-freebsd-x64@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1': + '@unrs/resolver-binding-linux-arm-gnueabihf@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1': + '@unrs/resolver-binding-linux-arm-musleabihf@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm64-gnu@1.11.1': + '@unrs/resolver-binding-linux-arm64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-arm64-musl@1.11.1': + '@unrs/resolver-binding-linux-arm64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': + '@unrs/resolver-binding-linux-loong64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': + '@unrs/resolver-binding-linux-loong64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': + '@unrs/resolver-binding-linux-ppc64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': + '@unrs/resolver-binding-linux-riscv64-gnu@1.12.2': optional: true - '@unrs/resolver-binding-linux-x64-gnu@1.11.1': + '@unrs/resolver-binding-linux-riscv64-musl@1.12.2': optional: true - '@unrs/resolver-binding-linux-x64-musl@1.11.1': + '@unrs/resolver-binding-linux-s390x-gnu@1.12.2': optional: true - '@unrs/resolver-binding-wasm32-wasi@1.11.1': + '@unrs/resolver-binding-linux-x64-gnu@1.12.2': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.12.2': + optional: true + + '@unrs/resolver-binding-openharmony-arm64@1.12.2': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.12.2': dependencies: - '@napi-rs/wasm-runtime': 0.2.12 + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.2.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true - '@unrs/resolver-binding-win32-arm64-msvc@1.11.1': + '@unrs/resolver-binding-win32-arm64-msvc@1.12.2': optional: true - '@unrs/resolver-binding-win32-ia32-msvc@1.11.1': + '@unrs/resolver-binding-win32-ia32-msvc@1.12.2': optional: true - '@unrs/resolver-binding-win32-x64-msvc@1.11.1': + '@unrs/resolver-binding-win32-x64-msvc@1.12.2': optional: true - '@vitest/eslint-plugin@1.5.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': + '@vitest/eslint-plugin@1.6.27(@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3)': dependencies: - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) optionalDependencies: + '@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color @@ -5732,47 +4958,28 @@ snapshots: dependencies: event-target-shim: 5.0.1 - acorn-jsx@5.3.2(acorn@8.15.0): + acorn-jsx@5.3.2(acorn@8.18.0): dependencies: - acorn: 8.15.0 + acorn: 8.18.0 - acorn@8.15.0: {} + acorn@8.18.0: {} agent-base@7.1.4: {} - ajv-draft-04@1.0.0(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - - ajv-errors@3.0.0(ajv@8.17.1): - dependencies: - ajv: 8.17.1 - - ajv-formats@2.1.1(ajv@8.17.1): - optionalDependencies: - ajv: 8.17.1 - ajv-formats@3.0.1(@redocly/ajv@8.18.3): optionalDependencies: ajv: '@redocly/ajv@8.18.3' - ajv@6.12.6: + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ajv@8.17.1: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.0 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - ansi-regex@5.0.1: {} - ansi-regex@6.2.2: {} + ansi-regex@6.3.0: {} ansi-styles@4.3.0: dependencies: @@ -5790,7 +4997,7 @@ snapshots: graceful-fs: 4.2.11 is-stream: 2.0.1 lazystream: 1.0.1 - lodash: 4.17.21 + lodash: 4.18.1 normalize-path: 3.0.0 readable-stream: 4.7.0 @@ -5801,7 +5008,7 @@ snapshots: buffer-crc32: 1.0.0 readable-stream: 4.7.0 readdir-glob: 1.1.3 - tar-stream: 3.2.0 + tar-stream: 3.2.1 zip-stream: 6.0.1 transitivePeerDependencies: - bare-abort-controller @@ -5812,77 +5019,48 @@ snapshots: argparse@2.0.1: {} - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - array-timsort@1.0.3: {} - arraybuffer.prototype.slice@1.0.4: - dependencies: - array-buffer-byte-length: 1.0.2 - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.0 - 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: {} - async@3.2.6: {} - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - - b4a@1.8.1: {} + b4a@1.9.0: {} balanced-match@1.0.2: {} - bare-events@2.9.1: {} + balanced-match@4.0.4: {} + + bare-events@2.9.2: {} - bare-fs@4.8.0: + bare-fs@4.8.1: dependencies: - bare-events: 2.9.1 - bare-path: 3.1.1 - bare-stream: 2.13.3(bare-events@2.9.1) - bare-url: 2.5.1 + bare-events: 2.9.2 + bare-path: 3.1.2 + bare-stream: 2.13.4(bare-events@2.9.2) + bare-url: 2.5.4 fast-fifo: 1.3.2 transitivePeerDependencies: - bare-abort-controller - react-native-b4a - bare-path@3.1.1: {} + bare-path@3.1.2: {} - bare-stream@2.13.3(bare-events@2.9.1): + bare-stream@2.13.4(bare-events@2.9.2): dependencies: - b4a: 1.8.1 - streamx: 2.28.0 + b4a: 1.9.0 + streamx: 2.28.1 teex: 1.0.1 optionalDependencies: - bare-events: 2.9.1 + bare-events: 2.9.2 transitivePeerDependencies: - react-native-b4a - bare-url@2.5.1: + bare-url@2.5.4: dependencies: - bare-path: 3.1.1 + bare-path: 3.1.2 base64-js@1.5.1: {} - baseline-browser-mapping@2.8.31: {} + baseline-browser-mapping@2.11.25: {} before-after-hook@2.2.3: {} @@ -5891,32 +5069,32 @@ snapshots: buffers: 0.1.1 chainsaw: 0.1.0 - birecord@0.1.1: {} + birecord@0.1.2: {} boolbase@1.0.0: {} bottleneck@2.19.5: {} - brace-expansion@1.1.12: + brace-expansion@1.1.21: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - brace-expansion@2.0.2: + brace-expansion@2.1.7: dependencies: balanced-match: 1.0.2 - braces@3.0.3: + brace-expansion@5.0.12: dependencies: - fill-range: 7.1.1 + balanced-match: 4.0.4 - browserslist@4.28.0: + browserslist@4.29.0: dependencies: - baseline-browser-mapping: 2.8.31 - caniuse-lite: 1.0.30001757 - electron-to-chromium: 1.5.260 - node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.28.0) + baseline-browser-mapping: 2.11.25 + caniuse-lite: 1.0.30001810 + electron-to-chromium: 1.5.433 + node-releases: 2.0.56 + update-browserslist-db: 1.3.3(browserslist@4.29.0) buffer-crc32@1.0.0: {} @@ -5929,39 +5107,20 @@ snapshots: builtin-modules@3.3.0: {} - builtins@1.0.3: {} - - bun-types@1.3.3: + bun-types@1.4.2: dependencies: - '@types/node': 24.10.1 + '@types/node': 24.13.6 - bundle-require@5.1.0(esbuild@0.27.0): + bundle-require@5.1.0(esbuild@0.27.7): dependencies: - esbuild: 0.27.0 + esbuild: 0.27.7 load-tsconfig: 0.2.5 cac@6.7.14: {} - call-bind-apply-helpers@1.0.2: - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - - call-bind@1.0.8: - 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 - callsites@3.1.0: {} - caniuse-lite@1.0.30001757: {} + caniuse-lite@1.0.30001810: {} ccount@2.0.1: {} @@ -5988,23 +5147,17 @@ snapshots: dependencies: readdirp: 4.1.2 - ci-info@4.3.1: {} + ci-info@4.4.0: {} clean-regexp@1.0.0: dependencies: escape-string-regexp: 1.0.5 - clear-module@4.1.2: + clear-module@4.1.3: dependencies: parent-module: 2.0.0 resolve-from: 5.0.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 @@ -6019,19 +5172,23 @@ snapshots: colorette@1.4.0: {} - commander@14.0.2: {} + commander@14.0.3: {} commander@4.1.1: {} - comment-json@4.4.1: + comment-json@4.6.2: + dependencies: + array-timsort: 1.0.3 + esprima: 4.0.1 + + comment-json@5.0.0: dependencies: array-timsort: 1.0.3 - core-util-is: 1.0.3 esprima: 4.0.1 comment-parser@1.4.1: {} - commondir@1.0.1: {} + comment-parser@1.4.9: {} compare-versions@6.1.1: {} @@ -6047,13 +5204,13 @@ snapshots: confbox@0.1.8: {} - confbox@0.2.2: {} + confbox@0.3.1: {} consola@3.4.2: {} - core-js-compat@3.47.0: + core-js-compat@3.50.0: dependencies: - browserslist: 4.28.0 + browserslist: 4.29.0 core-util-is@1.0.3: {} @@ -6070,141 +5227,171 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - cspell-config-lib@9.3.2: + cspell-config-lib@10.3.3: + dependencies: + '@cspell/cspell-types': 10.3.3 + comment-json: 5.0.0 + smol-toml: 1.8.0 + yaml: 2.9.1 + + cspell-config-lib@9.8.0: + dependencies: + '@cspell/cspell-types': 9.8.0 + comment-json: 4.6.2 + smol-toml: 1.8.0 + yaml: 2.9.1 + + cspell-dictionary@10.3.3: + dependencies: + '@cspell/cspell-performance-monitor': 10.3.3 + '@cspell/cspell-pipe': 10.3.3 + '@cspell/cspell-types': 10.3.3 + cspell-trie-lib: 10.3.3(@cspell/cspell-types@10.3.3) + fast-equals: 6.0.4 + + cspell-dictionary@9.8.0: + dependencies: + '@cspell/cspell-performance-monitor': 9.8.0 + '@cspell/cspell-pipe': 9.8.0 + '@cspell/cspell-types': 9.8.0 + cspell-trie-lib: 9.8.0(@cspell/cspell-types@9.8.0) + fast-equals: 6.0.4 + + cspell-gitignore@9.8.0: dependencies: - '@cspell/cspell-types': 9.3.2 - comment-json: 4.4.1 - smol-toml: 1.5.2 - yaml: 2.8.2 + '@cspell/url': 9.8.0 + cspell-glob: 9.8.0 + cspell-io: 9.8.0 - cspell-dictionary@9.3.2: + cspell-glob@10.3.3: dependencies: - '@cspell/cspell-pipe': 9.3.2 - '@cspell/cspell-types': 9.3.2 - cspell-trie-lib: 9.3.2 - fast-equals: 5.3.3 + '@cspell/url': 10.3.3 + picomatch: 4.0.7 + + cspell-glob@9.8.0: + dependencies: + '@cspell/url': 9.8.0 + picomatch: 4.0.7 - cspell-gitignore@9.3.2: + cspell-grammar@10.3.3: dependencies: - '@cspell/url': 9.3.2 - cspell-glob: 9.3.2 - cspell-io: 9.3.2 + '@cspell/cspell-pipe': 10.3.3 + '@cspell/cspell-types': 10.3.3 - cspell-glob@9.3.2: + cspell-grammar@9.8.0: dependencies: - '@cspell/url': 9.3.2 - picomatch: 4.0.3 + '@cspell/cspell-pipe': 9.8.0 + '@cspell/cspell-types': 9.8.0 - cspell-grammar@9.3.2: + cspell-io@10.3.3: dependencies: - '@cspell/cspell-pipe': 9.3.2 - '@cspell/cspell-types': 9.3.2 + '@cspell/cspell-service-bus': 10.3.3 + '@cspell/url': 10.3.3 - cspell-io@9.3.2: + cspell-io@9.8.0: dependencies: - '@cspell/cspell-service-bus': 9.3.2 - '@cspell/url': 9.3.2 + '@cspell/cspell-service-bus': 9.8.0 + '@cspell/url': 9.8.0 - cspell-lib@9.3.2: + cspell-lib@10.3.3: dependencies: - '@cspell/cspell-bundled-dicts': 9.3.2 - '@cspell/cspell-pipe': 9.3.2 - '@cspell/cspell-resolver': 9.3.2 - '@cspell/cspell-types': 9.3.2 - '@cspell/dynamic-import': 9.3.2 - '@cspell/filetypes': 9.3.2 - '@cspell/strong-weak-map': 9.3.2 - '@cspell/url': 9.3.2 - clear-module: 4.1.2 - cspell-config-lib: 9.3.2 - cspell-dictionary: 9.3.2 - cspell-glob: 9.3.2 - cspell-grammar: 9.3.2 - cspell-io: 9.3.2 - cspell-trie-lib: 9.3.2 - env-paths: 3.0.0 + '@cspell/cspell-bundled-dicts': 10.3.3 + '@cspell/cspell-performance-monitor': 10.3.3 + '@cspell/cspell-pipe': 10.3.3 + '@cspell/cspell-resolver': 10.3.3 + '@cspell/cspell-types': 10.3.3 + '@cspell/dynamic-import': 10.3.3 + '@cspell/filetypes': 10.3.3 + '@cspell/rpc': 10.3.3 + '@cspell/strong-weak-map': 10.3.3 + '@cspell/url': 10.3.3 + cspell-config-lib: 10.3.3 + cspell-dictionary: 10.3.3 + cspell-glob: 10.3.3 + cspell-grammar: 10.3.3 + cspell-io: 10.3.3 + cspell-trie-lib: 10.3.3(@cspell/cspell-types@10.3.3) + env-paths: 4.0.0 + gensequence: 8.0.8 + import-fresh: 4.0.0 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.14 + vscode-uri: 3.2.0 + xdg-basedir: 5.1.0 + + cspell-lib@9.8.0: + dependencies: + '@cspell/cspell-bundled-dicts': 9.8.0 + '@cspell/cspell-performance-monitor': 9.8.0 + '@cspell/cspell-pipe': 9.8.0 + '@cspell/cspell-resolver': 9.8.0 + '@cspell/cspell-types': 9.8.0 + '@cspell/dynamic-import': 9.8.0 + '@cspell/filetypes': 9.8.0 + '@cspell/rpc': 9.8.0 + '@cspell/strong-weak-map': 9.8.0 + '@cspell/url': 9.8.0 + clear-module: 4.1.3 + cspell-config-lib: 9.8.0 + cspell-dictionary: 9.8.0 + cspell-glob: 9.8.0 + cspell-grammar: 9.8.0 + cspell-io: 9.8.0 + cspell-trie-lib: 9.8.0(@cspell/cspell-types@9.8.0) + env-paths: 4.0.0 gensequence: 8.0.8 import-fresh: 3.3.1 resolve-from: 5.0.0 - vscode-languageserver-textdocument: 1.0.12 - vscode-uri: 3.1.0 + vscode-languageserver-textdocument: 1.0.14 + vscode-uri: 3.2.0 xdg-basedir: 5.1.0 - cspell-trie-lib@9.3.2: + cspell-trie-lib@10.3.3(@cspell/cspell-types@10.3.3): dependencies: - '@cspell/cspell-pipe': 9.3.2 - '@cspell/cspell-types': 9.3.2 - gensequence: 8.0.8 + '@cspell/cspell-types': 10.3.3 + + cspell-trie-lib@9.8.0(@cspell/cspell-types@9.8.0): + dependencies: + '@cspell/cspell-types': 9.8.0 - cspell@9.3.2: + cspell@9.8.0: dependencies: - '@cspell/cspell-json-reporter': 9.3.2 - '@cspell/cspell-pipe': 9.3.2 - '@cspell/cspell-types': 9.3.2 - '@cspell/dynamic-import': 9.3.2 - '@cspell/url': 9.3.2 + '@cspell/cspell-json-reporter': 9.8.0 + '@cspell/cspell-performance-monitor': 9.8.0 + '@cspell/cspell-pipe': 9.8.0 + '@cspell/cspell-types': 9.8.0 + '@cspell/cspell-worker': 9.8.0 + '@cspell/dynamic-import': 9.8.0 + '@cspell/url': 9.8.0 + ansi-regex: 6.3.0 chalk: 5.6.2 chalk-template: 1.1.2 - commander: 14.0.2 - cspell-config-lib: 9.3.2 - cspell-dictionary: 9.3.2 - cspell-gitignore: 9.3.2 - cspell-glob: 9.3.2 - cspell-io: 9.3.2 - cspell-lib: 9.3.2 + commander: 14.0.3 + cspell-config-lib: 9.8.0 + cspell-dictionary: 9.8.0 + cspell-gitignore: 9.8.0 + cspell-glob: 9.8.0 + cspell-io: 9.8.0 + cspell-lib: 9.8.0 fast-json-stable-stringify: 2.1.0 - flatted: 3.3.3 - semver: 7.7.3 - tinyglobby: 0.2.15 + flatted: 3.4.4 + semver: 7.8.5 + tinyglobby: 0.2.17 cssesc@3.0.0: {} - 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 - debug@4.4.3(supports-color@7.2.0): dependencies: ms: 2.1.3 optionalDependencies: supports-color: 7.2.0 - decode-named-character-reference@1.2.0: + decode-named-character-reference@1.3.0: dependencies: character-entities: 2.0.2 deep-is@0.1.4: {} - 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: {} - deprecation@2.3.1: {} dequal@2.0.3: {} @@ -6215,179 +5402,88 @@ snapshots: diff-sequences@27.5.1: {} - dunder-proto@1.0.1: - dependencies: - call-bind-apply-helpers: 1.0.2 - es-errors: 1.3.0 - gopd: 1.2.0 - eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.260: {} + electron-to-chromium@1.5.433: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} - enhanced-resolve@5.18.3: + enhanced-resolve@5.25.1: dependencies: graceful-fs: 4.2.11 - tapable: 2.3.0 + tapable: 2.3.3 entities@4.5.0: {} - env-paths@3.0.0: {} + env-paths@4.0.0: + dependencies: + is-safe-filename: 0.1.1 error-ex@1.3.4: dependencies: is-arrayish: 0.2.1 - es-abstract@1.24.0: - dependencies: - array-buffer-byte-length: 1.0.2 - arraybuffer.prototype.slice: 1.0.4 - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - 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.1 - es-set-tostringtag: 2.1.0 - es-to-primitive: 1.3.0 - function.prototype.name: 1.1.8 - 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.2 - 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.3 - 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.10 - string.prototype.trimend: 1.0.9 - 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.7 - unbox-primitive: 1.1.0 - which-typed-array: 1.1.19 - - es-aggregate-error@1.0.14: - dependencies: - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.24.0 - 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.1: - 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.2 - - es-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - - esbuild@0.25.12: + esbuild@0.27.7: optionalDependencies: - '@esbuild/aix-ppc64': 0.25.12 - '@esbuild/android-arm': 0.25.12 - '@esbuild/android-arm64': 0.25.12 - '@esbuild/android-x64': 0.25.12 - '@esbuild/darwin-arm64': 0.25.12 - '@esbuild/darwin-x64': 0.25.12 - '@esbuild/freebsd-arm64': 0.25.12 - '@esbuild/freebsd-x64': 0.25.12 - '@esbuild/linux-arm': 0.25.12 - '@esbuild/linux-arm64': 0.25.12 - '@esbuild/linux-ia32': 0.25.12 - '@esbuild/linux-loong64': 0.25.12 - '@esbuild/linux-mips64el': 0.25.12 - '@esbuild/linux-ppc64': 0.25.12 - '@esbuild/linux-riscv64': 0.25.12 - '@esbuild/linux-s390x': 0.25.12 - '@esbuild/linux-x64': 0.25.12 - '@esbuild/netbsd-arm64': 0.25.12 - '@esbuild/netbsd-x64': 0.25.12 - '@esbuild/openbsd-arm64': 0.25.12 - '@esbuild/openbsd-x64': 0.25.12 - '@esbuild/openharmony-arm64': 0.25.12 - '@esbuild/sunos-x64': 0.25.12 - '@esbuild/win32-arm64': 0.25.12 - '@esbuild/win32-ia32': 0.25.12 - '@esbuild/win32-x64': 0.25.12 - - esbuild@0.27.0: + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 + + esbuild@0.28.2: optionalDependencies: - '@esbuild/aix-ppc64': 0.27.0 - '@esbuild/android-arm': 0.27.0 - '@esbuild/android-arm64': 0.27.0 - '@esbuild/android-x64': 0.27.0 - '@esbuild/darwin-arm64': 0.27.0 - '@esbuild/darwin-x64': 0.27.0 - '@esbuild/freebsd-arm64': 0.27.0 - '@esbuild/freebsd-x64': 0.27.0 - '@esbuild/linux-arm': 0.27.0 - '@esbuild/linux-arm64': 0.27.0 - '@esbuild/linux-ia32': 0.27.0 - '@esbuild/linux-loong64': 0.27.0 - '@esbuild/linux-mips64el': 0.27.0 - '@esbuild/linux-ppc64': 0.27.0 - '@esbuild/linux-riscv64': 0.27.0 - '@esbuild/linux-s390x': 0.27.0 - '@esbuild/linux-x64': 0.27.0 - '@esbuild/netbsd-arm64': 0.27.0 - '@esbuild/netbsd-x64': 0.27.0 - '@esbuild/openbsd-arm64': 0.27.0 - '@esbuild/openbsd-x64': 0.27.0 - '@esbuild/openharmony-arm64': 0.27.0 - '@esbuild/sunos-x64': 0.27.0 - '@esbuild/win32-arm64': 0.27.0 - '@esbuild/win32-ia32': 0.27.0 - '@esbuild/win32-x64': 0.27.0 + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 escalade@3.2.0: {} @@ -6397,20 +5493,20 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-compat-utils@0.5.1(eslint@9.39.1(supports-color@7.2.0)): + eslint-compat-utils@0.5.1(eslint@9.39.5(supports-color@7.2.0)): dependencies: - eslint: 9.39.1(supports-color@7.2.0) - semver: 7.7.3 + eslint: 9.39.5(supports-color@7.2.0) + semver: 7.8.5 - eslint-compat-utils@0.6.5(eslint@9.39.1(supports-color@7.2.0)): + eslint-compat-utils@0.6.5(eslint@9.39.5(supports-color@7.2.0)): dependencies: - eslint: 9.39.1(supports-color@7.2.0) - semver: 7.7.3 + eslint: 9.39.5(supports-color@7.2.0) + semver: 7.8.5 - eslint-config-flat-gitignore@1.0.1(eslint@9.39.1(supports-color@7.2.0)): + eslint-config-flat-gitignore@1.0.1(eslint@9.39.5(supports-color@7.2.0)): dependencies: - '@eslint/compat': 1.4.1(eslint@9.39.1(supports-color@7.2.0)) - eslint: 9.39.1(supports-color@7.2.0) + '@eslint/compat': 1.4.1(eslint@9.39.5(supports-color@7.2.0)) + eslint: 9.39.5(supports-color@7.2.0) eslint-flat-config-utils@0.4.0: dependencies: @@ -6420,242 +5516,253 @@ snapshots: dependencies: pathe: 2.0.3 - eslint-import-context@0.1.9(unrs-resolver@1.11.1): + eslint-import-context@0.1.9(unrs-resolver@1.12.2): dependencies: - get-tsconfig: 4.13.0 + get-tsconfig: 4.14.3 stable-hash-x: 0.2.0 optionalDependencies: - unrs-resolver: 1.11.1 + unrs-resolver: 1.12.2 - eslint-json-compat-utils@0.2.1(eslint@9.39.1(supports-color@7.2.0))(jsonc-eslint-parser@2.4.1): + eslint-json-compat-utils@0.2.3(eslint@9.39.5(supports-color@7.2.0))(jsonc-eslint-parser@2.4.2): dependencies: - eslint: 9.39.1(supports-color@7.2.0) - esquery: 1.6.0 - jsonc-eslint-parser: 2.4.1 + eslint: 9.39.5(supports-color@7.2.0) + esquery: 1.7.0 + jsonc-eslint-parser: 2.4.2 - eslint-merge-processors@1.0.0(eslint@9.39.1(supports-color@7.2.0)): + eslint-merge-processors@1.0.0(eslint@9.39.5(supports-color@7.2.0)): dependencies: - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) - eslint-plugin-antfu@2.7.0(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-antfu@2.7.0(eslint@9.39.5(supports-color@7.2.0)): dependencies: '@antfu/utils': 0.7.10 - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) - eslint-plugin-command@2.1.0(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-command@2.1.0(eslint@9.39.5(supports-color@7.2.0)): dependencies: '@es-joy/jsdoccomment': 0.50.2 - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) - eslint-plugin-es-x@7.8.0(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-es-x@7.8.0(eslint@9.39.5(supports-color@7.2.0)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) '@eslint-community/regexpp': 4.12.2 - eslint: 9.39.1(supports-color@7.2.0) - eslint-compat-utils: 0.5.1(eslint@9.39.1(supports-color@7.2.0)) + eslint: 9.39.5(supports-color@7.2.0) + eslint-compat-utils: 0.5.1(eslint@9.39.5(supports-color@7.2.0)) - eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0): + eslint-plugin-import-x@4.17.1(@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - '@typescript-eslint/types': 8.48.0 - comment-parser: 1.4.1 + '@typescript-eslint/types': 8.70.0 + comment-parser: 1.4.9 debug: 4.4.3(supports-color@7.2.0) - eslint: 9.39.1(supports-color@7.2.0) - eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + eslint: 9.39.5(supports-color@7.2.0) + eslint-import-context: 0.1.9(unrs-resolver@1.12.2) is-glob: 4.0.3 - minimatch: 10.1.1 - semver: 7.7.3 + minimatch: 10.2.6 + semver: 7.8.5 stable-hash-x: 0.2.0 - unrs-resolver: 1.11.1 + unrs-resolver: 1.12.2 optionalDependencies: - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) transitivePeerDependencies: - supports-color - eslint-plugin-jsdoc@50.8.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0): + eslint-plugin-jsdoc@50.8.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0): dependencies: '@es-joy/jsdoccomment': 0.50.2 are-docs-informative: 0.0.2 comment-parser: 1.4.1 debug: 4.4.3(supports-color@7.2.0) escape-string-regexp: 4.0.0 - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) espree: 10.4.0 - esquery: 1.6.0 + esquery: 1.7.0 parse-imports-exports: 0.2.4 - semver: 7.7.3 + semver: 7.8.5 spdx-expression-parse: 4.0.0 transitivePeerDependencies: - supports-color - eslint-plugin-jsonc@2.21.0(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-jsonc@2.21.1(eslint@9.39.5(supports-color@7.2.0)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) diff-sequences: 27.5.1 - eslint: 9.39.1(supports-color@7.2.0) - eslint-compat-utils: 0.6.5(eslint@9.39.1(supports-color@7.2.0)) - eslint-json-compat-utils: 0.2.1(eslint@9.39.1(supports-color@7.2.0))(jsonc-eslint-parser@2.4.1) + eslint: 9.39.5(supports-color@7.2.0) + eslint-compat-utils: 0.6.5(eslint@9.39.5(supports-color@7.2.0)) + eslint-json-compat-utils: 0.2.3(eslint@9.39.5(supports-color@7.2.0))(jsonc-eslint-parser@2.4.2) espree: 10.4.0 graphemer: 1.4.0 - jsonc-eslint-parser: 2.4.1 + jsonc-eslint-parser: 2.4.2 natural-compare: 1.4.0 - synckit: 0.11.11 + synckit: 0.11.13 transitivePeerDependencies: - '@eslint/json' - eslint-plugin-n@17.23.1(eslint@9.39.1(supports-color@7.2.0))(typescript@6.0.3): + eslint-plugin-n@17.24.0(eslint@9.39.5(supports-color@7.2.0))(typescript@6.0.3): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) - enhanced-resolve: 5.18.3 - eslint: 9.39.1(supports-color@7.2.0) - eslint-plugin-es-x: 7.8.0(eslint@9.39.1(supports-color@7.2.0)) - get-tsconfig: 4.13.0 + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) + enhanced-resolve: 5.25.1 + eslint: 9.39.5(supports-color@7.2.0) + eslint-plugin-es-x: 7.8.0(eslint@9.39.5(supports-color@7.2.0)) + get-tsconfig: 4.14.3 globals: 15.15.0 globrex: 0.1.2 ignore: 5.3.2 - semver: 7.7.3 + semver: 7.8.5 ts-declaration-location: 1.0.7(typescript@6.0.3) transitivePeerDependencies: - typescript - eslint-plugin-no-only-tests@3.3.0: {} + eslint-plugin-no-only-tests@3.4.0: {} - eslint-plugin-perfectionist@4.15.1(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + eslint-plugin-perfectionist@4.15.1(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): dependencies: - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) natural-orderby: 5.0.0 transitivePeerDependencies: - supports-color - typescript - eslint-plugin-react-dom@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + eslint-plugin-react-dom@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/core': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/var': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/core': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) compare-versions: 6.1.1 - eslint: 9.39.1(supports-color@7.2.0) - string-ts: 2.2.1 + eslint: 9.39.5(supports-color@7.2.0) ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-hooks-extra@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): - dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/core': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/var': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - string-ts: 2.2.1 + eslint-plugin-react-hooks-extra@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + dependencies: + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/core': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-naming-convention@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): - dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/core': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/var': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - string-ts: 2.2.1 + eslint-plugin-react-naming-convention@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + dependencies: + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/core': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + compare-versions: 6.1.1 + eslint: 9.39.5(supports-color@7.2.0) + string-ts: 2.3.1 ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-refresh@0.4.24(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-react-refresh@0.4.24(eslint@9.39.5(supports-color@7.2.0)): dependencies: - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) optional: true - eslint-plugin-react-web-api@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): - dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/core': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/var': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - string-ts: 2.2.1 + eslint-plugin-react-rsc@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + dependencies: + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + ts-pattern: 5.9.0 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-web-api@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + dependencies: + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/core': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + birecord: 0.1.2 + eslint: 9.39.5(supports-color@7.2.0) ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - eslint-plugin-react-x@2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): - dependencies: - '@eslint-react/ast': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/core': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/eff': 2.3.9 - '@eslint-react/shared': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@eslint-react/var': 2.3.9(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.48.0 - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - '@typescript-eslint/types': 8.48.0 - '@typescript-eslint/utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint-plugin-react-x@2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + dependencies: + '@eslint-react/ast': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/core': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/eff': 2.13.0 + '@eslint-react/shared': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@eslint-react/var': 2.13.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/scope-manager': 8.70.0 + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/types': 8.70.0 + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) compare-versions: 6.1.1 - eslint: 9.39.1(supports-color@7.2.0) - is-immutable-type: 5.0.1(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - string-ts: 2.2.1 - ts-api-utils: 2.1.0(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + is-immutable-type: 5.0.4(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + ts-api-utils: 2.5.0(typescript@6.0.3) ts-pattern: 5.9.0 typescript: 6.0.3 transitivePeerDependencies: - supports-color - eslint-plugin-regexp@2.10.0(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-regexp@2.10.0(eslint@9.39.5(supports-color@7.2.0)): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) '@eslint-community/regexpp': 4.12.2 - comment-parser: 1.4.1 - eslint: 9.39.1(supports-color@7.2.0) + comment-parser: 1.4.9 + eslint: 9.39.5(supports-color@7.2.0) jsdoc-type-pratt-parser: 4.8.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-toml@0.12.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0): + eslint-plugin-toml@0.12.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0): dependencies: debug: 4.4.3(supports-color@7.2.0) - eslint: 9.39.1(supports-color@7.2.0) - eslint-compat-utils: 0.6.5(eslint@9.39.1(supports-color@7.2.0)) - lodash: 4.17.21 - toml-eslint-parser: 0.10.0 + eslint: 9.39.5(supports-color@7.2.0) + eslint-compat-utils: 0.6.5(eslint@9.39.5(supports-color@7.2.0)) + lodash: 4.18.1 + toml-eslint-parser: 0.10.1 transitivePeerDependencies: - supports-color - eslint-plugin-unicorn@56.0.1(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-unicorn@56.0.1(eslint@9.39.5(supports-color@7.2.0)): dependencies: - '@babel/helper-validator-identifier': 7.28.5 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) - ci-info: 4.3.1 + '@babel/helper-validator-identifier': 7.29.7 + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) + ci-info: 4.4.0 clean-regexp: 1.0.0 - core-js-compat: 3.47.0 - eslint: 9.39.1(supports-color@7.2.0) - esquery: 1.6.0 + core-js-compat: 3.50.0 + eslint: 9.39.5(supports-color@7.2.0) + esquery: 1.7.0 globals: 15.15.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 @@ -6664,45 +5771,45 @@ snapshots: read-pkg-up: 7.0.1 regexp-tree: 0.1.27 regjsparser: 0.10.0 - semver: 7.7.3 + semver: 7.8.5 strip-indent: 3.0.0 - eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0)): + eslint-plugin-unused-imports@4.4.1(@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0)): dependencies: - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.48.0(@typescript-eslint/parser@8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + '@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3))(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint-plugin-vue@9.33.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0): + eslint-plugin-vue@9.33.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) - eslint: 9.39.1(supports-color@7.2.0) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) + eslint: 9.39.5(supports-color@7.2.0) globals: 13.24.0 natural-compare: 1.4.0 nth-check: 2.1.1 - postcss-selector-parser: 6.1.2 - semver: 7.7.3 - vue-eslint-parser: 9.4.3(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0) + postcss-selector-parser: 6.1.4 + semver: 7.8.5 + vue-eslint-parser: 9.4.3(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0) xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color - eslint-plugin-yml@1.19.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0): + eslint-plugin-yml@1.19.1(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0): dependencies: debug: 4.4.3(supports-color@7.2.0) diff-sequences: 27.5.1 escape-string-regexp: 4.0.0 - eslint: 9.39.1(supports-color@7.2.0) - eslint-compat-utils: 0.6.5(eslint@9.39.1(supports-color@7.2.0)) + eslint: 9.39.5(supports-color@7.2.0) + eslint-compat-utils: 0.6.5(eslint@9.39.5(supports-color@7.2.0)) natural-compare: 1.4.0 - yaml-eslint-parser: 1.3.1 + yaml-eslint-parser: 1.3.2 transitivePeerDependencies: - supports-color - eslint-processor-vue-blocks@1.0.0(@vue/compiler-sfc@3.5.25)(eslint@9.39.1(supports-color@7.2.0)): + eslint-processor-vue-blocks@1.0.0(@vue/compiler-sfc@3.5.25)(eslint@9.39.5(supports-color@7.2.0)): dependencies: '@vue/compiler-sfc': 3.5.25 - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) eslint-scope@7.2.2: dependencies: @@ -6718,21 +5825,23 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.39.1(supports-color@7.2.0): + eslint-visitor-keys@5.0.1: {} + + eslint@9.39.5(supports-color@7.2.0): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.39.1(supports-color@7.2.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@7.2.0)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.1(supports-color@7.2.0) + '@eslint/config-array': 0.21.2(supports-color@7.2.0) '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.1(supports-color@7.2.0) - '@eslint/js': 9.39.1 + '@eslint/eslintrc': 3.3.7(supports-color@7.2.0) + '@eslint/js': 9.39.5 '@eslint/plugin-kit': 0.4.1 - '@humanfs/node': 0.16.7 + '@humanfs/node': 0.16.8 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.3 - '@types/estree': 1.0.8 - ajv: 6.12.6 + '@types/estree': 1.0.9 + ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 debug: 4.4.3(supports-color@7.2.0) @@ -6740,7 +5849,7 @@ snapshots: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 - esquery: 1.6.0 + esquery: 1.7.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 @@ -6751,7 +5860,7 @@ snapshots: is-glob: 4.0.3 json-stable-stringify-without-jsonify: 1.0.1 lodash.merge: 4.6.2 - minimatch: 3.1.2 + minimatch: 3.1.5 natural-compare: 1.4.0 optionator: 0.9.4 transitivePeerDependencies: @@ -6759,23 +5868,23 @@ snapshots: esno@4.8.0: dependencies: - tsx: 4.20.6 + tsx: 4.23.15 espree@10.4.0: dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 4.2.1 espree@9.6.1: dependencies: - acorn: 8.15.0 - acorn-jsx: 5.3.2(acorn@8.15.0) + acorn: 8.18.0 + acorn-jsx: 5.3.2(acorn@8.18.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} - esquery@1.6.0: + esquery@1.7.0: dependencies: estraverse: 5.3.0 @@ -6785,8 +5894,6 @@ snapshots: estraverse@5.3.0: {} - estree-walker@1.0.1: {} - estree-walker@2.0.2: {} esutils@2.0.3: {} @@ -6795,70 +5902,52 @@ snapshots: events-universal@1.0.1: dependencies: - bare-events: 2.9.1 + bare-events: 2.9.2 transitivePeerDependencies: - bare-abort-controller events@3.3.0: {} - exsolve@1.0.8: {} + exsolve@1.1.1: {} fast-deep-equal@3.1.3: {} - fast-equals@5.3.3: {} + fast-equals@6.0.4: {} fast-fifo@1.3.2: {} - fast-glob@3.2.12: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} - fast-memoize@2.5.2: {} - - fast-uri@3.1.0: {} + fast-uri@3.1.8: {} - fast-xml-builder@1.3.0: + fast-xml-builder@1.3.1: dependencies: path-expression-matcher: 1.6.2 xml-naming: 0.3.0 - fast-xml-parser@5.10.1: + fast-xml-parser@5.11.1: dependencies: '@nodable/entities': 3.0.0 - fast-xml-builder: 1.3.0 - is-unsafe: 2.0.0 + fast-xml-builder: 1.3.1 + is-unsafe: 2.0.2 path-expression-matcher: 1.6.2 - strnum: 2.4.1 + strnum: 2.4.2 xml-naming: 0.3.0 - fastq@1.19.1: - dependencies: - reusify: 1.1.0 - fault@2.0.1: dependencies: format: 0.2.2 - fdir@6.5.0(picomatch@4.0.3): + fdir@6.5.0(picomatch@4.0.7): optionalDependencies: - picomatch: 4.0.3 + picomatch: 4.0.7 file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - find-up@4.1.0: dependencies: locate-path: 5.0.0 @@ -6872,19 +5961,15 @@ snapshots: fix-dts-default-cjs-exports@1.0.1: dependencies: magic-string: 0.30.21 - mlly: 1.8.0 - rollup: 4.53.3 + mlly: 1.8.2 + rollup: 4.63.4 flat-cache@4.0.1: dependencies: - flatted: 3.3.3 + flatted: 3.4.4 keyv: 4.5.4 - flatted@3.3.3: {} - - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 + flatted@3.4.4: {} foreground-child@3.3.1: dependencies: @@ -6893,75 +5978,21 @@ snapshots: format@0.2.2: {} - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.2.0 - universalify: 2.0.1 - - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true function-bind@1.1.2: {} - function.prototype.name@1.1.8: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - hasown: 2.0.2 - is-callable: 1.2.7 - - functions-have-names@1.2.3: {} - - generator-function@2.0.1: {} - gensequence@8.0.8: {} 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.1 - function-bind: 1.1.2 - get-proto: 1.0.1 - gopd: 1.2.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - math-intrinsics: 1.1.0 - - get-proto@1.0.1: - dependencies: - dunder-proto: 1.0.1 - es-object-atoms: 1.1.1 - - 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 - - get-tsconfig@4.13.0: + get-tsconfig@4.14.3: dependencies: resolve-pkg-maps: 1.0.0 github-slugger@2.0.0: {} - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - glob-parent@6.0.2: dependencies: is-glob: 4.0.3 @@ -6970,23 +6001,14 @@ snapshots: dependencies: foreground-child: 3.3.1 jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 + minimatch: 9.0.9 + minipass: 7.1.3 package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - global-directory@4.0.1: + global-directory@5.0.0: dependencies: - ini: 4.1.1 + ini: 6.0.0 globals@13.24.0: dependencies: @@ -6996,47 +6018,22 @@ snapshots: globals@15.15.0: {} - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - globrex@0.1.2: {} - gopd@1.2.0: {} - graceful-fs@4.2.11: {} graphemer@1.4.0: {} graphql@16.14.2: {} - 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.2: + hasown@2.0.4: dependencies: function-bind: 1.1.2 hosted-git-info@2.8.9: {} - hpagent@1.2.0: {} - http-proxy-agent@7.0.2(supports-color@7.2.0): dependencies: agent-base: 7.1.4 @@ -7047,7 +6044,7 @@ snapshots: httpexec@0.0.2: dependencies: srvx: 0.12.5 - tinyexec: 1.3.0 + tinyexec: 1.3.1 https-proxy-agent@7.0.6(supports-color@7.2.0): dependencies: @@ -7060,174 +6057,61 @@ snapshots: ignore@5.3.2: {} - ignore@7.0.5: {} - - immer@9.0.21: {} + ignore@7.0.9: {} import-fresh@3.3.1: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 + import-fresh@4.0.0: {} + import-meta-resolve@4.2.0: {} imurmurhash@0.1.4: {} indent-string@4.0.0: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} - ini@4.1.1: {} - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - is-array-buffer@3.0.5: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 + ini@6.0.0: {} is-arrayish@0.2.1: {} - 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-builtin-module@3.2.1: dependencies: builtin-modules: 3.3.0 - is-callable@1.2.7: {} - - is-core-module@2.16.1: + is-core-module@2.17.0: dependencies: - hasown: 2.0.2 - - 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 + hasown: 2.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-immutable-type@5.0.1(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): + is-immutable-type@5.0.4(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3): dependencies: - '@typescript-eslint/type-utils': 8.48.0(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) - eslint: 9.39.1(supports-color@7.2.0) - ts-api-utils: 2.1.0(typescript@6.0.3) + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0)(typescript@6.0.3) + eslint: 9.39.5(supports-color@7.2.0) + ts-api-utils: 2.5.0(typescript@6.0.3) ts-declaration-location: 1.0.7(typescript@6.0.3) typescript: 6.0.3 transitivePeerDependencies: - supports-color - 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.8 - - is-regex@1.2.1: - dependencies: - call-bound: 1.0.4 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - - is-set@2.0.3: {} - - is-shared-array-buffer@1.0.4: - dependencies: - call-bound: 1.0.4 + is-safe-filename@0.1.1: {} is-stream@2.0.1: {} - 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.19 - - is-unsafe@2.0.0: {} - - 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 + is-unsafe@2.0.2: {} isarray@1.0.0: {} - isarray@2.0.5: {} - isexe@2.0.0: {} jackspeak@3.4.3: @@ -7242,11 +6126,11 @@ snapshots: js-tokens@4.0.0: {} - js-yaml@4.1.1: + js-yaml@4.3.2: dependencies: argparse: 2.0.1 - js-yaml@5.4.1: + js-yaml@5.4.2: dependencies: argparse: 2.0.1 @@ -7254,8 +6138,6 @@ snapshots: jsdoc-type-pratt-parser@4.8.0: {} - jsep@1.4.0: {} - jsesc@0.5.0: {} jsesc@3.1.0: {} @@ -7266,7 +6148,7 @@ snapshots: json-schema-to-ts@2.7.2: dependencies: - '@babel/runtime': 7.28.4 + '@babel/runtime': 7.29.7 '@types/json-schema': 7.0.15 ts-algebra: 1.2.2 @@ -7276,28 +6158,12 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - jsonc-eslint-parser@2.4.1: + jsonc-eslint-parser@2.4.2: dependencies: - acorn: 8.15.0 + acorn: 8.18.0 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - semver: 7.7.3 - - jsonc-parser@2.2.1: {} - - jsonfile@6.2.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - - jsonpath-plus@10.3.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: {} + semver: 7.8.5 jssha@3.3.2: {} @@ -7311,8 +6177,6 @@ snapshots: dependencies: readable-stream: 2.3.8 - leven@3.1.0: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -7326,13 +6190,13 @@ snapshots: local-pkg@0.5.1: dependencies: - mlly: 1.8.0 + mlly: 1.8.2 pkg-types: 1.3.1 - local-pkg@1.1.2: + local-pkg@1.2.1: dependencies: - mlly: 1.8.0 - pkg-types: 2.3.0 + mlly: 1.8.2 + pkg-types: 2.3.3 quansync: 0.2.11 locate-path@5.0.0: @@ -7345,28 +6209,18 @@ snapshots: lodash.merge@4.6.2: {} - lodash.topath@4.5.2: {} - - lodash@4.17.21: {} + lodash@4.18.1: {} longest-streak@3.1.0: {} lru-cache@10.4.3: {} - magic-string@0.25.9: - dependencies: - sourcemap-codec: 1.4.8 - magic-string@0.30.21: dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - markdown-escape@2.0.0: {} + '@jridgewell/sourcemap-codec': 1.6.0 markdown-table@3.0.4: {} - math-intrinsics@1.1.0: {} - mdast-util-find-and-replace@3.0.2: dependencies: '@types/mdast': 4.0.4 @@ -7374,11 +6228,11 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 - mdast-util-from-markdown@2.0.2(supports-color@7.2.0): + mdast-util-from-markdown@2.0.3(supports-color@7.2.0): dependencies: '@types/mdast': 4.0.4 '@types/unist': 3.0.3 - decode-named-character-reference: 1.2.0 + decode-named-character-reference: 1.3.0 devlop: 1.1.0 mdast-util-to-string: 4.0.0 micromark: 4.0.2(supports-color@7.2.0) @@ -7396,7 +6250,7 @@ snapshots: '@types/mdast': 4.0.4 devlop: 1.1.0 escape-string-regexp: 5.0.0 - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-to-markdown: 2.1.2 micromark-extension-frontmatter: 2.0.0 transitivePeerDependencies: @@ -7414,7 +6268,7 @@ snapshots: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-to-markdown: 2.1.2 micromark-util-normalize-identifier: 2.0.1 transitivePeerDependencies: @@ -7423,7 +6277,7 @@ snapshots: mdast-util-gfm-strikethrough@2.0.0(supports-color@7.2.0): dependencies: '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -7433,7 +6287,7 @@ snapshots: '@types/mdast': 4.0.4 devlop: 1.1.0 markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color @@ -7442,14 +6296,14 @@ snapshots: dependencies: '@types/mdast': 4.0.4 devlop: 1.1.0 - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-to-markdown: 2.1.2 transitivePeerDependencies: - supports-color mdast-util-gfm@3.1.0(supports-color@7.2.0): dependencies: - mdast-util-from-markdown: 2.0.2(supports-color@7.2.0) + mdast-util-from-markdown: 2.0.3(supports-color@7.2.0) mdast-util-gfm-autolink-literal: 2.0.1 mdast-util-gfm-footnote: 2.1.0(supports-color@7.2.0) mdast-util-gfm-strikethrough: 2.0.0(supports-color@7.2.0) @@ -7473,18 +6327,16 @@ snapshots: mdast-util-to-string: 4.0.0 micromark-util-classify-character: 2.0.1 micromark-util-decode-string: 2.0.1 - unist-util-visit: 5.0.0 + unist-util-visit: 5.1.0 zwitch: 2.0.4 mdast-util-to-string@4.0.0: dependencies: '@types/mdast': 4.0.4 - merge2@1.4.1: {} - micromark-core-commonmark@2.0.3: dependencies: - decode-named-character-reference: 1.2.0 + decode-named-character-reference: 1.3.0 devlop: 1.1.0 micromark-factory-destination: 2.0.1 micromark-factory-label: 2.0.1 @@ -7535,7 +6387,7 @@ snapshots: micromark-util-symbol: 2.0.1 micromark-util-types: 2.0.2 - micromark-extension-gfm-table@2.1.1: + micromark-extension-gfm-table@2.1.2: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.1 @@ -7560,7 +6412,7 @@ snapshots: micromark-extension-gfm-autolink-literal: 2.1.0 micromark-extension-gfm-footnote: 2.1.0 micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.1 + micromark-extension-gfm-table: 2.1.2 micromark-extension-gfm-tagfilter: 2.0.0 micromark-extension-gfm-task-list-item: 2.1.0 micromark-util-combine-extensions: 2.0.1 @@ -7624,7 +6476,7 @@ snapshots: micromark-util-decode-string@2.0.1: dependencies: - decode-named-character-reference: 1.2.0 + decode-named-character-reference: 1.3.0 micromark-util-character: 2.1.1 micromark-util-decode-numeric-character-reference: 2.0.2 micromark-util-symbol: 2.0.1 @@ -7660,9 +6512,9 @@ snapshots: micromark@4.0.2(supports-color@7.2.0): dependencies: - '@types/debug': 4.1.12 + '@types/debug': 4.1.13 debug: 4.4.3(supports-color@7.2.0) - decode-named-character-reference: 1.2.0 + decode-named-character-reference: 1.3.0 devlop: 1.1.0 micromark-core-commonmark: 2.0.3 micromark-factory-space: 2.0.1 @@ -7680,43 +6532,38 @@ snapshots: transitivePeerDependencies: - supports-color - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - min-indent@1.0.1: {} - minimatch@10.1.1: + minimatch@10.2.6: dependencies: - '@isaacs/brace-expansion': 5.0.0 + brace-expansion: 5.0.12 - minimatch@3.1.2: + minimatch@3.1.5: dependencies: - brace-expansion: 1.1.12 + brace-expansion: 1.1.21 - minimatch@5.1.6: + minimatch@5.1.9: dependencies: - brace-expansion: 2.0.2 + brace-expansion: 2.1.7 - minimatch@9.0.5: + minimatch@9.0.9: dependencies: - brace-expansion: 2.0.2 + brace-expansion: 2.1.7 minimist@1.2.8: {} - minipass@7.1.2: {} + minipass@7.1.3: {} mkdirp@0.5.6: dependencies: minimist: 1.2.8 - mlly@1.8.0: + mlly@1.8.2: dependencies: - acorn: 8.15.0 + acorn: 8.18.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.6.1 + ufo: 1.6.4 ms@2.1.3: {} @@ -7734,31 +6581,12 @@ snapshots: natural-orderby@5.0.0: {} - 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.3.0 - lodash.topath: 4.5.2 - - node-fetch@2.7.0: - dependencies: - whatwg-url: 5.0.0 - - node-releases@2.0.27: {} - - node-sarif-builder@2.0.3: - dependencies: - '@types/sarif': 2.1.7 - fs-extra: 10.1.0 + node-releases@2.0.56: {} normalize-package-data@2.5.0: dependencies: hosted-git-info: 2.8.9 - resolve: 1.22.11 + resolve: 1.22.12 semver: 5.7.2 validate-npm-package-license: 3.0.4 @@ -7770,19 +6598,6 @@ snapshots: object-assign@4.1.1: {} - object-inspect@1.13.4: {} - - object-keys@1.1.1: {} - - object.assign@4.1.7: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - has-symbols: 1.1.0 - object-keys: 1.1.1 - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -7796,12 +6611,6 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 - own-keys@1.0.1: - dependencies: - get-intrinsic: 1.3.0 - object-keys: 1.1.1 - safe-push-apply: 1.0.0 - p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -7822,7 +6631,7 @@ snapshots: package-json-from-dist@1.0.1: {} - package-manager-detector@1.5.0: {} + package-manager-detector@1.8.0: {} parent-module@1.0.1: dependencies: @@ -7840,7 +6649,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.7 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -7851,8 +6660,6 @@ snapshots: path-expression-matcher@1.6.2: {} - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-parse@1.0.7: {} @@ -7860,7 +6667,7 @@ snapshots: path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 - minipass: 7.1.2 + minipass: 7.1.3 pathe@1.1.2: {} @@ -7868,10 +6675,6 @@ snapshots: picocolors@1.1.1: {} - picomatch@2.3.1: {} - - picomatch@4.0.3: {} - picomatch@4.0.7: {} pirates@4.0.7: {} @@ -7879,30 +6682,26 @@ snapshots: pkg-types@1.3.1: dependencies: confbox: 0.1.8 - mlly: 1.8.0 + mlly: 1.8.2 pathe: 2.0.3 - pkg-types@2.3.0: + pkg-types@2.3.3: dependencies: - confbox: 0.2.2 - exsolve: 1.0.8 + confbox: 0.3.1 + exsolve: 1.1.1 pathe: 2.0.3 pluralize@8.0.0: {} - pony-cause@1.1.1: {} - - possible-typed-array-names@1.1.0: {} - - postcss-load-config@6.0.1(postcss@8.5.6)(tsx@4.20.6)(yaml@2.8.2): + postcss-load-config@6.0.1(postcss@8.5.6)(tsx@4.23.15)(yaml@2.9.1): dependencies: lilconfig: 3.1.3 optionalDependencies: postcss: 8.5.6 - tsx: 4.20.6 - yaml: 2.8.2 + tsx: 4.23.15 + yaml: 2.9.1 - postcss-selector-parser@6.1.2: + postcss-selector-parser@6.1.4: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 @@ -7915,8 +6714,6 @@ snapshots: prelude-ls@1.2.1: {} - printable-characters@1.0.42: {} - process-nextick-args@2.0.1: {} process@0.11.10: {} @@ -7925,8 +6722,6 @@ snapshots: quansync@0.2.11: {} - queue-microtask@1.2.3: {} - read-pkg-up@7.0.1: dependencies: find-up: 4.1.0 @@ -7960,7 +6755,7 @@ snapshots: readdir-glob@1.1.3: dependencies: - minimatch: 5.1.6 + minimatch: 5.1.9 readdirp@4.1.2: {} @@ -7968,17 +6763,6 @@ snapshots: dependencies: '@eslint-community/regexpp': 4.12.2 - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.0 - es-errors: 1.3.0 - es-object-atoms: 1.1.1 - get-intrinsic: 1.3.0 - get-proto: 1.0.1 - which-builtin-type: 1.2.1 - regexp-ast-analysis@0.7.1: dependencies: '@eslint-community/regexpp': 4.12.2 @@ -7986,15 +6770,6 @@ snapshots: regexp-tree@0.1.27: {} - regexp.prototype.flags@1.5.4: - dependencies: - call-bind: 1.0.8 - 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 - regjsparser@0.10.0: dependencies: jsesc: 0.5.0 @@ -8003,83 +6778,55 @@ snapshots: require-from-string@2.0.2: {} - reserved@0.1.2: {} - resolve-from@4.0.0: {} resolve-from@5.0.0: {} resolve-pkg-maps@1.0.0: {} - resolve@1.22.11: + resolve@1.22.12: dependencies: - is-core-module: 2.16.1 + es-errors: 1.3.0 + is-core-module: 2.17.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - reusify@1.1.0: {} - - rollup@2.79.2: - optionalDependencies: - fsevents: 2.3.3 - - rollup@4.53.3: + rollup@4.63.4: dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.53.3 - '@rollup/rollup-android-arm64': 4.53.3 - '@rollup/rollup-darwin-arm64': 4.53.3 - '@rollup/rollup-darwin-x64': 4.53.3 - '@rollup/rollup-freebsd-arm64': 4.53.3 - '@rollup/rollup-freebsd-x64': 4.53.3 - '@rollup/rollup-linux-arm-gnueabihf': 4.53.3 - '@rollup/rollup-linux-arm-musleabihf': 4.53.3 - '@rollup/rollup-linux-arm64-gnu': 4.53.3 - '@rollup/rollup-linux-arm64-musl': 4.53.3 - '@rollup/rollup-linux-loong64-gnu': 4.53.3 - '@rollup/rollup-linux-ppc64-gnu': 4.53.3 - '@rollup/rollup-linux-riscv64-gnu': 4.53.3 - '@rollup/rollup-linux-riscv64-musl': 4.53.3 - '@rollup/rollup-linux-s390x-gnu': 4.53.3 - '@rollup/rollup-linux-x64-gnu': 4.53.3 - '@rollup/rollup-linux-x64-musl': 4.53.3 - '@rollup/rollup-openharmony-arm64': 4.53.3 - '@rollup/rollup-win32-arm64-msvc': 4.53.3 - '@rollup/rollup-win32-ia32-msvc': 4.53.3 - '@rollup/rollup-win32-x64-gnu': 4.53.3 - '@rollup/rollup-win32-x64-msvc': 4.53.3 + '@napi-rs/lzma-linux-x64-gnu': 1.5.1 + '@rollup/rollup-android-arm-eabi': 4.63.4 + '@rollup/rollup-android-arm64': 4.63.4 + '@rollup/rollup-darwin-arm64': 4.63.4 + '@rollup/rollup-darwin-x64': 4.63.4 + '@rollup/rollup-freebsd-arm64': 4.63.4 + '@rollup/rollup-freebsd-x64': 4.63.4 + '@rollup/rollup-linux-arm-gnueabihf': 4.63.4 + '@rollup/rollup-linux-arm-musleabihf': 4.63.4 + '@rollup/rollup-linux-arm64-gnu': 4.63.4 + '@rollup/rollup-linux-arm64-musl': 4.63.4 + '@rollup/rollup-linux-loong64-gnu': 4.63.4 + '@rollup/rollup-linux-loong64-musl': 4.63.4 + '@rollup/rollup-linux-ppc64-gnu': 4.63.4 + '@rollup/rollup-linux-ppc64-musl': 4.63.4 + '@rollup/rollup-linux-riscv64-gnu': 4.63.4 + '@rollup/rollup-linux-riscv64-musl': 4.63.4 + '@rollup/rollup-linux-s390x-gnu': 4.63.4 + '@rollup/rollup-linux-x64-gnu': 4.63.4 + '@rollup/rollup-linux-x64-musl': 4.63.4 + '@rollup/rollup-openbsd-x64': 4.63.4 + '@rollup/rollup-openharmony-arm64': 4.63.4 + '@rollup/rollup-win32-arm64-msvc': 4.63.4 + '@rollup/rollup-win32-ia32-msvc': 4.63.4 + '@rollup/rollup-win32-x64-gnu': 4.63.4 + '@rollup/rollup-win32-x64-msvc': 4.63.4 fsevents: 2.3.3 - run-parallel@1.2.0: - dependencies: - queue-microtask: 1.2.3 - - safe-array-concat@1.1.3: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - get-intrinsic: 1.3.0 - has-symbols: 1.1.0 - isarray: 2.0.5 - safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} - 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: {} - scslre@0.3.0: dependencies: '@eslint-community/regexpp': 4.12.2 @@ -8088,29 +6835,7 @@ snapshots: semver@5.7.2: {} - semver@7.7.3: {} - - 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.1 + semver@7.8.5: {} shebang-command@2.0.0: dependencies: @@ -8118,86 +6843,40 @@ snapshots: shebang-regex@3.0.0: {} - side-channel-list@1.0.0: - 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.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - signal-exit@4.1.0: {} - simple-eval@1.0.1: - dependencies: - jsep: 1.4.0 - sisteransi@1.0.5: {} - smol-toml@1.5.2: {} + smol-toml@1.8.0: {} source-map-js@1.2.1: {} - source-map@0.6.1: {} - source-map@0.7.6: {} - sourcemap-codec@1.4.8: {} - spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.24 spdx-exceptions@2.5.0: {} spdx-expression-parse@3.0.1: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.24 spdx-expression-parse@4.0.0: dependencies: spdx-exceptions: 2.5.0 - spdx-license-ids: 3.0.22 + spdx-license-ids: 3.0.24 - spdx-license-ids@3.0.22: {} + spdx-license-ids@3.0.24: {} srvx@0.12.5: {} stable-hash-x@0.2.0: {} - stacktracey@2.1.8: - 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 - - streamx@2.28.0: + streamx@2.28.1: dependencies: events-universal: 1.0.1 fast-fifo: 1.3.2 @@ -8206,7 +6885,7 @@ snapshots: - bare-abort-controller - react-native-b4a - string-ts@2.2.1: {} + string-ts@2.3.1: {} string-width@4.2.3: dependencies: @@ -8218,30 +6897,7 @@ snapshots: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 - strip-ansi: 7.1.2 - - string.prototype.trim@1.2.10: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-data-property: 1.1.4 - define-properties: 1.2.1 - es-abstract: 1.24.0 - es-object-atoms: 1.1.1 - has-property-descriptors: 1.0.2 - - string.prototype.trimend@1.0.9: - dependencies: - call-bind: 1.0.8 - call-bound: 1.0.4 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 - - string.prototype.trimstart@1.0.8: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-object-atoms: 1.1.1 + strip-ansi: 7.2.0 string_decoder@1.1.1: dependencies: @@ -8255,9 +6911,9 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.2: + strip-ansi@7.2.0: dependencies: - ansi-regex: 6.2.2 + ansi-regex: 6.3.0 strip-indent@3.0.0: dependencies: @@ -8265,7 +6921,7 @@ snapshots: strip-json-comments@3.1.1: {} - strnum@2.4.1: + strnum@2.4.2: dependencies: anynum: 1.0.1 @@ -8276,7 +6932,7 @@ snapshots: lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.7 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 ts-interface-checker: 0.1.13 supports-color@7.2.0: @@ -8285,18 +6941,18 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - synckit@0.11.11: + synckit@0.11.13: dependencies: - '@pkgr/core': 0.2.9 + '@pkgr/core': 0.3.6 - tapable@2.3.0: {} + tapable@2.3.3: {} - tar-stream@3.2.0: + tar-stream@3.2.1: dependencies: - b4a: 1.8.1 - bare-fs: 4.8.0 + b4a: 1.9.0 + bare-fs: 4.8.1 fast-fifo: 1.3.2 - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - bare-buffer @@ -8304,19 +6960,17 @@ snapshots: teex@1.0.1: dependencies: - streamx: 2.28.0 + streamx: 2.28.1 transitivePeerDependencies: - bare-abort-controller - react-native-b4a text-decoder@1.2.7: dependencies: - b4a: 1.8.1 + b4a: 1.9.0 transitivePeerDependencies: - react-native-b4a - text-table@0.2.0: {} - thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -8327,20 +6981,14 @@ snapshots: tinyexec@0.3.2: {} - tinyexec@1.0.2: {} - - tinyexec@1.3.0: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 + tinyexec@1.3.1: {} - to-regex-range@5.0.1: + tinyglobby@0.2.17: dependencies: - is-number: 7.0.0 + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 - toml-eslint-parser@0.10.0: + toml-eslint-parser@0.10.1: dependencies: eslint-visitor-keys: 3.4.3 @@ -8348,49 +6996,45 @@ snapshots: dependencies: jssha: 3.3.2 - tr46@0.0.3: {} - traverse@0.3.9: {} tree-kill@1.2.2: {} ts-algebra@1.2.2: {} - ts-api-utils@2.1.0(typescript@6.0.3): + ts-api-utils@2.5.0(typescript@6.0.3): dependencies: typescript: 6.0.3 ts-declaration-location@1.0.7(typescript@6.0.3): dependencies: - picomatch: 4.0.3 + picomatch: 4.0.7 typescript: 6.0.3 ts-interface-checker@0.1.13: {} ts-pattern@5.9.0: {} - tslib@1.14.1: {} - tslib@2.8.1: {} - tsup@8.5.1(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.20.6)(typescript@6.0.3)(yaml@2.8.2): + tsup@8.5.1(postcss@8.5.6)(supports-color@7.2.0)(tsx@4.23.15)(typescript@6.0.3)(yaml@2.9.1): dependencies: - bundle-require: 5.1.0(esbuild@0.27.0) + bundle-require: 5.1.0(esbuild@0.27.7) cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.2 debug: 4.4.3(supports-color@7.2.0) - esbuild: 0.27.0 + esbuild: 0.27.7 fix-dts-default-cjs-exports: 1.0.1 joycon: 3.1.1 picocolors: 1.1.1 - postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@4.20.6)(yaml@2.8.2) + postcss-load-config: 6.0.1(postcss@8.5.6)(tsx@4.23.15)(yaml@2.9.1) resolve-from: 5.0.0 - rollup: 4.53.3 + rollup: 4.63.4 source-map: 0.7.6 sucrase: 3.35.1 tinyexec: 0.3.2 - tinyglobby: 0.2.15 + tinyglobby: 0.2.17 tree-kill: 1.2.2 optionalDependencies: postcss: 8.5.6 @@ -8401,10 +7045,9 @@ snapshots: - tsx - yaml - tsx@4.20.6: + tsx@4.23.15: dependencies: - esbuild: 0.25.12 - get-tsconfig: 4.13.0 + esbuild: 0.28.2 optionalDependencies: fsevents: 2.3.3 @@ -8420,61 +7063,21 @@ snapshots: type-fest@0.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.8 - 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.8 - 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.7: - dependencies: - call-bind: 1.0.8 - 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 - typescript@3.9.10: {} typescript@5.4.5: {} typescript@6.0.3: {} - ufo@1.6.1: {} + ufo@1.6.4: {} - 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.16.0: {} + undici-types@7.18.2: {} undici@5.29.0: dependencies: '@fastify/busboy': 2.1.1 - undici@6.28.0: {} + undici@6.28.1: {} unist-util-is@6.0.1: dependencies: @@ -8489,7 +7092,7 @@ snapshots: '@types/unist': 3.0.3 unist-util-is: 6.0.1 - unist-util-visit@5.0.0: + unist-util-visit@5.1.0: dependencies: '@types/unist': 3.0.3 unist-util-is: 6.0.1 @@ -8497,40 +7100,41 @@ snapshots: universal-user-agent@6.0.1: {} - universalify@2.0.1: {} - - unrs-resolver@1.11.1: + unrs-resolver@1.12.2: dependencies: napi-postinstall: 0.3.4 optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.11.1 - '@unrs/resolver-binding-android-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-arm64': 1.11.1 - '@unrs/resolver-binding-darwin-x64': 1.11.1 - '@unrs/resolver-binding-freebsd-x64': 1.11.1 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1 - '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-arm64-musl': 1.11.1 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1 - '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-gnu': 1.11.1 - '@unrs/resolver-binding-linux-x64-musl': 1.11.1 - '@unrs/resolver-binding-wasm32-wasi': 1.11.1 - '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1 - '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 - '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 + '@unrs/resolver-binding-android-arm-eabi': 1.12.2 + '@unrs/resolver-binding-android-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-arm64': 1.12.2 + '@unrs/resolver-binding-darwin-x64': 1.12.2 + '@unrs/resolver-binding-freebsd-x64': 1.12.2 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.12.2 + '@unrs/resolver-binding-linux-arm64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-arm64-musl': 1.12.2 + '@unrs/resolver-binding-linux-loong64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-loong64-musl': 1.12.2 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-riscv64-musl': 1.12.2 + '@unrs/resolver-binding-linux-s390x-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-gnu': 1.12.2 + '@unrs/resolver-binding-linux-x64-musl': 1.12.2 + '@unrs/resolver-binding-openharmony-arm64': 1.12.2 + '@unrs/resolver-binding-wasm32-wasi': 1.12.2 + '@unrs/resolver-binding-win32-arm64-msvc': 1.12.2 + '@unrs/resolver-binding-win32-ia32-msvc': 1.12.2 + '@unrs/resolver-binding-win32-x64-msvc': 1.12.2 unzip-stream@0.3.4: dependencies: binary: 0.3.0 mkdirp: 0.5.6 - update-browserslist-db@1.1.4(browserslist@4.28.0): + update-browserslist-db@1.3.3(browserslist@4.29.0): dependencies: - browserslist: 4.28.0 + browserslist: 4.29.0 escalade: 3.2.0 picocolors: 1.1.1 @@ -8538,86 +7142,30 @@ snapshots: dependencies: punycode: 2.3.1 - urijs@1.19.11: {} - util-deprecate@1.0.2: {} - utility-types@3.11.0: {} - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 - validate-npm-package-name@3.0.0: - dependencies: - builtins: 1.0.3 + vscode-languageserver-textdocument@1.0.14: {} - vscode-languageserver-textdocument@1.0.12: {} + vscode-uri@3.2.0: {} - vscode-uri@3.1.0: {} - - vue-eslint-parser@9.4.3(eslint@9.39.1(supports-color@7.2.0))(supports-color@7.2.0): + vue-eslint-parser@9.4.3(eslint@9.39.5(supports-color@7.2.0))(supports-color@7.2.0): dependencies: debug: 4.4.3(supports-color@7.2.0) - eslint: 9.39.1(supports-color@7.2.0) + eslint: 9.39.5(supports-color@7.2.0) eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 - esquery: 1.6.0 - lodash: 4.17.21 - semver: 7.7.3 + esquery: 1.7.0 + lodash: 4.18.1 + semver: 7.8.5 transitivePeerDependencies: - supports-color - 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.1.8 - 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.19 - - 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.19: - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.8 - call-bound: 1.0.4 - for-each: 0.3.5 - get-proto: 1.0.1 - gopd: 1.2.0 - has-tostringtag: 1.0.2 - which@2.0.2: dependencies: isexe: 2.0.0 @@ -8634,7 +7182,7 @@ snapshots: dependencies: ansi-styles: 6.2.3 string-width: 5.1.2 - strip-ansi: 7.1.2 + strip-ansi: 7.2.0 wrappy@1.0.2: {} @@ -8648,16 +7196,16 @@ snapshots: yaml-ast-parser@0.0.43: {} - yaml-eslint-parser@1.3.1: + yaml-eslint-parser@1.3.2: dependencies: eslint-visitor-keys: 3.4.3 - yaml: 2.8.2 + yaml: 2.9.1 - yaml@2.8.2: {} + yaml@2.9.1: {} yargs-parser@21.1.1: {} - yargs@17.7.2: + yargs@17.7.3: dependencies: cliui: 8.0.1 escalade: 3.2.0 @@ -8675,6 +7223,6 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 - zod@4.1.13: {} + zod@4.6.5: {} zwitch@2.0.4: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a8c8a10e..e1cf67ad 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,6 @@ packages: - . + - packages/* allowBuilds: core-js: true esbuild: true diff --git a/redocly.yaml b/redocly.yaml index df94f3b8..18a9523a 100644 --- a/redocly.yaml +++ b/redocly.yaml @@ -4,87 +4,192 @@ extends: plugins: - ./redocly/plugin.ts + - ./packages/redocly-plugin-downlevel/src/index.ts -preprocessors: - vrchat/x-if: on +rules: + array-parameter-serialization: warn + component-name-unique: warn + path-not-include-query: warn + +oas3_0Rules: + vrchat/no-empty-description: warn + vrchat/no-nested-object: warn + vrchat/operation-id-convention: warn + vrchat/schema-title: warn + +oas3_1Rules: + vrchat/no-empty-description: warn + vrchat/no-nested-object: warn + vrchat/no-schema-example: warn + vrchat/no-single-value-enum: warn + vrchat/operation-id-convention: warn + vrchat/prefer-unknown: warn + vrchat/schema-title: warn + +oas3_2Rules: + vrchat/no-empty-description: warn + vrchat/no-nested-object: warn + vrchat/no-schema-example: warn + vrchat/no-single-value-enum: warn + vrchat/operation-id-convention: warn + vrchat/prefer-unknown: warn + vrchat/schema-title: warn + +decorators: + info-description-override: + filePath: openapi/description.md + vrchat/info-extension-override: + name: x-agents + filePath: openapi/agents.md + vrchat/version-override: on + vrchat/x-links: + releases: https://github.com/vrchatapi/specification/releases + formats: [json, yaml] + versions: ["3.2", "3.1", "3.0"] + documents: + openapi: openapi-{version} + openapi-internal: openapi-internal+{version} apis: - legacy: + openapi.json: root: openapi/openapi.yaml - output: dist/openapi-legacy.json + output: dist/openapi.json decorators: remove-x-internal: on + vrchat/remove-x-deleted: on - modern: + openapi-internal.json: root: openapi/openapi.yaml - output: dist/openapi.json + output: dist/openapi-internal.json + decorators: + vrchat/remove-x-deleted: on + + openapi.yaml: + root: openapi/openapi.yaml + output: dist/openapi.yaml decorators: remove-x-internal: on - preprocessors: - vrchat/x-if: - defines: - - jsonschema + vrchat/remove-x-deleted: on - legacy-internal: + openapi-internal.yaml: root: openapi/openapi.yaml - output: dist/openapi-internal+legacy.json - preprocessors: - vrchat/x-if: - defines: - - internal + output: dist/openapi-internal.yaml + decorators: + vrchat/remove-x-deleted: on - modern-internal: + openapi-3.2.json: root: openapi/openapi.yaml - output: dist/openapi-internal.json - preprocessors: - vrchat/x-if: - defines: - - jsonschema - - internal + output: dist/openapi-3.2.json + decorators: + remove-x-internal: on + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.2" - legacy-yaml: + "openapi-internal+3.2.json": root: openapi/openapi.yaml - output: dist/openapi-legacy.yaml + output: dist/openapi-internal+3.2.json + decorators: + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.2" + + openapi-3.2.yaml: + root: openapi/openapi.yaml + output: dist/openapi-3.2.yaml decorators: remove-x-internal: on + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.2" - modern-yaml: + "openapi-internal+3.2.yaml": root: openapi/openapi.yaml - output: dist/openapi.yaml + output: dist/openapi-internal+3.2.yaml + decorators: + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.2" + + openapi-3.1.json: + root: openapi/openapi.yaml + output: dist/openapi-3.1.json decorators: remove-x-internal: on - preprocessors: - vrchat/x-if: - defines: - - jsonschema + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.1" - legacy-internal-yaml: + "openapi-internal+3.1.json": root: openapi/openapi.yaml - output: dist/openapi-internal+legacy.yaml - preprocessors: - vrchat/x-if: - defines: - - internal + output: dist/openapi-internal+3.1.json + decorators: + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.1" - modern-internal-yaml: + openapi-3.1.yaml: root: openapi/openapi.yaml - output: dist/openapi-internal.yaml - preprocessors: - vrchat/x-if: - defines: - - jsonschema - - internal + output: dist/openapi-3.1.yaml + decorators: + remove-x-internal: on + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.1" + + "openapi-internal+3.1.yaml": + root: openapi/openapi.yaml + output: dist/openapi-internal+3.1.yaml + decorators: + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.1" + + openapi-3.0.json: + root: openapi/openapi.yaml + output: dist/openapi-3.0.json + decorators: + remove-x-internal: on + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.0" + loosenUnions: true + + "openapi-internal+3.0.json": + root: openapi/openapi.yaml + output: dist/openapi-internal+3.0.json + decorators: + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.0" + loosenUnions: true + + openapi-3.0.yaml: + root: openapi/openapi.yaml + output: dist/openapi-3.0.yaml + decorators: + remove-x-internal: on + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.0" + loosenUnions: true + + "openapi-internal+3.0.yaml": + root: openapi/openapi.yaml + output: dist/openapi-internal+3.0.yaml + decorators: + vrchat/remove-x-deleted: on + downlevel/openapi: + version: "3.0" + loosenUnions: true # Not published. The bundle the workflows run against, and what `pnpm # test:drift` compares the captures to — it cannot see undocumented response # fields while the schemas stay open. - test: + openapi-test.yaml: root: openapi/openapi.yaml output: dist/openapi-test.yaml - preprocessors: - vrchat/x-if: - defines: - - jsonschema - - internal decorators: vrchat/close-schemas: on + vrchat/remove-discriminators: on + vrchat/x-links: off diff --git a/redocly/decorators/close-schemas.ts b/redocly/decorators/close-schemas.ts new file mode 100644 index 00000000..47e23ec1 --- /dev/null +++ b/redocly/decorators/close-schemas.ts @@ -0,0 +1,68 @@ +import type { Oas3Decorator } from "@redocly/openapi-core"; + +/** + * Closes every object schema that lists properties, so a response carrying a + * field the description does not mention fails validation. + * + * Only for the test bundle. An open schema legally permits any extra property, + * which is correct for consumers but makes undocumented fields undetectable. + * + * A schema another reaches through `allOf` is left open: the composing schema + * closes over its properties, and closing the part as well would reject every + * property the composing schema adds. Where such a schema is also used directly, + * that reference is closed instead. + * + * Schemas without `properties` are left alone — those are deliberately free-form + * (`defaultContentSettings`, `appleDetails`) and closing them would report their + * entire contents as drift. + * + * `unevaluatedProperties` is a JSON Schema 2019-09 keyword and is not valid in + * this description's OpenAPI 3.0.3 dialect. It works because `redocly drift` + * validates with Ajv; a validator that only knows 3.0 ignores it and silently + * reports zero drift. Safe only while the `test` bundle stays unpublished and + * drift-only. + */ +export const closeSchemas: Oas3Decorator = () => { + const candidates: Array> = []; + const parts = new WeakSet(); + const partReferences = new WeakSet(); + const references: Array<{ reference: Record; target: object }> = []; + + return { + ref: { + enter: (reference, _, { node }) => { + if (node) references.push({ reference: reference as unknown as Record, target: node as object }); + } + }, + Schema: { + enter: (schema, { resolve }) => { + for (const part of (schema.allOf ?? []) as Array) { + partReferences.add(part); + const { node } = resolve(part); + if (node) parts.add(node as object); + } + } + }, + SchemaProperties: { + leave: (_, { parent }) => { + if (parent.type !== "object" || parent.additionalProperties !== undefined) return; + if (parent.unevaluatedProperties !== undefined) return; + candidates.push(parent); + } + }, + Root: { + leave: () => { + // `unevaluatedProperties`, not `additionalProperties`: inside a `oneOf` + // branch the latter judges the whole object, so a response matching one + // branch fails every other branch once per field. `/auth/user` produced 89 + // phantom findings that way, including for properties the description does + // define. + for (const schema of candidates) if (!parts.has(schema)) schema.unevaluatedProperties = false; + + const closable = new WeakSet(candidates); + for (const { reference, target } of references) + if (parts.has(target) && closable.has(target) && !partReferences.has(reference)) reference.unevaluatedProperties = false; + } + } + }; +}; diff --git a/redocly/decorators/index.ts b/redocly/decorators/index.ts new file mode 100644 index 00000000..fca7409d --- /dev/null +++ b/redocly/decorators/index.ts @@ -0,0 +1,15 @@ +import { closeSchemas } from "./close-schemas.ts"; +import { infoExtensionOverride } from "./info-extension-override.ts"; +import { removeDiscriminators } from "./remove-discriminators.ts"; +import { removeXDeleted } from "./remove-x-deleted.ts"; +import { versionOverride } from "./version-override.ts"; +import { xLinks } from "./x-links.ts"; + +export const decorators = { + "close-schemas": closeSchemas, + "info-extension-override": infoExtensionOverride, + "remove-discriminators": removeDiscriminators, + "remove-x-deleted": removeXDeleted, + "version-override": versionOverride, + "x-links": xLinks +}; diff --git a/redocly/decorators/info-extension-override.ts b/redocly/decorators/info-extension-override.ts new file mode 100644 index 00000000..8fa39148 --- /dev/null +++ b/redocly/decorators/info-extension-override.ts @@ -0,0 +1,29 @@ +import { readFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import process from "node:process"; + +import type { Oas3Decorator } from "@redocly/openapi-core"; + +/** + * Sets an extension on `info` from a Markdown file, as Redocly's + * `info-description-override` does for `description`, so long prose such as the + * `x-agents` guidance lives in a file of its own. + * + * https://redocly.com/docs/cli/decorators/info-description-override + */ +export const infoExtensionOverride: Oas3Decorator = ({ name, filePath }) => ({ + Info: { + leave: (info, { report, location, config }) => { + if (typeof name !== "string" || !name.startsWith("x-") || typeof filePath !== "string") + throw new Error("`info-extension-override` needs an extension `name` starting with `x-` and a `filePath`."); + + try { + const base = config?.configPath ? dirname(config.configPath) : process.cwd(); + Object.assign(info, { [name]: readFileSync(resolve(base, filePath), "utf8").trimEnd() }); + } + catch (reason) { + report({ message: `Cannot read \`${filePath}\` for \`info.${name}\`: ${(reason as Error).message}`, location: location.child(name) }); + } + } + } +}); diff --git a/redocly/decorators/remove-discriminators.ts b/redocly/decorators/remove-discriminators.ts new file mode 100644 index 00000000..36c994b3 --- /dev/null +++ b/redocly/decorators/remove-discriminators.ts @@ -0,0 +1,13 @@ +import type { Oas3Decorator } from "@redocly/openapi-core"; + +/** + * The suite's Ajv cannot compile a `defaultMapping` fallback, and a discriminator never changes what a `oneOf` accepts. + * https://ajv.js.org/json-schema.html#discriminator + */ +export const removeDiscriminators: Oas3Decorator = () => ({ + Schema: { + leave: (schema) => { + delete (schema as Record).discriminator; + } + } +}); diff --git a/redocly/decorators/remove-x-deleted.ts b/redocly/decorators/remove-x-deleted.ts new file mode 100644 index 00000000..2b292d75 --- /dev/null +++ b/redocly/decorators/remove-x-deleted.ts @@ -0,0 +1,31 @@ +import type { Oas3Decorator } from "@redocly/openapi-core"; + +/** + * Drops every operation carrying `x-deleted`, and any path item left without an + * operation, from the published bundles. The test bundle keeps them so the suite + * goes on calling the route and a revival shows up as a failing `not-found` + * workflow. + */ +export const removeXDeleted: Oas3Decorator = () => { + // Operations leave before the path item holding them, so by the time one is + // visited this knows whether any of its own survived. + const populated = new WeakSet(); + + return { + Operation: { + leave: (operation, { parent, key }) => { + if ((operation as Record)["x-deleted"]) { + delete (parent as Record)[key]; + return; + } + + populated.add(parent as object); + } + }, + PathItem: { + leave: (pathItem, { parent, key }) => { + if (!populated.has(pathItem as object)) delete (parent as Record)[key]; + } + } + }; +}; diff --git a/redocly/decorators/version-override.ts b/redocly/decorators/version-override.ts new file mode 100644 index 00000000..d3978215 --- /dev/null +++ b/redocly/decorators/version-override.ts @@ -0,0 +1,25 @@ +import process from "node:process"; + +import type { Oas3Decorator } from "@redocly/openapi-core"; + +/** + * Sets `info.version` from the environment variable `environmentVariable` + * names, `version` by default, so a nightly build carries its own number. + */ +export const versionOverride: Oas3Decorator = ({ environmentVariable = "version" }) => ({ + Info: { + leave: (info, { report, location }) => { + const version = process.env[environmentVariable]; + if (!version) { + report({ + message: `\`${environmentVariable}\` is not set, so \`info.version\` stays \`${info.version}\`.`, + location: location.child("version"), + forceSeverity: "warn" + }); + return; + } + + info.version = version; + } + } +}); diff --git a/redocly/decorators/x-links.ts b/redocly/decorators/x-links.ts new file mode 100644 index 00000000..2dd7aa5f --- /dev/null +++ b/redocly/decorators/x-links.ts @@ -0,0 +1,56 @@ +import { extname } from "node:path"; + +import type { Oas3Decorator } from "@redocly/openapi-core"; + +/** + * Links each published document through `x-links` to the latest release, the + * latest nightly, and every OpenAPI version and format the release named by + * `info.version` publishes its family in. + * + * `documents` maps each family's evergreen file name, without its extension, to + * the template its versioned ones follow. The document being built is named by + * its API alias, which is its output file name, since Redocly hands a decorator + * its API's configuration without `output`. + * + * The links are written as the root is left, after every `info` decorator, so + * they follow `info.description` rather than pushing it further down. + * + * https://github.com/Redocly/redocly-cli/blob/main/packages/core/src/config/config.ts + */ +export const xLinks: Oas3Decorator = ({ releases, formats, versions, documents }) => ({ + Root: { + leave: ({ info }, { report, location, config }) => { + if (info === undefined) return; + + const file = config?._alias ?? ""; + const extension = extname(file); + const stem = file.slice(0, file.length - extension.length); + + const family = Object.entries(documents as Record).find(([evergreen, template]) => + stem === evergreen || (versions as Array).some((version) => template.replace("{version}", version) === stem)); + + if (!family) { + report({ message: `\`x-links\` has no family in \`documents\` for the API \`${file}\`.`, location: location.child(["info", "x-links"]), forceSeverity: "error" }); + return; + } + + const [evergreen, template] = family; + const type = (format: string) => `application/openapi+${format}`; + const base = `${releases}/download/v${info.version}`; + + Object.assign(info, { "x-links": [ + { title: "Latest (stable)", rel: "latest-version", href: `${releases}/latest/download/${file}`, type: type(extension.slice(1)) }, + { title: "Latest (nightly)", rel: "working-copy", href: `${releases}/download/nightly/${file}`, type: type(extension.slice(1)) }, + ...[ + [evergreen, "OpenAPI (evergreen)"], + ...(versions as Array).map((version) => [template.replace("{version}", version), `OpenAPI ${version}`]) + ].flatMap(([name, title]) => (formats as Array).map((format) => ({ + title: `${title}, ${format.toUpperCase()}`, + rel: "alternate", + href: `${base}/${name}.${format}`, + type: type(format) + }))) + ] }); + } + } +}); diff --git a/redocly/lib/casing.ts b/redocly/lib/casing.ts new file mode 100644 index 00000000..4039681d --- /dev/null +++ b/redocly/lib/casing.ts @@ -0,0 +1,33 @@ +import { camelCase, pascalCase } from "change-case"; + +/** + * Two or more capitals in a row read as an acronym. Where the run is followed by + * a lowercase letter its last capital opens the next word instead, so `FAEmail` + * is `FA` and `Email`. + */ +const acronyms = /[A-Z]{2,}/g; + +/** + * An acronym keeps every letter, so `getCSS` is already right where `getCss` is + * what splitting it into words gives. Renaming one costs a method name in every + * generated client and a redirect on the docs site, which is more than the + * spelling is worth. + */ +function isCase(value: string, convert: (value: string) => string) { + if (value === convert(value)) return true; + + const spelled = value.replaceAll(acronyms, (run, index: number) => { + const acronym = /[a-z]/.test(value[index + run.length] ?? "") ? run.slice(0, -1) : run; + return pascalCase(acronym) + run.slice(acronym.length); + }); + + return convert(spelled) === spelled || spelled === convert(value); +} + +export function isCamelCase(value: string) { + return isCase(value, camelCase); +} + +export function isPascalCase(value: string) { + return isCase(value, pascalCase); +} diff --git a/redocly/plugin.ts b/redocly/plugin.ts index 8ddc3484..19012cdf 100644 --- a/redocly/plugin.ts +++ b/redocly/plugin.ts @@ -1,77 +1,19 @@ import type { Plugin } from "@redocly/openapi-core"; -export default function myLocalPlugin(): Plugin { +import { decorators } from "./decorators/index.ts"; +import { rules } from "./rules/index.ts"; +import { typeExtension } from "./type-extension.ts"; + +/** + * Redocly transpiles this file alone, so every import within the plugin names + * its `.ts` extension outright; without one the loader reports the module as + * missing. + */ +export default function plugin(): Plugin { return { id: "vrchat", - decorators: { - oas3: { - /** - * Closes every object schema that lists properties, so a response - * carrying a field the description does not mention fails validation. - * - * Only for the test bundle. An open schema legally permits any - * extra property, which is correct for consumers but makes undocumented - * fields undetectable. - * - * Schemas without `properties` are left alone — those are deliberately - * free-form (`defaultContentSettings`, `appleDetails`) and closing them - * would report their entire contents as drift. - * - * `unevaluatedProperties` is a JSON Schema 2019-09 keyword and is not - * valid in this description's OpenAPI 3.0.3 dialect. It works because - * `redocly drift` validates with Ajv; a validator that only knows 3.0 - * ignores it and silently reports zero drift. Safe only while the - * `test` bundle stays unpublished and drift-only. - */ - "close-schemas": () => ({ - SchemaProperties: { - leave: (_, { parent }) => { - if (parent.type !== "object" || parent.additionalProperties !== undefined) return; - if (parent.unevaluatedProperties !== undefined) return; - - // `unevaluatedProperties`, not `additionalProperties`: inside a - // `oneOf` branch the latter judges the whole object, so a response - // matching one branch fails every other branch once per field. - // `/auth/user` produced 89 phantom findings that way, including for - // properties the description does define. - parent.unevaluatedProperties = false; - } - } - }), - }, - }, - preprocessors: { - oas3: { - "x-if": ({ defines = [] }: { defines?: Array }) => { - return { - SpecExtension: { - skip: (_, key) => key !== "x-if", - enter: (value, { parent, report, location }) => { - if (typeof value !== "object" || !value) - return report({ message: "Must be an object." }); - - const { when, then, else: fallback } = value as { when: string; then: Record; else: Record }; - - if (typeof when !== "string" || !when) - return report({ message: "Cannot be empty.", location: location.child("when") }); - - if (typeof then !== "object" || !then) - return report({ message: "Must be an object.", location: location.child("then") }); - - if (fallback !== undefined && (typeof fallback !== "object" || !fallback)) - return report({ message: "Must be an object.", location: location.child("else") }); - - Object.assign(parent, { - "x-if": undefined, - ...(defines.includes(when) - ? then - : fallback) - }); - } - } - }; - }, - }, - }, + rules: { oas3: rules }, + decorators: { oas3: decorators }, + typeExtension }; } diff --git a/redocly/rules/index.ts b/redocly/rules/index.ts new file mode 100644 index 00000000..f67f0afd --- /dev/null +++ b/redocly/rules/index.ts @@ -0,0 +1,17 @@ +import { noEmptyDescription } from "./no-empty-description.ts"; +import { noNestedObject } from "./no-nested-object.ts"; +import { noSchemaExample } from "./no-schema-example.ts"; +import { noSingleValueEnum } from "./no-single-value-enum.ts"; +import { operationIdConvention } from "./operation-id-convention.ts"; +import { preferUnknown } from "./prefer-unknown.ts"; +import { schemaTitle } from "./schema-title.ts"; + +export const rules = { + "no-empty-description": noEmptyDescription, + "no-nested-object": noNestedObject, + "no-schema-example": noSchemaExample, + "no-single-value-enum": noSingleValueEnum, + "operation-id-convention": operationIdConvention, + "prefer-unknown": preferUnknown, + "schema-title": schemaTitle +}; diff --git a/redocly/rules/no-empty-description.ts b/redocly/rules/no-empty-description.ts new file mode 100644 index 00000000..e2ffe66b --- /dev/null +++ b/redocly/rules/no-empty-description.ts @@ -0,0 +1,18 @@ +import type { Oas3Rule } from "@redocly/openapi-core"; + +/** + * A `description` left empty reads as a field nobody has written yet, and every + * generated client carries it through as a blank doc comment. + */ +export const noEmptyDescription: Oas3Rule = () => ({ + any: { + enter: (node, { report, location }) => { + if (typeof node !== "object" || node === null || !("description" in node)) return; + + const description = (node as { description: unknown }).description; + if (typeof description !== "string" || description.trim().length !== 0) return; + + report({ message: "Cannot be empty.", location: location.child("description") }); + } + } +}); diff --git a/redocly/rules/no-nested-object.ts b/redocly/rules/no-nested-object.ts new file mode 100644 index 00000000..81391bcd --- /dev/null +++ b/redocly/rules/no-nested-object.ts @@ -0,0 +1,20 @@ +import type { Oas3Rule } from "@redocly/openapi-core"; + +/** + * A schema in its own file carries a title taken from that file, so an object + * without one is still nested inside another schema. Adding a title in place + * would satisfy the rule without moving the object, which is why the message + * asks for the file rather than the title. + */ +export const noNestedObject: Oas3Rule = () => ({ + Schema: { + enter: (schema, { report, location }) => { + if (schema.type !== "object" || (schema.title ?? "").trim().length !== 0) return; + + report({ + message: "Object schemas belong in their own file under components/schemas, reached by $ref.", + location + }); + } + } +}); diff --git a/redocly/rules/no-schema-example.ts b/redocly/rules/no-schema-example.ts new file mode 100644 index 00000000..c79ba5a0 --- /dev/null +++ b/redocly/rules/no-schema-example.ts @@ -0,0 +1,17 @@ +import type { Oas3Rule } from "@redocly/openapi-core"; + +/** + * 3.1 deprecates a schema's `example` in favour of the JSON Schema `examples` + * keyword, a list. + * + * https://spec.openapis.org/oas/v3.1.2#schema-example + */ +export const noSchemaExample: Oas3Rule = () => ({ + Schema: { + enter: (schema, { report, location }) => { + if (!("example" in schema)) return; + + report({ message: "Use `examples`: 3.1 deprecates a schema's `example`.", location: location.child("example").key(), suggest: ["examples"] }); + } + } +}); diff --git a/redocly/rules/no-single-value-enum.ts b/redocly/rules/no-single-value-enum.ts new file mode 100644 index 00000000..360cb2ed --- /dev/null +++ b/redocly/rules/no-single-value-enum.ts @@ -0,0 +1,16 @@ +import type { Oas3Rule } from "@redocly/openapi-core"; + +/** + * An `enum` of one value is a `const`, which 3.1 schemas have. + * + * https://www.ietf.org/archive/id/draft-bhutton-json-schema-validation-01.txt section 6.1.3 + */ +export const noSingleValueEnum: Oas3Rule = () => ({ + Schema: { + enter: (schema, { report, location }) => { + if (!Array.isArray(schema.enum) || schema.enum.length !== 1) return; + + report({ message: "Use `const`: an `enum` of one value is a `const`.", location: location.child("enum").key(), suggest: ["const"] }); + } + } +}); diff --git a/redocly/rules/operation-id-convention.ts b/redocly/rules/operation-id-convention.ts new file mode 100644 index 00000000..a411e5b8 --- /dev/null +++ b/redocly/rules/operation-id-convention.ts @@ -0,0 +1,58 @@ +import type { Oas3Rule } from "@redocly/openapi-core"; +import { camelCase, split } from "change-case"; +import pluralize from "pluralize"; + +import { isCamelCase } from "../lib/casing.ts"; + +const { addUncountableRule, isPlural, plural } = pluralize; + +addUncountableRule("feedback"); + +/** + * An operation id is a public URL and the method name of every generated client, + * so the prefix has to match what the operation does and the plurality has to + * match what it returns. + */ +const prefixesByType = { + read: ["get", "list"], + write: ["create", "update", "patch", "delete"] +}; + +export const operationIdConvention: Oas3Rule = () => ({ + Operation: { + enter: (operation, { report, location, key }) => { + const { operationId = "", responses = {} } = operation; + if (!operationId) return; + + const at = location.child("operationId"); + const type = key === "get" ? "read" : "write"; + const [prefix, ...name] = split(operationId); + + if (type === "read") { + const returnsArray = Object + .values(responses) + .some((response) => response?.content?.["application/json"]?.schema?.type === "array"); + + const last = name.at(-1) || ""; + + if (returnsArray && !isPlural(last)) { + const suggested = camelCase(`${prefix}${name.slice(0, -1).join("")}${plural(last)}`); + report({ message: `Operation returns an array, consider renaming to ${suggested}.`, location: at }); + } + } + + const disallowed = Object + .entries(prefixesByType) + .filter(([candidate]) => candidate !== type) + .flatMap(([, prefixes]) => prefixes); + + if (disallowed.includes(prefix)) { + const suggested = camelCase(`${prefixesByType[type][0]}${name.join("")}`); + report({ message: `Operation name implies incorrect operation type, consider renaming to ${suggested}.`, location: at }); + } + + if (!isCamelCase(operationId)) + report({ message: `Consider renaming to ${camelCase(operationId)}.`, location: at }); + } + } +}); diff --git a/redocly/rules/prefer-unknown.ts b/redocly/rules/prefer-unknown.ts new file mode 100644 index 00000000..7f472257 --- /dev/null +++ b/redocly/rules/prefer-unknown.ts @@ -0,0 +1,16 @@ +import type { Oas3Rule } from "@redocly/openapi-core"; + +/** + * An empty schema accepts any value, which is what `Unknown` says by name. The + * named schema marks every value the description has yet to settle, and points a + * reader at how to help settle it. + */ +export const preferUnknown: Oas3Rule = () => ({ + Schema: { + enter: (schema, { report, location }) => { + if (Object.keys(schema).length !== 0) return; + + report({ message: "Use `$ref: Unknown` for a value of any shape.", location }); + } + } +}); diff --git a/redocly/rules/schema-title.ts b/redocly/rules/schema-title.ts new file mode 100644 index 00000000..c0969a9b --- /dev/null +++ b/redocly/rules/schema-title.ts @@ -0,0 +1,60 @@ +import { basename, extname } from "node:path"; + +import type { Oas3Rule, Oas3Visitor } from "@redocly/openapi-core"; +import { pascalCase } from "change-case"; + +import { isPascalCase } from "../lib/casing.ts"; + +/** + * Generated clients name a type after its title, so every named schema needs + * one, spelled in PascalCase, the case every language they target uses for a + * type. An acronym keeps its capitals, as in `APIConfig`. + * + * The bundle names a schema after its file, so a title that differs from the + * filename gives one schema two names, and can give two schemas the same one. + * + * `NamedSchemas` hands over the `$ref` nodes rather than the files behind them, + * and every schema here is a `$ref`, so an unresolved read finds no title on any + * of them. + */ +export const schemaTitle: Oas3Rule = (): Array => [ + { + NamedSchemas: { + enter: (schemas, { report, location, resolve }) => { + for (const [name, schema] of Object.entries(schemas)) { + const { node } = resolve(schema); + if ((node?.title ?? "").trim().length !== 0) continue; + + report({ message: "Schema must have a non-empty title.", location: location.child(name) }); + } + } + } + }, + { + Schema: { + enter: ({ title }, { report, location }) => { + if (title === undefined || isPascalCase(title)) return; + + report({ + message: "The title must be PascalCase.", + suggest: [pascalCase(title)], + location: location.child("title") + }); + } + } + }, + { + Schema: { + enter: ({ title }, { report, location }) => { + const filename = basename(location.source.absoluteRef, extname(location.source.absoluteRef)); + if (title === undefined || location.pointer !== "#/" || title === filename) return; + + report({ + message: `The title must match the filename, \`${filename}\`.`, + suggest: [filename], + location: location.child("title") + }); + } + } + } +]; diff --git a/redocly/type-extension.ts b/redocly/type-extension.ts new file mode 100644 index 00000000..b7d3c096 --- /dev/null +++ b/redocly/type-extension.ts @@ -0,0 +1,54 @@ +import type { Plugin } from "@redocly/openapi-core"; + +type TypeExtension = NonNullable; +type Types = ReturnType>; + +/** + * The `info` extensions the `vrchat/info-extension-override` and + * `vrchat/x-links` decorators write, so `struct` checks every bundle + * carries them in shape. Each link is an RFC 8288 web link. + * + * https://redocly.com/docs/cli/custom-plugins/extended-types + * https://www.rfc-editor.org/rfc/rfc8288#section-2 + */ +function extendInfo(types: Types): Types { + return { + ...types, + XLinkList: { properties: {}, items: "XLink" }, + XLink: { + properties: { + title: { type: "string" }, + rel: { type: "string" }, + href: { type: "string" }, + type: { type: "string" } + }, + required: ["rel", "href"] + }, + Info: { + ...types.Info, + properties: { + ...types.Info.properties, + "x-agents": { type: "string" }, + "x-links": "XLinkList" + } + } + }; +} + +/** + * 3.2 made a response's `description` optional, and Redocly's 3.2 Response type + * still inherits 3.1's requirement. + * + * https://spec.openapis.org/oas/v3.2.0#response-object + */ +function optionalResponseDescription(types: Types): Types { + const required = types.Response.required as Array; + return { ...types, Response: { ...types.Response, required: required.filter((name) => name !== "description") } }; +} + +export const typeExtension: TypeExtension = { + oas3: (types, version) => { + const extended = extendInfo(types); + return version === "oas3_2" ? optionalResponseDescription(extended) : extended; + } +}; diff --git a/spectral/functions/casing.ts b/spectral/functions/casing.ts deleted file mode 100644 index 92c17cbe..00000000 --- a/spectral/functions/casing.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createRulesetFunction } from "@stoplight/spectral-core"; -import { camelCase, pascalCase } from "change-case"; - -const types = { - camelCase, - pascalCase -}; - -export const casing = createRulesetFunction({ - input: { - type: "string", - }, - options: { - type: "object", - properties: { - type: { - enum: Object.keys(types), - } - }, - } -}, (value, { type }) => { - const suggestedName = types[type](value); - if (value === suggestedName) return []; - - return [{ - message: `Consider renaming to ${suggestedName}.`, - }]; -}); diff --git a/spectral/functions/spelling.ts b/spectral/functions/spelling.ts deleted file mode 100644 index 157a3e10..00000000 --- a/spectral/functions/spelling.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { createRulesetFunction } from "@stoplight/spectral-core"; - -import { check } from "../lib/typos"; - -const listFormat = new Intl.ListFormat("en", { style: "long", type: "disjunction" }); - -export const spelling = createRulesetFunction({ - input: { - type: "string", - }, - options: null -}, async (value, options, { path, documentInventory: { findAssociatedItemForPath } }) => { - value = value.trim(); - if (!value) return []; - - const parent = findAssociatedItemForPath(path.slice(0, -1), true); - const enumValues = ( - typeof parent?.document.data === "object" - && parent?.document.data - && "enum" in parent?.document.data - && Array.isArray(parent?.document.data.enum) - && parent?.document.data.enum - ) as Array || []; - - const issues = await check(value, enumValues); - if (issues.length === 0) return []; - - const messages = issues - .filter(({ text, suggestions }) => { - // It is pedantic sometimes, suggesting to change casing or apostrophes in words. - const cleanedSuggestions = suggestions?.map((suggestion) => suggestion.toLowerCase().replaceAll("'", "")) || []; - if (cleanedSuggestions.includes(text.toLowerCase())) return false; - - return true; - }) - .map((issue) => ({ - message: `Unknown word: ${issue.text}${issue.suggestions && issue.suggestions.length > 0 - ? `, did you mean ${listFormat.format(issue.suggestions)}?` - : "."}` - })); - - return messages; -}); diff --git a/spectral/identity.ts b/spectral/identity.ts deleted file mode 100644 index af51938c..00000000 --- a/spectral/identity.ts +++ /dev/null @@ -1,6 +0,0 @@ -import type { RuleDefinition, RulesetDefinition } from "@stoplight/spectral-core"; - -const identity = (value: T) => value; - -export const rule = (value: RuleDefinition) => identity(value); -export const ruleset = (value: RulesetDefinition) => identity(value); diff --git a/spectral/index.ts b/spectral/index.ts deleted file mode 100644 index 380ef75c..00000000 --- a/spectral/index.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* eslint-disable no-console */ -/** - * Spectral's CLI has some issues with resolving nested $refs, causing it to - * lose track of the source file in certain situations. - * - * This is a workaround for that. - * - * @see https://github.com/stoplightio/spectral/issues/2007 - */ - -import { readFile } from "node:fs/promises"; -import { relative, resolve } from "node:path"; -import { cwd, env, exit } from "node:process"; -import { parseArgs } from "node:util"; - -import { error, notice, summary, warning } from "@actions/core"; -import { Document, Ruleset, Spectral } from "@stoplight/spectral-core"; -import Parsers from "@stoplight/spectral-parsers"; -import Bun from "bun"; - -import { defaultRuleset } from "./ruleset"; - -const { values: { only = [], except = [], ci, fail }, positionals } = parseArgs({ - args: Bun.argv.slice(2), - strict: true, - allowPositionals: true, - options: { - only: { - type: "string", - multiple: true, - }, - except: { - type: "string", - multiple: true, - }, - ci: { - type: "boolean", - default: "CI" in env, - short: "i", - }, - fail: { - type: "string", - default: "0", - short: "f", - } - } -}); - -const commandBySeverity = { - 0: error, - 1: warning, - 2: notice, - 3: notice, -}; - -const filename = resolve(cwd(), positionals[0] || ""); - -// eslint-disable-next-line antfu/no-top-level-await -await execute(filename, { only, except, ci, failSeverity: Number.parseInt(fail) }); - -interface ExecuteOptions { - only: Array; - except: Array; - ci: boolean; - failSeverity: number; -} - -async function execute(filename: string, { only, except, failSeverity, ci }: ExecuteOptions) { - const spectral = new Spectral(); - spectral.setRuleset(new Ruleset(defaultRuleset, { source: filename })); - - if (except.length > 0) - for (const rule of except) - delete spectral.ruleset?.rules?.[rule]; - - if (only.length > 0) { - Object.assign(spectral.ruleset || {}, { - rules: Object.fromEntries(Object.entries(spectral.ruleset?.rules ?? {}).filter(([key]) => only.includes(key))) - }); - } - - const ruleNames = Object.keys(spectral.ruleset?.rules ?? {}).sort(); - console.log(`using Spectral with ${ruleNames.length} rules:`); - console.log(ruleNames.map((r) => `- ${r}`).join("\n")); - console.log(`on file: ${filename}`); - - const document = new Document(await readFile(filename, "utf8"), Parsers.Yaml, filename); - const diagnostics = await spectral.run(document); - - const failed = diagnostics.filter(({ severity }) => severity <= failSeverity).length > 0; - - if (!ci) { - const { stylish } = await import("@stoplight/spectral-formatters"); - - console.log(stylish(diagnostics, { failSeverity })); - if (failed) exit(1); - - return; - } - - summary.addHeading("Spectral lint"); - summary.addRaw(`${diagnostics.length} issue(s).`, true); - summary.addBreak(); - - const diagnosticsBySource = diagnostics.reduce((acc, diag) => { - const file = diag.source || ""; - if (!acc[file]) acc[file] = []; - acc[file].push(diag); - return acc; - }, {} as Record); - - summary.addHeading("By file", 2); - summary.addRaw(`${Object.keys(diagnosticsBySource).length} file(s) with issues.`, true); - summary.addBreak(); - - for (const [source, diagnostics] of Object.entries(diagnosticsBySource)) { - const pathname = relative(cwd(), source); - - summary.addHeading(pathname, 3); - summary.addRaw(`${diagnostics.length} issue${diagnostics.length === 1 ? "" : "s"}.`, true); - - summary.addList(diagnostics.map(({ code, message, range: { start } }) => { - const href = `${pathname}#L${start.line + 1}`; - return `(view) ${message} [${code}]`; - })); - } - - diagnostics.map(({ severity, code, message, source = "", range: { start, end } }) => { - const file = relative(cwd(), source); - - return commandBySeverity[severity](message, { - title: code.toString(), - file, - startLine: start.line + 1, - startColumn: start.character + 1, - endLine: end.line + 1, - endColumn: end.character + 1, - }); - }); - - if (env.GITHUB_STEP_SUMMARY) - await summary.write(); - - if (failed) exit(1); -} diff --git a/spectral/lib/typos.ts b/spectral/lib/typos.ts deleted file mode 100644 index 4989c38a..00000000 --- a/spectral/lib/typos.ts +++ /dev/null @@ -1,81 +0,0 @@ -import type { CSpellSettings, Document } from "cspell-lib"; -import { spellCheckDocument } from "cspell-lib"; - -const words = [ - "VRChat", - "VRC", - "Tilia", - "8JoV9XEdpo", - "Tupper", - "cooldown", - "favorited", - "vrchatplus", - "unban", - "unmute", - "spritesheet", - "despawns", - "urlencode", - "unmoderates", - "standalonewindows", - "unknownplatform", - "booping", - "unequip", - "playermoderation", - "unmoderate", - "interactable", - "bitmask", - "unbans", - "unequips", - "equippable", - "unmoderated", - "unmoderating", - "webform", - "recents" -]; - -const suggestWords = [ - "favourited: favorited" -]; - -const config: CSpellSettings = { - words, - - suggestWords, - numSuggestions: 3, - - noConfigSearch: true, - readonly: true, - validateDirectives: false, - - languageId: "markdown", - enabledLanguageIds: ["markdown"], - - patterns: [ - { - name: "ids", - pattern: /\w{1,4}_[\w-]{36}/g - }, - { - name: "extensions", - pattern: /\.\w+/g - } - ], - ignoreRegExpList: ["ids", "extensions"], - ignoreRandomStrings: true -}; - -const options = { - generateSuggestions: true, - ...config -}; - -export async function check(value: string, userWords: Array = []) { - if (!value?.trim()) return []; - - const document: Document = { text: value, uri: "value.md" }; - - // This is stupidly slow, might be worth looking into improving performance later. - const { issues = [] } = await spellCheckDocument(document, options, { ...config, userWords }); - - return issues; -} diff --git a/spectral/rules/description.ts b/spectral/rules/description.ts deleted file mode 100644 index 1b3084d3..00000000 --- a/spectral/rules/description.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { rule } from "../identity"; - -export const description = rule({ - given: "$..description", - then: { - function: (description) => { - if (description && String(description).trim().length !== 0) return []; - return [{ message: "Cannot be empty." }]; - } - } -}); diff --git a/spectral/rules/index.ts b/spectral/rules/index.ts deleted file mode 100644 index a99211c7..00000000 --- a/spectral/rules/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { description } from "./description.js"; -import { operationId } from "./operation-id"; -import { title } from "./title.js"; -import { typos } from "./typos.js"; - -export const rules = { - "vrc-description": description, - "vrc-operation-id": operationId, - "vrc-title": title, - "vrc-typos": typos, -}; diff --git a/spectral/rules/operation-id.ts b/spectral/rules/operation-id.ts deleted file mode 100644 index 5543e8e7..00000000 --- a/spectral/rules/operation-id.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { camelCase, split } from "change-case"; -import { addUncountableRule, isPlural, plural } from "pluralize"; - -import { casing } from "../functions/casing"; -import { rule } from "../identity"; - -addUncountableRule("feedback"); - -const prefixesByType = { - read: ["get", "list"], - write: ["create", "update", "patch", "delete"] -}; - -export const operationId = rule({ - severity: "hint", - given: "#OperationObject", - then: [ - { - function: ({ operationId = "", responses = {} } = {}, _options, { path = [] }) => { - const [, , method] = path; - const type = method === "get" ? "read" : "write"; - - const [prefix, ...operationName] = split(operationId); - - if (type === "read") { - const hasArrayResponse = Object - .values(responses) - .some((response: any) => { - const schema = response?.content?.["application/json"]?.schema; - return schema?.type === "array"; - }); - - const lastNameSegment = operationName.at(-1) || ""; - - if (hasArrayResponse && !isPlural(lastNameSegment)) { - const suggestedName = camelCase(`${prefix}${operationName.slice(0, -1).join("")}${plural(lastNameSegment)}`); - - return [{ - message: `Operation returns an array, consider renaming to ${suggestedName}.`, - path: [...path, "operationId"], - }]; - } - } - - const disallowedPrefixes = Object - .entries(prefixesByType) - .filter(([key]) => key !== type) - .flatMap(([, value]) => value); - - if (disallowedPrefixes.includes(prefix)) { - const suggestedPrefix = prefixesByType[type]?.[0]; - const suggestedName = camelCase(`${suggestedPrefix}${operationName.join("")}`); - - return [{ - message: `Operation name implies incorrect operation type, consider renaming to ${suggestedName}.`, - path: [...path, "operationId"], - }]; - } - - return []; - } - }, - { - field: "operationId", - function: casing, - functionOptions: { - type: "camelCase" - } - } - ] -}); diff --git a/spectral/rules/title.ts b/spectral/rules/title.ts deleted file mode 100644 index 467ec702..00000000 --- a/spectral/rules/title.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { rule } from "../identity"; - -export const title = rule({ - given: [ - "#AnyObjectSchema", - "$.components.schemas[*]", - ], - then: { - field: "title", - function: (value) => { - if (value && String(value).trim().length !== 0) return []; - return [{ message: "Schema must have a non-empty title." }]; - } - } -}); diff --git a/spectral/rules/typos.ts b/spectral/rules/typos.ts deleted file mode 100644 index e6beb55d..00000000 --- a/spectral/rules/typos.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { spelling } from "../functions/spelling.js"; -import { rule } from "../identity"; - -export const typos = rule({ - severity: "hint", - given: [ - "$..title", - "$..summary", - "$..description", - // "$..example", - "$..examples" - ], - then: [ - { - function: spelling - }, - { - field: "@key", - function: spelling - } - ] -}); diff --git a/spectral/ruleset.ts b/spectral/ruleset.ts deleted file mode 100644 index bae46773..00000000 --- a/spectral/ruleset.ts +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check - -import { oas3 } from "@stoplight/spectral-formats/dist/openapi"; -import { oas } from "@stoplight/spectral-rulesets"; - -import { ruleset } from "./identity"; -import { rules } from "./rules"; - -const excludedRules = [ - "oas3-operation-security-defined", - "operation-singular-tag" -]; - -export const defaultRuleset = ruleset({ - ...oas, - aliases: { - ...oas.aliases, - - AnyObjectSchema: { - targets: [ - { - formats: [oas3], - given: [ - // type: object - "$..[?(@ && @.type === 'object')]" - ] - } - ] - } - }, - rules: { - ...Object.fromEntries( - Object - .entries(oas.rules) - .filter(([key]) => !excludedRules.includes(key) && !key.startsWith("oas2-")) - .map(([key, { recommended, ...value }]) => [key, value]) - ), - ...rules - }, - overrides: [ - { - files: ["openapi.yaml"], - rules: { - "oas3-schema": "off", - "oas3-unused-component": "off" - } - } - ] -}); diff --git a/test/.env.example b/test/.env.example index f0cf7efa..ff65cafe 100644 --- a/test/.env.example +++ b/test/.env.example @@ -11,5 +11,11 @@ VRCHAT_TOTP_SECRET= VRCHAT_USERNAME= # Another account to exercise the friend and group-invite workflows against. -# Must not be the account above. +# Must not be the account above, and must not be one it is already friends with: +# `friend-request-lifecycle` starts by asserting there is no friendship to build. VRCHAT_FRIEND_ID=usr_00000000-0000-0000-0000-000000000000 + +# A group the account above owns, for the workflows that post, create roles, +# galleries and calendar events, and rename inside an existing group. They +# delete what they create, but the group itself must outlive every run. +VRCHAT_GROUP_ID=grp_00000000-0000-0000-0000-000000000000 diff --git a/test/arazzo.yaml b/test/arazzo.yaml index dee0a142..8820a176 100644 --- a/test/arazzo.yaml +++ b/test/arazzo.yaml @@ -328,6 +328,27 @@ workflows: successCriteria: - condition: $statusCode == 200 || $statusCode == 429 + - workflowId: check-user-exists-anonymous + summary: checkUserExists answers an anonymous caller + inputs: + type: object + required: + - username + properties: + username: + type: string + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: by-username-anonymous + operationId: $sourceDescriptions.default.checkUserExists + parameters: + - name: username + in: query + value: $inputs.username + successCriteria: + - condition: $statusCode == 200 || $statusCode == 429 + - workflowId: check-user-exists-no-parameters summary: Exists no parameters parameters: @@ -336,7 +357,7 @@ workflows: - stepId: exists-no-parameters operationId: $sourceDescriptions.default.checkUserExists successCriteria: - - condition: $statusCode == 400 + - condition: $statusCode == 400 || $statusCode == 429 - workflowId: avatar-moderation-lifecycle summary: Block an avatar globally, confirm it is listed, then unblock it @@ -346,6 +367,10 @@ workflows: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: unblock-avatar steps: - stepId: block-avatar operationId: $sourceDescriptions.default.createGlobalAvatarModeration @@ -378,6 +403,28 @@ workflows: value: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - workflowId: create-global-avatar-moderation-invalid-type + summary: createGlobalAvatarModeration names the moderation types it accepts + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: create-global-avatar-moderation + operationId: $sourceDescriptions.default.createGlobalAvatarModeration + requestBody: + contentType: application/json + payload: + avatarModerationType: x + targetAvatarId: avtr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 400 - workflowId: create-global-avatar-moderation-unauthenticated summary: createGlobalAvatarModeration refuses an anonymous caller @@ -486,6 +533,30 @@ workflows: successCriteria: - condition: $statusCode == 401 + - workflowId: get-interests-and-preferences + summary: Interests and preferences + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: interests-and-preferences + operationId: $sourceDescriptions.default.getInterestsAndPreferences + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-interests-and-preferences-unauthenticated + summary: getInterestsAndPreferences refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-interests-and-preferences + operationId: $sourceDescriptions.default.getInterestsAndPreferences + successCriteria: + - condition: $statusCode == 401 + - workflowId: get-moderation-reports summary: Moderation reports parameters: @@ -531,6 +602,59 @@ workflows: successCriteria: - condition: $statusCode == 401 + - workflowId: moderation-report-lifecycle + summary: Report the test account's own profile, find the report, then delete it + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-report + steps: + - stepId: submit-report + operationId: $sourceDescriptions.default.submitModerationReport + requestBody: + contentType: application/json + payload: + type: user + category: profile + reason: other + contentId: $workflows.session.outputs.userId + description: Please do not action this report. It is an automated test report filed by the VRChat API specification test suite (https://github.com/vrchatapi/specification) against its own test account. The suite deletes it moments after filing it. + successCriteria: + - condition: $statusCode == 200 + outputs: + reportId: $response.body#/id + onFailure: + - name: stop + type: end + + - stepId: find-report + operationId: $sourceDescriptions.default.getModerationReports + parameters: + - name: reportingUserId + in: query + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/totalCount == 1 + + - stepId: delete-report + operationId: $sourceDescriptions.default.deleteModerationReport + parameters: + - name: moderationReportId + in: path + value: $steps.submit-report.outputs.reportId + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + - workflowId: get-o-auth-redirect-code summary: Oauth redirect code parameters: @@ -611,6 +735,128 @@ workflows: value: test successCriteria: - condition: $statusCode == 400 + - workflowId: interests-and-preferences-lifecycle + summary: Turns every interest on, one off, then the rest off, reading each state back + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: turn-all-on + operationId: $sourceDescriptions.default.updateInterestsAndPreferences + requestBody: + contentType: application/json + payload: + Anime: true + Art: true + Avatars: true + BigGroup: true + Explore: true + Fantasy: true + Fashion: true + FindAvatars: true + Furries: true + Horror: true + LanguageLearning: true + MeetPeople: true + Music: true + Mystery: true + SciFi: true + SmallGroup: true + Surprise: true + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - stepId: read-all-on + operationId: $sourceDescriptions.default.getInterestsAndPreferences + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/Anime == true + - condition: $response.body#/Art == true + - condition: $response.body#/Avatars == true + - condition: $response.body#/BigGroup == true + - condition: $response.body#/Explore == true + - condition: $response.body#/Fantasy == true + - condition: $response.body#/Fashion == true + - condition: $response.body#/FindAvatars == true + - condition: $response.body#/Furries == true + - condition: $response.body#/Horror == true + - condition: $response.body#/LanguageLearning == true + - condition: $response.body#/MeetPeople == true + - condition: $response.body#/Music == true + - condition: $response.body#/Mystery == true + - condition: $response.body#/SciFi == true + - condition: $response.body#/SmallGroup == true + - condition: $response.body#/Surprise == true + onFailure: + - name: stop + type: end + + - stepId: turn-one-off + operationId: $sourceDescriptions.default.updateInterestsAndPreferences + requestBody: + contentType: application/json + payload: + Art: false + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - stepId: read-one-off + operationId: $sourceDescriptions.default.getInterestsAndPreferences + successCriteria: + - condition: $statusCode == 200 + - context: $response.body + condition: $[?(!@.Art)] + type: jsonpath + - condition: $response.body#/Music == true + onFailure: + - name: stop + type: end + + - stepId: turn-all-off + operationId: $sourceDescriptions.default.updateInterestsAndPreferences + requestBody: + contentType: application/json + payload: + Anime: false + Art: false + Avatars: false + BigGroup: false + Explore: false + Fantasy: false + Fashion: false + FindAvatars: false + Furries: false + Horror: false + LanguageLearning: false + MeetPeople: false + Music: false + Mystery: false + SciFi: false + SmallGroup: false + Surprise: false + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - stepId: read-all-off + operationId: $sourceDescriptions.default.getInterestsAndPreferences + successCriteria: + - condition: $statusCode == 200 + - context: $response.body + condition: $[?(!@.Music)] + type: jsonpath + - workflowId: logout summary: >- Invalidates the session, so `pnpm test` skips it by name — running @@ -663,6 +909,33 @@ workflows: successCriteria: - condition: $statusCode == 401 + - workflowId: update-interests-and-preferences-invalid-body + summary: updateInterestsAndPreferences refuses a body that is not an object + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: update-interests-and-preferences + operationId: $sourceDescriptions.default.updateInterestsAndPreferences + requestBody: + contentType: application/json + payload: not an object + successCriteria: + - condition: $statusCode == 400 + + - workflowId: update-interests-and-preferences-unauthenticated + summary: updateInterestsAndPreferences refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: update-interests-and-preferences + operationId: $sourceDescriptions.default.updateInterestsAndPreferences + successCriteria: + - condition: $statusCode == 401 + - workflowId: verify-2fa-unauthenticated summary: verify2FA refuses an anonymous caller parameters: @@ -865,6 +1138,16 @@ workflows: successCriteria: - condition: $statusCode == 200 + - workflowId: get-avatar-styles-anonymous + summary: getAvatarStyles answers an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: avatar-styles + operationId: $sourceDescriptions.default.getAvatarStyles + successCriteria: + - condition: $statusCode == 200 + - workflowId: get-favorited-avatars-query-parameters summary: getFavoritedAvatars with every fillable query parameter parameters: @@ -1096,6 +1379,24 @@ workflows: successCriteria: - condition: $statusCode == 401 + - workflowId: search-avatars-invalid-user + summary: searchAvatars names the values user accepts + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: search-avatars + operationId: $sourceDescriptions.default.searchAvatars + parameters: + - name: user + in: query + value: x + successCriteria: + - condition: $statusCode == 400 + - workflowId: search-avatars-query-parameters summary: searchAvatars with every fillable query parameter parameters: @@ -1335,10 +1636,6 @@ workflows: endsAt: $steps.ends-at.outputs.value successCriteria: - condition: $statusCode == 200 - onFailure: - - name: stop - type: end - outputs: calendarId: $response.body#/id @@ -1887,8 +2184,19 @@ workflows: - workflowId: calendar-event-lifecycle summary: Create a calendar event on an owned group, read it, update it, delete it + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent + failureActions: + - name: cleanup + type: goto + stepId: delete-event steps: - stepId: starts-at operationId: $sourceDescriptions.local.execute @@ -1928,26 +2236,6 @@ workflows: outputs: value: $response.body#/stdout - - stepId: own-groups - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - stepId: create-event x-security: - schemeName: authCookie @@ -1957,7 +2245,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -1986,7 +2274,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: calendarId in: path value: $steps.create-event.outputs.calendarId @@ -2003,7 +2291,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: calendarId in: path value: $steps.create-event.outputs.calendarId @@ -2024,12 +2312,15 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: calendarId in: path value: $steps.create-event.outputs.calendarId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: search-calendar-events summary: Search events @@ -2630,6 +2921,27 @@ workflows: successCriteria: - condition: $statusCode == 200 + - workflowId: get-product-purchases-invalid-sort + summary: getProductPurchases names the values sort accepts + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-product-purchases + operationId: $sourceDescriptions.default.getProductPurchases + parameters: + - name: buyerId + in: query + value: $workflows.session.outputs.userId + - name: sort + in: query + value: x + successCriteria: + - condition: $statusCode == 400 + - workflowId: get-product-purchases-query-parameters summary: getProductPurchases with every fillable query parameter parameters: @@ -2663,22 +2975,29 @@ workflows: successCriteria: - condition: $statusCode == 200 - - workflowId: get-product-purchases-unauthenticated - summary: getProductPurchases refuses an anonymous caller + - workflowId: get-product-purchases-sort-expire-date + summary: getProductPurchases sorted by expiry parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - stepId: get-product-purchases operationId: $sourceDescriptions.default.getProductPurchases parameters: - name: buyerId in: query - value: id_00000000-0000-0000-0000-000000000000 + value: $workflows.session.outputs.userId + - name: sort + in: query + value: expireDate successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-recent-subscription - summary: Read the most recent subscription + - workflowId: get-product-purchases-sort-name + summary: getProductPurchases sorted by name parameters: - reference: $components.parameters.userAgent x-security: @@ -2686,8 +3005,43 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: recent-subscription - operationId: $sourceDescriptions.default.getRecentSubscription + - stepId: get-product-purchases + operationId: $sourceDescriptions.default.getProductPurchases + parameters: + - name: buyerId + in: query + value: $workflows.session.outputs.userId + - name: sort + in: query + value: name + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-product-purchases-unauthenticated + summary: getProductPurchases refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-product-purchases + operationId: $sourceDescriptions.default.getProductPurchases + parameters: + - name: buyerId + in: query + value: id_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-recent-subscription + summary: Read the most recent subscription + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: recent-subscription + operationId: $sourceDescriptions.default.getRecentSubscription successCriteria: - condition: $statusCode == 200 @@ -3435,6 +3789,10 @@ workflows: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: remove-favorite steps: - stepId: world-favorites operationId: $sourceDescriptions.default.getFavorites @@ -3444,6 +3802,9 @@ workflows: value: world successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - stepId: add-favorite operationId: $sourceDescriptions.default.addFavorite @@ -3500,6 +3861,9 @@ workflows: value: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - stepId: verify-favorite-removed operationId: $sourceDescriptions.default.removeFavorite @@ -3509,6 +3873,9 @@ workflows: value: avtr_c38a1615-5bf5-42b4-84eb-a8b6c37cbd11 successCriteria: - condition: $statusCode == 404 + onFailure: + - name: stop + type: end - stepId: remove-unknown-favorite operationId: $sourceDescriptions.default.removeFavorite @@ -3518,11 +3885,17 @@ workflows: value: avtr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 404 + onFailure: + - name: stop + type: end - stepId: favorite-limits operationId: $sourceDescriptions.default.getFavoriteLimits successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: get-favorites-query-parameters summary: getFavorites with every fillable query parameter @@ -3777,6 +4150,10 @@ workflows: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-file steps: - stepId: files-before operationId: $sourceDescriptions.default.getFiles @@ -3786,6 +4163,9 @@ workflows: value: gallery successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - stepId: create-file operationId: $sourceDescriptions.default.createFile @@ -3872,6 +4252,9 @@ workflows: value: $steps.create-file.outputs.fileId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - stepId: verify-file-deleted operationId: $sourceDescriptions.default.getFile @@ -3881,6 +4264,9 @@ workflows: value: $steps.create-file.outputs.fileId successCriteria: - condition: $statusCode == 404 + onFailure: + - name: stop + type: end - workflowId: get-files-query-parameters summary: getFiles with every fillable query parameter @@ -3991,7 +4377,7 @@ workflows: successCriteria: - condition: $statusCode == 401 - workflowId: friend-request-lifecycle - summary: Send a friend request, confirm it is outgoing, withdraw it + summary: Send a friend request, read the status it leaves, withdraw it inputs: type: object required: @@ -4005,6 +4391,10 @@ workflows: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: cleanup-unfriend steps: - stepId: status-before operationId: $sourceDescriptions.default.getFriendStatus @@ -4016,6 +4406,9 @@ workflows: - condition: $statusCode == 200 - condition: $response.body#/isFriend == false - condition: $response.body#/outgoingRequest == false + onFailure: + - name: stop + type: end - stepId: send-request operationId: $sourceDescriptions.default.friend @@ -4026,7 +4419,18 @@ workflows: successCriteria: - condition: $statusCode == 200 - - stepId: verify-outgoing + - stepId: confirm-pending + description: A second request to the same user is refused while the first is outstanding, so a 200 here would mean the first never took. + operationId: $sourceDescriptions.default.friend + parameters: + - name: userId + in: path + value: $inputs.friendId + successCriteria: + - condition: $statusCode == 400 || $statusCode == 429 + + - stepId: status-pending + description: outgoingRequest trails the request it reflects by a minute or more, so a step reading it this soon can assert nothing either way. operationId: $sourceDescriptions.default.getFriendStatus parameters: - name: userId @@ -4034,7 +4438,7 @@ workflows: value: $inputs.friendId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/outgoingRequest == true + - condition: $response.body#/isFriend == false - stepId: delete-request operationId: $sourceDescriptions.default.deleteFriendRequest @@ -4054,6 +4458,34 @@ workflows: successCriteria: - condition: $statusCode == 200 - condition: $response.body#/outgoingRequest == false + onSuccess: + - name: done + type: end + + - stepId: cleanup-unfriend + operationId: $sourceDescriptions.default.unfriend + parameters: + - name: userId + in: path + value: $inputs.friendId + successCriteria: + - condition: $statusCode == 200 || $statusCode == 400 + onFailure: + - name: withdraw + type: goto + stepId: cleanup-withdraw + + - stepId: cleanup-withdraw + operationId: $sourceDescriptions.default.deleteFriendRequest + parameters: + - name: userId + in: path + value: $inputs.friendId + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: get-friend-status summary: Friend status @@ -5434,6 +5866,34 @@ workflows: successCriteria: - condition: $statusCode == 403 + - workflowId: get-group-member-not-member + summary: getGroupMember answers null for a user outside the group + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-group-member + operationId: $sourceDescriptions.default.getGroupMember + parameters: + - name: groupId + in: path + value: $inputs.groupId + - name: userId + in: path + value: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + successCriteria: + - condition: $statusCode == 200 + - workflowId: get-group-member-unauthenticated summary: getGroupMember refuses an anonymous caller parameters: @@ -5451,6 +5911,28 @@ workflows: successCriteria: - condition: $statusCode == 401 + - workflowId: get-group-members-populated + summary: Members of a group that has them + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-group-members + operationId: $sourceDescriptions.default.getGroupMembers + parameters: + - name: groupId + in: path + value: grp_52c61c62-9aff-44ed-a8ae-2595dd4745ca + - name: n + in: query + value: 50 + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/0/user/id != null + - workflowId: get-group-members-unauthenticated summary: getGroupMembers refuses an anonymous caller parameters: @@ -5619,35 +6101,30 @@ workflows: - workflowId: group-announcement-lifecycle summary: Create a group announcement, then delete it + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-announcement steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - stepId: create-announcement operationId: $sourceDescriptions.default.createGroupAnnouncement parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -5665,41 +6142,39 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: group-gallery-lifecycle summary: Create a group gallery, update it, delete it + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-gallery steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - stepId: create-gallery operationId: $sourceDescriptions.default.createGroupGallery parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -5720,7 +6195,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: groupGalleryId in: path value: $steps.create-gallery.outputs.galleryId @@ -5737,56 +6212,70 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId + - name: groupGalleryId + in: path + value: $steps.create-gallery.outputs.galleryId + successCriteria: + - condition: $statusCode == 200 + + - stepId: gallery-images-paginated + operationId: $sourceDescriptions.default.getGroupGalleryImages + parameters: + - name: groupId + in: path + value: $inputs.groupId - name: groupGalleryId in: path value: $steps.create-gallery.outputs.galleryId + - name: v + in: query + value: 2 successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/totalCount != null - stepId: delete-gallery operationId: $sourceDescriptions.default.deleteGroupGallery parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: groupGalleryId in: path value: $steps.create-gallery.outputs.galleryId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: group-member-role summary: Grant a role to the owner, then take it away + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-role steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - stepId: create-role operationId: $sourceDescriptions.default.createGroupRole parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -5809,7 +6298,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: userId in: path value: $workflows.session.outputs.userId @@ -5824,7 +6313,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: userId in: path value: $workflows.session.outputs.userId @@ -5839,44 +6328,42 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: groupRoleId in: path value: $steps.create-role.outputs.roleId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: group-post-lifecycle summary: Create a group post, update it, delete it + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-post steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - stepId: create-post operationId: $sourceDescriptions.default.addGroupPost parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -5898,7 +6385,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: notificationId in: path value: $steps.create-post.outputs.postId @@ -5917,15 +6404,25 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: notificationId in: path value: $steps.create-post.outputs.postId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: group-reads summary: Group reads against an existing membership + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: @@ -5933,28 +6430,12 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups + - stepId: group + operationId: $sourceDescriptions.default.getGroup parameters: - - name: userId + - name: groupId in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - - stepId: group - operationId: $sourceDescriptions.default.getGroup - parameters: - - name: groupId - in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -5963,7 +6444,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -5972,7 +6453,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -5981,7 +6462,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -5990,7 +6471,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -5999,7 +6480,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6008,7 +6489,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6017,7 +6498,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6026,7 +6507,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: query in: query value: test @@ -6038,7 +6519,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: userId in: path value: $workflows.session.outputs.userId @@ -6050,7 +6531,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6059,7 +6540,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6068,7 +6549,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6077,7 +6558,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 @@ -6086,41 +6567,36 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 - workflowId: group-role-lifecycle summary: Create a group role, update it, delete it + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: delete-role steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - stepId: create-role operationId: $sourceDescriptions.default.createGroupRole parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -6144,7 +6620,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: groupRoleId in: path value: $steps.create-role.outputs.roleId @@ -6161,15 +6637,25 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId - name: groupRoleId in: path value: $steps.create-role.outputs.roleId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - workflowId: group-update summary: Rename the group, confirm it applied, restore the name + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent x-security: @@ -6177,29 +6663,12 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - name: $response.body#/0/name - - stepId: rename operationId: $sourceDescriptions.default.updateGroup parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -6213,7 +6682,7 @@ workflows: parameters: - name: groupId in: path - value: $steps.own-groups.outputs.groupId + value: $inputs.groupId requestBody: contentType: application/json payload: @@ -6701,442 +7170,534 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: close-instance-not-found - summary: closeInstance refuses a resource that does not exist - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: close-instance - operationId: $sourceDescriptions.default.closeInstance - parameters: - - name: worldId - in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: instanceId - in: path - value: id_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - successCriteria: - - condition: $statusCode == 404 - - - workflowId: close-instance-unauthenticated - summary: closeInstance refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: close-instance - operationId: $sourceDescriptions.default.closeInstance - parameters: - - name: worldId - in: path - value: wrld_00000000-0000-0000-0000-000000000000 - - name: instanceId - in: path - value: 0 - successCriteria: - - condition: $statusCode == 401 - - - workflowId: get-instance-categories - summary: Instance categories need no session + - workflowId: update-instance-calendar-link-lifecycle + summary: Validate group instance calendar links and clean up every fixture parameters: - reference: $components.parameters.userAgent steps: - - stepId: instance-categories - operationId: $sourceDescriptions.default.getInstanceCategories + - stepId: in-window-starts-at + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: sh + args: + - -c + - date -u -d '+3600 seconds' +%Y-%m-%dT%H:%M:%S.%3NZ | tr -d '\n' successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/0/id != null + - condition: $response.body#/exitCode == 0 + onFailure: + - name: stop + type: end - - workflowId: get-instance-vibes - summary: Instance vibes need no session - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: instance-vibes - operationId: $sourceDescriptions.default.getInstanceVibes - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/id != null + outputs: + value: $response.body#/stdout - - workflowId: create-instance-non-private-can-request-invite - summary: createInstance refuses canRequestInvite outside a private instance - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: create-instance - operationId: $sourceDescriptions.default.createInstance + - stepId: in-window-ends-at + operationId: $sourceDescriptions.local.execute requestBody: contentType: application/json payload: - worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - type: friends - region: use - ownerId: $workflows.session.outputs.userId - canRequestInvite: true - successCriteria: - - condition: $statusCode == 400 - - - workflowId: create-instance-categorised - summary: Creates an instance carrying a category, a description and a vibe, then closes it - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: instance-categories - operationId: $sourceDescriptions.default.getInstanceCategories + command: sh + args: + - -c + - date -u -d '+7200 seconds' +%Y-%m-%dT%H:%M:%S.%3NZ | tr -d '\n' successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 onFailure: - name: stop type: end outputs: - categoryId: $response.body#/0/id + value: $response.body#/stdout - - stepId: instance-vibes - operationId: $sourceDescriptions.default.getInstanceVibes + - stepId: outside-window-starts-at + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: sh + args: + - -c + - date -u -d '+43200 seconds' +%Y-%m-%dT%H:%M:%S.%3NZ | tr -d '\n' successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 onFailure: - name: stop type: end outputs: - vibeId: $response.body#/0/id + value: $response.body#/stdout - - stepId: create-instance - operationId: $sourceDescriptions.default.createInstance + - stepId: outside-window-ends-at + operationId: $sourceDescriptions.local.execute requestBody: contentType: application/json payload: - worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - type: private - region: use - ownerId: $workflows.session.outputs.userId - description: test - categoryId: $steps.instance-categories.outputs.categoryId - vibeIds: - - $steps.instance-vibes.outputs.vibeId + command: sh + args: + - -c + - date -u -d '+46800 seconds' +%Y-%m-%dT%H:%M:%S.%3NZ | tr -d '\n' successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/description == 'test' - - condition: $response.body#/categoryId == $steps.instance-categories.outputs.categoryId - - condition: $response.body#/vibeIds/0 == $steps.instance-vibes.outputs.vibeId + - condition: $response.body#/exitCode == 0 onFailure: - name: stop type: end outputs: - instanceId: $response.body#/instanceId - - - stepId: close-instance - operationId: $sourceDescriptions.default.closeInstance - parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - - name: instanceId - in: path - value: $steps.create-instance.outputs.instanceId - successCriteria: - - condition: $statusCode == 200 + value: $response.body#/stdout - - workflowId: instance-lifecycle - summary: Creates a real private instance, then invites the account to it - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: create-instance - operationId: $sourceDescriptions.default.createInstance + - stepId: instance-group-short-code + operationId: $sourceDescriptions.local.execute requestBody: contentType: application/json payload: - worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - type: private - region: use - ownerId: $workflows.session.outputs.userId - canRequestInvite: true - ageGate: false - displayName: test - hardClose: false - inviteOnly: false - queueEnabled: false - instancePersistenceEnabled: false - playerPersistenceEnabled: false - closedAt: "2099-01-01T00:00:00.000Z" - contentSettings: - drones: true - emoji: true - pedestals: true - prints: true - props: true - stickers: true + command: sh + args: + - -c + - openssl rand -hex 2 | tr -d '\n' successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/canRequestInvite == true + - condition: $response.body#/exitCode == 0 onFailure: - name: stop type: end outputs: - instanceId: $response.body#/instanceId - - - stepId: invite-myself - operationId: $sourceDescriptions.default.inviteMyselfTo - parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - - name: instanceId - in: path - value: $steps.create-instance.outputs.instanceId - successCriteria: - - condition: $statusCode == 200 + value: $response.body#/stdout - - stepId: create-instance-null-display-name - operationId: $sourceDescriptions.default.createInstance + - stepId: event-group-short-code + operationId: $sourceDescriptions.local.execute requestBody: contentType: application/json payload: - worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - type: private - region: use - ownerId: $workflows.session.outputs.userId - displayName: null + command: sh + args: + - -c + - openssl rand -hex 2 | tr -d '\n' successCriteria: - - condition: $statusCode == 400 + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + onFailure: + - name: stop + type: end - - workflowId: get-instance - summary: Instance lookup needs no session - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: instance - operationId: $sourceDescriptions.default.getInstance + outputs: + value: $response.body#/stdout + + - stepId: create-instance-group + operationId: $sourceDescriptions.default.createGroup + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + requestBody: + contentType: application/json + payload: + name: Test Instance Calendar Links + privacy: private + joinState: invite + roleTemplate: default + shortCode: $steps.instance-group-short-code.outputs.value + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + outputs: + groupId: $response.body#/id + + - stepId: create-linkable-event + operationId: $sourceDescriptions.default.createGroupCalendarEvent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - - name: instanceId + - name: groupId in: path - value: "0" + value: $steps.create-instance-group.outputs.groupId + requestBody: + contentType: application/json + payload: + accessType: group + category: other + description: Created by the test suite + title: Test Instance Calendar Link + sendCreationNotification: false + startsAt: $steps.in-window-starts-at.outputs.value + endsAt: $steps.in-window-ends-at.outputs.value successCriteria: - condition: $statusCode == 200 + onFailure: + - name: cleanup-instance-group + type: goto + stepId: delete-instance-group - - workflowId: get-instance-by-short-name-not-found - summary: getInstanceByShortName refuses a resource that does not exist - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: get-instance-by-short-name - operationId: $sourceDescriptions.default.getInstanceByShortName + outputs: + calendarId: $response.body#/id + + - stepId: create-outside-window-event + operationId: $sourceDescriptions.default.createGroupCalendarEvent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: shortName + - name: groupId in: path - value: test + value: $steps.create-instance-group.outputs.groupId + requestBody: + contentType: application/json + payload: + accessType: group + category: other + description: Created by the test suite + title: Test Instance Calendar Window + sendCreationNotification: false + startsAt: $steps.outside-window-starts-at.outputs.value + endsAt: $steps.outside-window-ends-at.outputs.value successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 + onFailure: + - name: cleanup-instance-group + type: goto + stepId: delete-instance-group - - workflowId: get-recent-locations - summary: Recent locations - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: recent-locations - operationId: $sourceDescriptions.default.getRecentLocations + outputs: + calendarId: $response.body#/id + + - stepId: create-event-group + operationId: $sourceDescriptions.default.createGroup + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + requestBody: + contentType: application/json + payload: + name: Test Instance Calendar Event Owner + privacy: private + joinState: invite + roleTemplate: default + shortCode: $steps.event-group-short-code.outputs.value successCriteria: - condition: $statusCode == 200 + onFailure: + - name: cleanup-instance-group + type: goto + stepId: delete-instance-group - - workflowId: get-recent-locations-query-parameters - summary: getRecentLocations with every fillable query parameter - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: get-recent-locations - operationId: $sourceDescriptions.default.getRecentLocations + outputs: + groupId: $response.body#/id + + - stepId: create-cross-group-event + operationId: $sourceDescriptions.default.createGroupCalendarEvent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 + - name: groupId + in: path + value: $steps.create-event-group.outputs.groupId + requestBody: + contentType: application/json + payload: + accessType: group + category: other + description: Created by the test suite + title: Test Cross-Group Instance Calendar Link + sendCreationNotification: false + startsAt: $steps.in-window-starts-at.outputs.value + endsAt: $steps.in-window-ends-at.outputs.value successCriteria: - condition: $statusCode == 200 + onFailure: + - name: cleanup-event-group + type: goto + stepId: delete-event-group - - workflowId: get-recent-locations-unauthenticated - summary: getRecentLocations refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-recent-locations - operationId: $sourceDescriptions.default.getRecentLocations - successCriteria: - - condition: $statusCode == 401 + outputs: + calendarId: $response.body#/id - - workflowId: get-short-name - summary: Instance short name needs no session - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: short-name - operationId: $sourceDescriptions.default.getShortName - parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - - name: instanceId - in: path - value: "0" + - stepId: create-group-instance + operationId: $sourceDescriptions.default.createInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + requestBody: + contentType: application/json + payload: + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: group + region: use + ownerId: $steps.create-instance-group.outputs.groupId + groupAccessType: members successCriteria: - condition: $statusCode == 200 - - workflowId: world-instance-lifecycle - summary: Instance lookups derived from a live world - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: black-cat - operationId: $sourceDescriptions.default.getWorld - parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + onFailure: + - name: cleanup-event-group + type: goto + stepId: delete-event-group + + outputs: + instanceId: $response.body#/instanceId + + - stepId: create-private-instance + operationId: $sourceDescriptions.default.createInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + requestBody: + contentType: application/json + payload: + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: private + region: use + ownerId: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 onFailure: - - name: stop - type: end + - name: cleanup-group-instance + type: goto + stepId: close-group-instance outputs: - instanceId: $response.body#/instances/0/0 + instanceId: $response.body#/instanceId - - stepId: world-instance - operationId: $sourceDescriptions.default.getWorldInstance + - stepId: link-instance-event + operationId: $sourceDescriptions.default.updateInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - name: worldId in: path value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - name: instanceId in: path - value: $steps.black-cat.outputs.instanceId + value: $steps.create-group-instance.outputs.instanceId + requestBody: + contentType: application/json + payload: + calendarEntryId: $steps.create-linkable-event.outputs.calendarId successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/calendarEntryId == $steps.create-linkable-event.outputs.calendarId onFailure: - - name: stop - type: end - - outputs: - secureName: $response.body#/secureName + - name: cleanup-private-instance + type: goto + stepId: close-private-instance - - stepId: instance - operationId: $sourceDescriptions.default.getInstance + - stepId: unlink-instance-event + operationId: $sourceDescriptions.default.updateInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - name: worldId in: path value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - name: instanceId in: path - value: $steps.black-cat.outputs.instanceId + value: $steps.create-group-instance.outputs.instanceId + requestBody: + contentType: application/json + payload: + calendarEntryId: null successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/calendarEntryId == null + onFailure: + - name: cleanup-private-instance + type: goto + stepId: close-private-instance - - stepId: short-name - operationId: $sourceDescriptions.default.getShortName + - stepId: reject-outside-window-link + operationId: $sourceDescriptions.default.updateInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - name: worldId in: path value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - name: instanceId in: path - value: $steps.black-cat.outputs.instanceId + value: $steps.create-group-instance.outputs.instanceId + requestBody: + contentType: application/json + payload: + calendarEntryId: $steps.create-outside-window-event.outputs.calendarId + successCriteria: + - condition: $statusCode == 400 + - condition: $response.body#/error/message == 'You can only link instances to events starting within 6 hours‚ or that have ended within the last 6 hours․' + - condition: $response.body#/error/status_code == 400 + onFailure: + - name: cleanup-private-instance + type: goto + stepId: close-private-instance + + - stepId: reject-cross-group-link + operationId: $sourceDescriptions.default.updateInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-group-instance.outputs.instanceId + requestBody: + contentType: application/json + payload: + calendarEntryId: $steps.create-cross-group-event.outputs.calendarId + successCriteria: + - condition: $statusCode == 404 + - condition: $response.body#/error/message == 'Event not found․' + - condition: $response.body#/error/status_code == 404 + onFailure: + - name: cleanup-private-instance + type: goto + stepId: close-private-instance + + - stepId: reject-non-group-link + operationId: $sourceDescriptions.default.updateInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-private-instance.outputs.instanceId + requestBody: + contentType: application/json + payload: + calendarEntryId: $steps.create-linkable-event.outputs.calendarId + successCriteria: + - condition: $statusCode == 400 + - condition: $response.body#/error/message == "'calendarEntryId' is only allowed for group instances․" + - condition: $response.body#/error/status_code == 400 + onFailure: + - name: cleanup-private-instance + type: goto + stepId: close-private-instance + + - stepId: close-private-instance + operationId: $sourceDescriptions.default.closeInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-private-instance.outputs.instanceId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/secureName == - $steps.world-instance.outputs.secureName + onFailure: + - name: cleanup-group-instance + type: goto + stepId: close-group-instance - - stepId: instance-by-short-name - operationId: $sourceDescriptions.default.getInstanceByShortName + - stepId: close-group-instance + operationId: $sourceDescriptions.default.closeInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: shortName + - name: worldId in: path - value: $steps.world-instance.outputs.secureName + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-group-instance.outputs.instanceId successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/calendarEntryId == null + onFailure: + - name: cleanup-event-group + type: goto + stepId: delete-event-group - - workflowId: consume-own-inventory-item-unauthenticated - summary: consumeOwnInventoryItem refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: consume-own-inventory-item - operationId: $sourceDescriptions.default.consumeOwnInventoryItem + - stepId: delete-event-group + operationId: $sourceDescriptions.default.deleteGroup + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: inventoryItemId + - name: groupId in: path - value: inv_00000000-0000-0000-0000-000000000000 + value: $steps.create-event-group.outputs.groupId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + onFailure: + - name: cleanup-instance-group + type: goto + stepId: delete-instance-group - - workflowId: delete-own-inventory-item-unauthenticated - summary: deleteOwnInventoryItem refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: delete-own-inventory-item - operationId: $sourceDescriptions.default.deleteOwnInventoryItem + - stepId: delete-instance-group + operationId: $sourceDescriptions.default.deleteGroup + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: inventoryItemId + - name: groupId in: path - value: inv_00000000-0000-0000-0000-000000000000 + value: $steps.create-instance-group.outputs.groupId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: equip-own-inventory-item-unauthenticated - summary: equipOwnInventoryItem refuses an anonymous caller + - workflowId: update-instance-unauthenticated + summary: updateInstance refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: equip-own-inventory-item - operationId: $sourceDescriptions.default.equipOwnInventoryItem + - stepId: update-instance + operationId: $sourceDescriptions.default.updateInstance parameters: - - name: inventoryItemId + - name: worldId in: path - value: inv_00000000-0000-0000-0000-000000000000 + value: wrld_00000000-0000-0000-0000-000000000000 + - name: instanceId + in: path + value: 0 + requestBody: + contentType: application/json + payload: + calendarEntryId: null successCriteria: - condition: $statusCode == 401 - - workflowId: get-inventory-query-parameters - summary: getInventory with every fillable query parameter + - workflowId: update-instance-forbidden + summary: updateInstance refuses an instance the caller cannot edit parameters: - reference: $components.parameters.userAgent x-security: @@ -7144,82 +7705,74 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-inventory - operationId: $sourceDescriptions.default.getInventory + - stepId: update-instance + operationId: $sourceDescriptions.default.updateInstance parameters: - - name: archived - in: query - value: false - - name: equipSlot - in: query - value: "" - - name: flags - in: query - value: archivable - - name: notFlags - in: query - value: archivable - - name: notTypes - in: query - value: bundle + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + - name: instanceId + in: path + value: 0 + requestBody: + contentType: application/json + payload: + calendarEntryId: null successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 403 + - condition: $response.body#/error/message == "You're not allowed to edit this instance․" + - condition: $response.body#/error/status_code == 403 - - workflowId: get-inventory-unauthenticated - summary: getInventory refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-inventory - operationId: $sourceDescriptions.default.getInventory - successCriteria: - - condition: $statusCode == 401 - - workflowId: inventory-item-reads - summary: Reads the oldest owned prop, then fetches it by id + - workflowId: update-instance-not-found + summary: updateInstance refuses an owned instance that does not exist parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: list - operationId: $sourceDescriptions.default.getInventory - parameters: - - name: n - in: query - value: 100 - - name: offset - in: query - value: 0 - - name: order - in: query - value: oldest - - name: types - in: query - value: prop + - stepId: instance-id + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: sh + args: + - -c + - printf '98765~private(%s)~region(use)~nonce(00000000-0000-0000-0000-000000000000)' "$1" + - sh + - $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/data/0/metadata/propId == - 'prop_49fec698-f0cb-475c-9bc3-8f24e1bcc4eb' + - condition: $response.body#/exitCode == 0 onFailure: - name: stop type: end outputs: - inventoryItemId: $response.body#/data/0/id + value: $response.body#/stdout - - stepId: own-item - operationId: $sourceDescriptions.default.getOwnInventoryItem + - stepId: update-instance + operationId: $sourceDescriptions.default.updateInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: inventoryItemId + - name: worldId in: path - value: $steps.list.outputs.inventoryItemId + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.instance-id.outputs.value + requestBody: + contentType: application/json + payload: + calendarEntryId: null successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 404 + - condition: $response.body#/error/message == 'Instance not found․' + - condition: $response.body#/error/status_code == 404 - - workflowId: get-inventory-collections - summary: Inventory collections + - workflowId: close-instance-not-found + summary: closeInstance refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -7227,172 +7780,321 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: inventory-collections - operationId: $sourceDescriptions.default.getInventoryCollections + - stepId: close-instance + operationId: $sourceDescriptions.default.closeInstance + parameters: + - name: worldId + in: path + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: instanceId + in: path + value: id_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 404 - - workflowId: get-inventory-collections-unauthenticated - summary: getInventoryCollections refuses an anonymous caller + - workflowId: close-instance-unauthenticated + summary: closeInstance refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-inventory-collections - operationId: $sourceDescriptions.default.getInventoryCollections + - stepId: close-instance + operationId: $sourceDescriptions.default.closeInstance + parameters: + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + - name: instanceId + in: path + value: 0 successCriteria: - condition: $statusCode == 401 - - workflowId: get-inventory-drops - summary: Drops + - workflowId: get-instance-categories + summary: Instance categories need no session parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: drops - operationId: $sourceDescriptions.default.getInventoryDrops + - stepId: instance-categories + operationId: $sourceDescriptions.default.getInstanceCategories successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/0/id != null - - workflowId: get-inventory-drops-query-parameters - summary: getInventoryDrops with every fillable query parameter + - workflowId: get-instance-vibes + summary: Instance vibes need no session parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-inventory-drops - operationId: $sourceDescriptions.default.getInventoryDrops - parameters: - - name: active - in: query - value: false + - stepId: instance-vibes + operationId: $sourceDescriptions.default.getInstanceVibes successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/0/id != null - - workflowId: get-inventory-drops-unauthenticated - summary: getInventoryDrops refuses an anonymous caller + - workflowId: create-instance-non-private-can-request-invite + summary: createInstance refuses canRequestInvite outside a private instance parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-inventory-drops - operationId: $sourceDescriptions.default.getInventoryDrops + - stepId: create-instance + operationId: $sourceDescriptions.default.createInstance + requestBody: + contentType: application/json + payload: + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: friends + region: use + ownerId: $workflows.session.outputs.userId + canRequestInvite: true successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 400 - - workflowId: get-inventory-template - summary: Template + - workflowId: create-instance-categorised + summary: Creates an instance carrying a category, a description and a vibe, then closes it parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: close-instance steps: - - stepId: template - operationId: $sourceDescriptions.default.getInventoryTemplate + - stepId: instance-categories + operationId: $sourceDescriptions.default.getInstanceCategories + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + outputs: + categoryId: $response.body#/0/id + + - stepId: instance-vibes + operationId: $sourceDescriptions.default.getInstanceVibes + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + outputs: + vibeId: $response.body#/0/id + + - stepId: create-instance + operationId: $sourceDescriptions.default.createInstance + requestBody: + contentType: application/json + payload: + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: private + region: use + ownerId: $workflows.session.outputs.userId + description: test + categoryId: $steps.instance-categories.outputs.categoryId + vibeIds: + - $steps.instance-vibes.outputs.vibeId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/description == 'test' + - condition: $response.body#/categoryId == $steps.instance-categories.outputs.categoryId + - condition: $response.body#/vibeIds/0 == $steps.instance-vibes.outputs.vibeId + onFailure: + - name: stop + type: end + + outputs: + instanceId: $response.body#/instanceId + + - stepId: close-instance + operationId: $sourceDescriptions.default.closeInstance parameters: - - name: inventoryTemplateId + - name: worldId in: path - value: invt_1f11aa73-8f05-4d50-a1a8-c59074d03ce2 + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-instance.outputs.instanceId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: get-inventory-template-unauthenticated - summary: getInventoryTemplate refuses an anonymous caller + - workflowId: instance-lifecycle + summary: Creates a real private instance, then invites the account to it parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-inventory-template - operationId: $sourceDescriptions.default.getInventoryTemplate + - stepId: create-instance + operationId: $sourceDescriptions.default.createInstance + requestBody: + contentType: application/json + payload: + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: private + region: use + ownerId: $workflows.session.outputs.userId + canRequestInvite: true + ageGate: false + displayName: test + hardClose: false + inviteOnly: false + queueEnabled: false + instancePersistenceEnabled: false + playerPersistenceEnabled: false + closedAt: "2099-01-01T00:00:00.000Z" + contentSettings: + drones: true + emoji: true + pedestals: true + prints: true + props: true + stickers: true + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/canRequestInvite == true + onFailure: + - name: stop + type: end + + outputs: + instanceId: $response.body#/instanceId + + - stepId: invite-myself + operationId: $sourceDescriptions.default.inviteMyselfTo parameters: - - name: inventoryTemplateId + - name: worldId in: path - value: invt_00000000-0000-0000-0000-000000000000 + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-instance.outputs.instanceId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-own-inventory-item-unauthenticated - summary: getOwnInventoryItem refuses an anonymous caller + - stepId: create-instance-null-display-name + operationId: $sourceDescriptions.default.createInstance + requestBody: + contentType: application/json + payload: + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: private + region: use + ownerId: $workflows.session.outputs.userId + displayName: null + successCriteria: + - condition: $statusCode == 400 + + - workflowId: get-instance + summary: Instance lookup needs no session parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-own-inventory-item - operationId: $sourceDescriptions.default.getOwnInventoryItem + - stepId: instance + operationId: $sourceDescriptions.default.getInstance parameters: - - name: inventoryItemId + - name: worldId in: path - value: inv_00000000-0000-0000-0000-000000000000 + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: "0" successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-user-inventory-item-unauthenticated - summary: getUserInventoryItem refuses an anonymous caller + - workflowId: get-instance-by-short-name-not-found + summary: getInstanceByShortName refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-user-inventory-item - operationId: $sourceDescriptions.default.getUserInventoryItem + - stepId: get-instance-by-short-name + operationId: $sourceDescriptions.default.getInstanceByShortName parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: inventoryItemId + - name: shortName in: path - value: inv_00000000-0000-0000-0000-000000000000 + value: test successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 404 - - workflowId: redeem-reward-unauthenticated - summary: redeemReward refuses an anonymous caller + - workflowId: get-recent-locations + summary: Recent locations parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: redeem-reward - operationId: $sourceDescriptions.default.redeemReward + - stepId: recent-locations + operationId: $sourceDescriptions.default.getRecentLocations successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: share-inventory-item-direct-unauthenticated - summary: shareInventoryItemDirect refuses an anonymous caller + - workflowId: get-recent-locations-query-parameters + summary: getRecentLocations with every fillable query parameter parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: share-inventory-item-direct - operationId: $sourceDescriptions.default.shareInventoryItemDirect + - stepId: get-recent-locations + operationId: $sourceDescriptions.default.getRecentLocations parameters: - - name: itemId + - name: n in: query - value: id_00000000-0000-0000-0000-000000000000 - - name: duration + value: 1 + - name: offset in: query - value: id_00000000-0000-0000-0000-000000000000 + value: 1 successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: share-inventory-item-pedestal-unauthenticated - summary: shareInventoryItemPedestal refuses an anonymous caller + - workflowId: get-recent-locations-unauthenticated + summary: getRecentLocations refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: share-inventory-item-pedestal - operationId: $sourceDescriptions.default.shareInventoryItemPedestal - parameters: - - name: itemId - in: query - value: id_00000000-0000-0000-0000-000000000000 - - name: duration - in: query - value: id_00000000-0000-0000-0000-000000000000 + - stepId: get-recent-locations + operationId: $sourceDescriptions.default.getRecentLocations successCriteria: - condition: $statusCode == 401 - - workflowId: spawn-inventory-item - summary: Spawn + - workflowId: get-short-name + summary: Instance short name needs no session + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: short-name + operationId: $sourceDescriptions.default.getShortName + parameters: + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: "0" + successCriteria: + - condition: $statusCode == 200 + - workflowId: world-instance-lifecycle + summary: Instance lookups derived from a live world parameters: - reference: $components.parameters.userAgent x-security: @@ -7400,36 +8102,81 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: spawn - operationId: $sourceDescriptions.default.spawnInventoryItem + - stepId: black-cat + operationId: $sourceDescriptions.default.getWorld parameters: - - name: id - in: query - value: default_money + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: spawn-inventory-item-unauthenticated - summary: spawnInventoryItem refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: spawn-inventory-item - operationId: $sourceDescriptions.default.spawnInventoryItem + outputs: + instanceId: $response.body#/instances/0/0 + + - stepId: world-instance + operationId: $sourceDescriptions.default.getWorldInstance parameters: - - name: id - in: query - value: id_00000000-0000-0000-0000-000000000000 + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.black-cat.outputs.instanceId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: unequip-own-inventory-slot-unauthenticated - summary: unequipOwnInventorySlot refuses an anonymous caller + outputs: + secureName: $response.body#/secureName + + - stepId: instance + operationId: $sourceDescriptions.default.getInstance + parameters: + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.black-cat.outputs.instanceId + successCriteria: + - condition: $statusCode == 200 + + - stepId: short-name + operationId: $sourceDescriptions.default.getShortName + parameters: + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.black-cat.outputs.instanceId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/secureName == + $steps.world-instance.outputs.secureName + + - stepId: instance-by-short-name + operationId: $sourceDescriptions.default.getInstanceByShortName + parameters: + - name: shortName + in: path + value: $steps.world-instance.outputs.secureName + successCriteria: + - condition: $statusCode == 200 + + - workflowId: consume-own-inventory-item-unauthenticated + summary: consumeOwnInventoryItem refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: unequip-own-inventory-slot - operationId: $sourceDescriptions.default.unequipOwnInventorySlot + - stepId: consume-own-inventory-item + operationId: $sourceDescriptions.default.consumeOwnInventoryItem parameters: - name: inventoryItemId in: path @@ -7437,13 +8184,13 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: update-own-inventory-item-unauthenticated - summary: updateOwnInventoryItem refuses an anonymous caller + - workflowId: delete-own-inventory-item-unauthenticated + summary: deleteOwnInventoryItem refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: update-own-inventory-item - operationId: $sourceDescriptions.default.updateOwnInventoryItem + - stepId: delete-own-inventory-item + operationId: $sourceDescriptions.default.deleteOwnInventoryItem parameters: - name: inventoryItemId in: path @@ -7451,32 +8198,22 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: get-invite-message - summary: Message + - workflowId: equip-own-inventory-item-unauthenticated + summary: equipOwnInventoryItem refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: message - operationId: $sourceDescriptions.default.getInviteMessage + - stepId: equip-own-inventory-item + operationId: $sourceDescriptions.default.equipOwnInventoryItem parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message - - name: slot + - name: inventoryItemId in: path - value: 0 + value: inv_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: get-invite-message-not-found - summary: getInviteMessage refuses a resource that does not exist + - workflowId: get-inventory-query-parameters + summary: getInventory with every fillable query parameter parameters: - reference: $components.parameters.userAgent x-security: @@ -7484,43 +8221,38 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-invite-message - operationId: $sourceDescriptions.default.getInviteMessage + - stepId: get-inventory + operationId: $sourceDescriptions.default.getInventory parameters: - - name: userId - in: path - value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 + - name: archived + in: query + value: false + - name: equipSlot + in: query + value: "" + - name: flags + in: query + value: archivable + - name: notFlags + in: query + value: archivable + - name: notTypes + in: query + value: bundle successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 - - workflowId: get-invite-message-unauthenticated - summary: getInviteMessage refuses an anonymous caller + - workflowId: get-inventory-unauthenticated + summary: getInventory refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-invite-message - operationId: $sourceDescriptions.default.getInviteMessage - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 + - stepId: get-inventory + operationId: $sourceDescriptions.default.getInventory successCriteria: - condition: $statusCode == 401 - - - workflowId: get-invite-messages - summary: Messages + - workflowId: inventory-item-reads + summary: Reads the oldest owned prop, then fetches it by id parameters: - reference: $components.parameters.userAgent x-security: @@ -7528,37 +8260,43 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: messages - operationId: $sourceDescriptions.default.getInviteMessages + - stepId: list + operationId: $sourceDescriptions.default.getInventory parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message + - name: n + in: query + value: 100 + - name: offset + in: query + value: 0 + - name: order + in: query + value: oldest + - name: types + in: query + value: prop successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/data/0/metadata/propId == + 'prop_49fec698-f0cb-475c-9bc3-8f24e1bcc4eb' + onFailure: + - name: stop + type: end - - workflowId: get-invite-messages-unauthenticated - summary: getInviteMessages refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-invite-messages - operationId: $sourceDescriptions.default.getInviteMessages + outputs: + inventoryItemId: $response.body#/data/0/id + + - stepId: own-item + operationId: $sourceDescriptions.default.getOwnInventoryItem parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: messageType + - name: inventoryItemId in: path - value: message + value: $steps.list.outputs.inventoryItemId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: invite-myself-to-not-found - summary: inviteMyselfTo refuses a resource that does not exist + - workflowId: get-inventory-collections + summary: Inventory collections parameters: - reference: $components.parameters.userAgent x-security: @@ -7566,38 +8304,23 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: invite-myself-to - operationId: $sourceDescriptions.default.inviteMyselfTo - parameters: - - name: worldId - in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: instanceId - in: path - value: id_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - stepId: inventory-collections + operationId: $sourceDescriptions.default.getInventoryCollections successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: invite-myself-to-unauthenticated - summary: inviteMyselfTo refuses an anonymous caller + - workflowId: get-inventory-collections-unauthenticated + summary: getInventoryCollections refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: invite-myself-to - operationId: $sourceDescriptions.default.inviteMyselfTo - parameters: - - name: worldId - in: path - value: wrld_00000000-0000-0000-0000-000000000000 - - name: instanceId - in: path - value: 0 + - stepId: get-inventory-collections + operationId: $sourceDescriptions.default.getInventoryCollections successCriteria: - condition: $statusCode == 401 - - workflowId: invite-message-lifecycle - summary: >- - Skipped by name in `pnpm test`: resetting or updating a message - slot locks it for roughly half an hour, so these cannot run on every pass. + + - workflowId: get-inventory-drops + summary: Drops parameters: - reference: $components.parameters.userAgent x-security: @@ -7605,92 +8328,13 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: reset-message - operationId: $sourceDescriptions.default.resetInviteMessage - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 - successCriteria: - - condition: $statusCode == 200 - - - stepId: reset-message-rate-limited - operationId: $sourceDescriptions.default.resetInviteMessage - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 - successCriteria: - - condition: $statusCode == 429 - - - stepId: update-message - operationId: $sourceDescriptions.default.updateInviteMessage - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 - requestBody: - contentType: application/json - payload: - message: Hello, World! - successCriteria: - - condition: $statusCode == 200 - - - stepId: verify-message-updated - operationId: $sourceDescriptions.default.getInviteMessage - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 + - stepId: drops + operationId: $sourceDescriptions.default.getInventoryDrops successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/message == 'Hello, World!' - - - stepId: update-message-rate-limited - operationId: $sourceDescriptions.default.updateInviteMessage - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - - name: messageType - in: path - value: message - - name: slot - in: path - value: 0 - requestBody: - contentType: application/json - payload: - message: I am speed! - successCriteria: - - condition: $statusCode == 429 - - workflowId: invite-user-must-be-friends - summary: inviteUser refuses a user who is not a friend + - workflowId: get-inventory-drops-query-parameters + summary: getInventoryDrops with every fillable query parameter parameters: - reference: $components.parameters.userAgent x-security: @@ -7698,39 +8342,27 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: invite-user - operationId: $sourceDescriptions.default.inviteUser + - stepId: get-inventory-drops + operationId: $sourceDescriptions.default.getInventoryDrops parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - requestBody: - contentType: application/json - payload: - instanceId: "0" + - name: active + in: query + value: false successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 - - workflowId: invite-user-unauthenticated - summary: inviteUser refuses an anonymous caller + - workflowId: get-inventory-drops-unauthenticated + summary: getInventoryDrops refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: invite-user - operationId: $sourceDescriptions.default.inviteUser - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - requestBody: - contentType: application/json - payload: - instanceId: "0" + - stepId: get-inventory-drops + operationId: $sourceDescriptions.default.getInventoryDrops successCriteria: - condition: $statusCode == 401 - - workflowId: reset-invite-message-not-found - summary: resetInviteMessage refuses a resource that does not exist + - workflowId: get-inventory-template + summary: Template parameters: - reference: $components.parameters.userAgent x-security: @@ -7738,132 +8370,106 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: reset-invite-message - operationId: $sourceDescriptions.default.resetInviteMessage + - stepId: template + operationId: $sourceDescriptions.default.getInventoryTemplate parameters: - - name: userId - in: path - value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: messageType - in: path - value: message - - name: slot + - name: inventoryTemplateId in: path - value: 0 + value: invt_1f11aa73-8f05-4d50-a1a8-c59074d03ce2 successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 - - workflowId: reset-invite-message-unauthenticated - summary: resetInviteMessage refuses an anonymous caller + - workflowId: get-inventory-template-unauthenticated + summary: getInventoryTemplate refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: reset-invite-message - operationId: $sourceDescriptions.default.resetInviteMessage + - stepId: get-inventory-template + operationId: $sourceDescriptions.default.getInventoryTemplate parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: messageType - in: path - value: message - - name: slot + - name: inventoryTemplateId in: path - value: 0 + value: invt_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: update-invite-message-unauthenticated - summary: updateInviteMessage refuses an anonymous caller + - workflowId: get-own-inventory-item-unauthenticated + summary: getOwnInventoryItem refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: update-invite-message - operationId: $sourceDescriptions.default.updateInviteMessage + - stepId: get-own-inventory-item + operationId: $sourceDescriptions.default.getOwnInventoryItem parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: messageType - in: path - value: message - - name: slot + - name: inventoryItemId in: path - value: 0 + value: inv_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: delete-jam-submission-not-found - summary: deleteJamSubmission refuses a resource that does not exist + - workflowId: get-user-inventory-item-unauthenticated + summary: getUserInventoryItem refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: delete-jam-submission - operationId: $sourceDescriptions.default.deleteJamSubmission + - stepId: get-user-inventory-item + operationId: $sourceDescriptions.default.getUserInventoryItem parameters: - - name: jamId + - name: userId in: path - value: jam_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: jamSubmissionId + value: usr_00000000-0000-0000-0000-000000000000 + - name: inventoryItemId in: path - value: jsub_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: inv_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 401 - - workflowId: delete-jam-submission-unauthenticated - summary: deleteJamSubmission refuses an anonymous caller + - workflowId: redeem-reward-unauthenticated + summary: redeemReward refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-jam-submission - operationId: $sourceDescriptions.default.deleteJamSubmission - parameters: - - name: jamId - in: path - value: jam_00000000-0000-0000-0000-000000000000 - - name: jamSubmissionId - in: path - value: jsub_00000000-0000-0000-0000-000000000000 + - stepId: redeem-reward + operationId: $sourceDescriptions.default.redeemReward successCriteria: - condition: $statusCode == 401 - - workflowId: get-jam-not-found - summary: getJam refuses a resource that does not exist + - workflowId: share-inventory-item-direct-unauthenticated + summary: shareInventoryItemDirect refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-jam - operationId: $sourceDescriptions.default.getJam + - stepId: share-inventory-item-direct + operationId: $sourceDescriptions.default.shareInventoryItemDirect parameters: - - name: jamId - in: path - value: jam_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: itemId + in: query + value: id_00000000-0000-0000-0000-000000000000 + - name: duration + in: query + value: id_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 401 - - workflowId: get-jams - summary: Jams + - workflowId: share-inventory-item-pedestal-unauthenticated + summary: shareInventoryItemPedestal refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: jams - operationId: $sourceDescriptions.default.getJams + - stepId: share-inventory-item-pedestal + operationId: $sourceDescriptions.default.shareInventoryItemPedestal + parameters: + - name: itemId + in: query + value: id_00000000-0000-0000-0000-000000000000 + - name: duration + in: query + value: id_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 - - workflowId: jam-reads - summary: Reads the first jam, then its submissions + - condition: $statusCode == 401 + + - workflowId: spawn-inventory-item + summary: Spawn parameters: - reference: $components.parameters.userAgent x-security: @@ -7871,74 +8477,59 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: jams - operationId: $sourceDescriptions.default.getJams - successCriteria: - - condition: $statusCode == 200 - onFailure: - - name: stop - type: end - - outputs: - jamId: $response.body#/0/id - - - stepId: jam - operationId: $sourceDescriptions.default.getJam + - stepId: spawn + operationId: $sourceDescriptions.default.spawnInventoryItem parameters: - - name: jamId - in: path - value: $steps.jams.outputs.jamId + - name: id + in: query + value: default_money successCriteria: - condition: $statusCode == 200 - - stepId: submissions - operationId: $sourceDescriptions.default.getJamSubmissions + - workflowId: spawn-inventory-item-unauthenticated + summary: spawnInventoryItem refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: spawn-inventory-item + operationId: $sourceDescriptions.default.spawnInventoryItem parameters: - - name: jamId - in: path - value: $steps.jams.outputs.jamId + - name: id + in: query + value: id_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: submit-jam-content-not-found - summary: submitJamContent refuses a resource that does not exist + - workflowId: unequip-own-inventory-slot-unauthenticated + summary: unequipOwnInventorySlot refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: submit-jam-content - operationId: $sourceDescriptions.default.submitJamContent + - stepId: unequip-own-inventory-slot + operationId: $sourceDescriptions.default.unequipOwnInventorySlot parameters: - - name: jamId + - name: inventoryItemId in: path - value: jam_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - requestBody: - contentType: application/json - payload: - contentId: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - description: test + value: inv_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 400 + - condition: $statusCode == 401 - - workflowId: submit-jam-content-unauthenticated - summary: submitJamContent refuses an anonymous caller + - workflowId: update-own-inventory-item-unauthenticated + summary: updateOwnInventoryItem refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: submit-jam-content - operationId: $sourceDescriptions.default.submitJamContent + - stepId: update-own-inventory-item + operationId: $sourceDescriptions.default.updateOwnInventoryItem parameters: - - name: jamId + - name: inventoryItemId in: path - value: jam_00000000-0000-0000-0000-000000000000 + value: inv_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: get-assigned-permissions - summary: Assigned permissions + - workflowId: get-invite-message + summary: Message parameters: - reference: $components.parameters.userAgent x-security: @@ -7946,53 +8537,105 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: assigned-permissions - operationId: $sourceDescriptions.default.getAssignedPermissions + - stepId: message + operationId: $sourceDescriptions.default.getInviteMessage + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - condition: $statusCode == 200 - - workflowId: get-assigned-permissions-unauthenticated - summary: getAssignedPermissions refuses an anonymous caller + - workflowId: get-invite-message-not-found + summary: getInviteMessage refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-assigned-permissions - operationId: $sourceDescriptions.default.getAssignedPermissions + - stepId: get-invite-message + operationId: $sourceDescriptions.default.getInviteMessage + parameters: + - name: userId + in: path + value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 403 - - workflowId: get-config - summary: Config + - workflowId: get-invite-message-unauthenticated + summary: getInviteMessage refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: config - operationId: $sourceDescriptions.default.getConfig + - stepId: get-invite-message + operationId: $sourceDescriptions.default.getInviteMessage + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: get-css - summary: Css + - workflowId: get-invite-messages + summary: Messages parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: css - operationId: $sourceDescriptions.default.getCSS + - stepId: messages + operationId: $sourceDescriptions.default.getInviteMessages + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message successCriteria: - condition: $statusCode == 200 - - workflowId: get-current-online-users - summary: Online users + - workflowId: get-invite-messages-unauthenticated + summary: getInviteMessages refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: online-users - operationId: $sourceDescriptions.default.getCurrentOnlineUsers + - stepId: get-invite-messages + operationId: $sourceDescriptions.default.getInviteMessages + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + - name: messageType + in: path + value: message successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: get-health - summary: Health + - workflowId: invite-myself-to-not-found + summary: inviteMyselfTo refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -8000,22 +8643,38 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: health - operationId: $sourceDescriptions.default.getHealth + - stepId: invite-myself-to + operationId: $sourceDescriptions.default.inviteMyselfTo + parameters: + - name: worldId + in: path + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: instanceId + in: path + value: id_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 404 - - workflowId: get-health-unauthenticated - summary: getHealth refuses an anonymous caller + - workflowId: invite-myself-to-unauthenticated + summary: inviteMyselfTo refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-health - operationId: $sourceDescriptions.default.getHealth + - stepId: invite-myself-to + operationId: $sourceDescriptions.default.inviteMyselfTo + parameters: + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + - name: instanceId + in: path + value: 0 successCriteria: - condition: $statusCode == 401 - - workflowId: get-info-push - summary: Info push + - workflowId: invite-message-lifecycle + summary: >- + Skipped by name in `pnpm test`: resetting or updating a message + slot locks it for roughly half an hour, so these cannot run on every pass. parameters: - reference: $components.parameters.userAgent x-security: @@ -8023,34 +8682,92 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: info-push - operationId: $sourceDescriptions.default.getInfoPush - successCriteria: - - condition: $statusCode == 400 - - - workflowId: get-info-push-quick-menu-banner - summary: Info push quick menu banner - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: info-push-quick-menu-banner - operationId: $sourceDescriptions.default.getInfoPush + - stepId: reset-message + operationId: $sourceDescriptions.default.resetInviteMessage parameters: - - name: include - in: query - value: quick-menu-banner - - name: require - in: query - value: quick-menu-banner + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - condition: $statusCode == 200 - - workflowId: get-info-push-user-all - summary: Info push user all + - stepId: reset-message-rate-limited + operationId: $sourceDescriptions.default.resetInviteMessage + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 + successCriteria: + - condition: $statusCode == 429 + + - stepId: update-message + operationId: $sourceDescriptions.default.updateInviteMessage + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 + requestBody: + contentType: application/json + payload: + message: Hello, World! + successCriteria: + - condition: $statusCode == 200 + + - stepId: verify-message-updated + operationId: $sourceDescriptions.default.getInviteMessage + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/message == 'Hello, World!' + + - stepId: update-message-rate-limited + operationId: $sourceDescriptions.default.updateInviteMessage + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 + requestBody: + contentType: application/json + payload: + message: I am speed! + successCriteria: + - condition: $statusCode == 429 + + - workflowId: invite-user-must-be-friends + summary: inviteUser refuses a user who is not a friend parameters: - reference: $components.parameters.userAgent x-security: @@ -8058,30 +8775,39 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: info-push-user-all - operationId: $sourceDescriptions.default.getInfoPush + - stepId: invite-user + operationId: $sourceDescriptions.default.inviteUser parameters: - - name: include - in: query - value: user-all - - name: require - in: query - value: user-all + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + instanceId: "0" successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 403 - - workflowId: get-java-script - summary: Javascript + - workflowId: invite-user-unauthenticated + summary: inviteUser refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: javascript - operationId: $sourceDescriptions.default.getJavaScript + - stepId: invite-user + operationId: $sourceDescriptions.default.inviteUser + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + requestBody: + contentType: application/json + payload: + instanceId: "0" successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: get-permission - summary: Get permission + - workflowId: reset-invite-message-not-found + summary: resetInviteMessage refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -8089,41 +8815,63 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-permission - operationId: $sourceDescriptions.default.getPermission + - stepId: reset-invite-message + operationId: $sourceDescriptions.default.resetInviteMessage parameters: - - name: permissionId + - name: userId in: path - value: prms_fe07c8a7-a4ca-4eda-97e5-e241040ef6f8 + value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 403 - - workflowId: get-permissions - summary: Permissions + - workflowId: reset-invite-message-unauthenticated + summary: resetInviteMessage refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: permissions - operationId: $sourceDescriptions.default.getPermissions + - stepId: reset-invite-message + operationId: $sourceDescriptions.default.resetInviteMessage + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 401 - - workflowId: get-system-time - summary: System time + - workflowId: update-invite-message-unauthenticated + summary: updateInviteMessage refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: system-time - operationId: $sourceDescriptions.default.getSystemTime + - stepId: update-invite-message + operationId: $sourceDescriptions.default.updateInviteMessage + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + - name: messageType + in: path + value: message + - name: slot + in: path + value: 0 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: accept-friend-request-not-found - summary: acceptFriendRequest refuses a resource that does not exist + - workflowId: delete-jam-submission-not-found + summary: deleteJamSubmission refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -8131,31 +8879,37 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: accept-friend-request - operationId: $sourceDescriptions.default.acceptFriendRequest + - stepId: delete-jam-submission + operationId: $sourceDescriptions.default.deleteJamSubmission parameters: - - name: notificationId + - name: jamId in: path - value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: jam_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: jamSubmissionId + in: path + value: jsub_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - condition: $statusCode == 404 - - workflowId: accept-friend-request-unauthenticated - summary: acceptFriendRequest refuses an anonymous caller + - workflowId: delete-jam-submission-unauthenticated + summary: deleteJamSubmission refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: accept-friend-request - operationId: $sourceDescriptions.default.acceptFriendRequest + - stepId: delete-jam-submission + operationId: $sourceDescriptions.default.deleteJamSubmission parameters: - - name: notificationId + - name: jamId in: path - value: not_00000000-0000-0000-0000-000000000000 + value: jam_00000000-0000-0000-0000-000000000000 + - name: jamSubmissionId + in: path + value: jsub_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: acknowledge-notification-v2-not-found - summary: acknowledgeNotificationV2 refuses a resource that does not exist + - workflowId: get-jam-not-found + summary: getJam refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -8163,42 +8917,30 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: acknowledge-notification-v2 - operationId: $sourceDescriptions.default.acknowledgeNotificationV2 + - stepId: get-jam + operationId: $sourceDescriptions.default.getJam parameters: - - name: notificationId + - name: jamId in: path - value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: jam_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - condition: $statusCode == 404 - - workflowId: acknowledge-notification-v2-unauthenticated - summary: acknowledgeNotificationV2 refuses an anonymous caller + - workflowId: get-jams + summary: Jams parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: acknowledge-notification-v2 - operationId: $sourceDescriptions.default.acknowledgeNotificationV2 - parameters: - - name: notificationId - in: path - value: not_00000000-0000-0000-0000-000000000000 + - stepId: jams + operationId: $sourceDescriptions.default.getJams successCriteria: - - condition: $statusCode == 401 - - - workflowId: clear-notifications-unauthenticated - summary: clearNotifications refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: clear-notifications - operationId: $sourceDescriptions.default.clearNotifications - successCriteria: - - condition: $statusCode == 401 - - - workflowId: notification-lifecycle - summary: Invite the account to its own instance, then read, see and delete the - notification + - condition: $statusCode == 200 + - workflowId: jam-reads + summary: Reads the first jam, then its submissions parameters: - reference: $components.parameters.userAgent x-security: @@ -8206,119 +8948,74 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: create-instance - operationId: $sourceDescriptions.default.createInstance - requestBody: - contentType: application/json - payload: - worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - type: private - region: use - ownerId: $workflows.session.outputs.userId - canRequestInvite: true - successCriteria: - - condition: $statusCode == 200 - onFailure: - - name: stop - type: end - - outputs: - instanceId: $response.body#/instanceId - - - stepId: invite-self - operationId: $sourceDescriptions.default.inviteMyselfTo - parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - - name: instanceId - in: path - value: $steps.create-instance.outputs.instanceId + - stepId: jams + operationId: $sourceDescriptions.default.getJams successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/id != null onFailure: - name: stop type: end outputs: - notificationId: $response.body#/id - - - stepId: notification - operationId: $sourceDescriptions.default.getNotificationV2 - parameters: - - name: notificationId - in: path - value: $steps.invite-self.outputs.notificationId - successCriteria: - - condition: $statusCode == 403 + jamId: $response.body#/0/id - - stepId: get-notification - operationId: $sourceDescriptions.default.getNotification + - stepId: jam + operationId: $sourceDescriptions.default.getJam parameters: - - name: notificationId + - name: jamId in: path - value: $steps.invite-self.outputs.notificationId + value: $steps.jams.outputs.jamId successCriteria: - condition: $statusCode == 200 - - stepId: mark-read - operationId: $sourceDescriptions.default.markNotificationAsRead + - stepId: submissions + operationId: $sourceDescriptions.default.getJamSubmissions parameters: - - name: notificationId + - name: jamId in: path - value: $steps.invite-self.outputs.notificationId + value: $steps.jams.outputs.jamId successCriteria: - condition: $statusCode == 200 - - stepId: respond-invite - operationId: $sourceDescriptions.default.respondInvite + - workflowId: submit-jam-content-not-found + summary: submitJamContent refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: submit-jam-content + operationId: $sourceDescriptions.default.submitJamContent parameters: - - name: notificationId + - name: jamId in: path - value: $steps.invite-self.outputs.notificationId + value: jam_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 requestBody: contentType: application/json payload: - responseSlot: 0 + contentId: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + description: test successCriteria: - condition: $statusCode == 400 - - stepId: hide-notification - operationId: $sourceDescriptions.default.deleteNotification - parameters: - - name: notificationId - in: path - value: $steps.invite-self.outputs.notificationId - successCriteria: - - condition: $statusCode == 200 - - - workflowId: delete-all-notification-v2s-unauthenticated - summary: deleteAllNotificationV2s refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: delete-all-notification-v2s - operationId: $sourceDescriptions.default.deleteAllNotificationV2s - successCriteria: - - condition: $statusCode == 401 - - - workflowId: delete-notification-unauthenticated - summary: deleteNotification refuses an anonymous caller + - workflowId: submit-jam-content-unauthenticated + summary: submitJamContent refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-notification - operationId: $sourceDescriptions.default.deleteNotification + - stepId: submit-jam-content + operationId: $sourceDescriptions.default.submitJamContent parameters: - - name: notificationId + - name: jamId in: path - value: not_00000000-0000-0000-0000-000000000000 + value: jam_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: delete-notification-v2-not-found - summary: deleteNotificationV2 refuses a resource that does not exist + - workflowId: get-assigned-permissions + summary: Assigned permissions parameters: - reference: $components.parameters.userAgent x-security: @@ -8326,63 +9023,43 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: delete-notification-v2 - operationId: $sourceDescriptions.default.deleteNotificationV2 - parameters: - - name: notificationId - in: path - value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - stepId: assigned-permissions + operationId: $sourceDescriptions.default.getAssignedPermissions successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: delete-notification-v2-unauthenticated - summary: deleteNotificationV2 refuses an anonymous caller + - workflowId: get-assigned-permissions-unauthenticated + summary: getAssignedPermissions refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-notification-v2 - operationId: $sourceDescriptions.default.deleteNotificationV2 - parameters: - - name: notificationId - in: path - value: not_00000000-0000-0000-0000-000000000000 + - stepId: get-assigned-permissions + operationId: $sourceDescriptions.default.getAssignedPermissions successCriteria: - condition: $statusCode == 401 - - workflowId: get-notification-not-found - summary: getNotification refuses a resource that does not exist + - workflowId: get-config + summary: Config parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-notification - operationId: $sourceDescriptions.default.getNotification - parameters: - - name: notificationId - in: path - value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - stepId: config + operationId: $sourceDescriptions.default.getConfig successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: get-notification-unauthenticated - summary: getNotification refuses an anonymous caller + - workflowId: get-current-online-users + summary: Online users parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-notification - operationId: $sourceDescriptions.default.getNotification - parameters: - - name: notificationId - in: path - value: not_00000000-0000-0000-0000-000000000000 + - stepId: online-users + operationId: $sourceDescriptions.default.getCurrentOnlineUsers successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-notification-v2-not-found - summary: getNotificationV2 refuses a resource that does not exist + - workflowId: get-health + summary: Health parameters: - reference: $components.parameters.userAgent x-security: @@ -8390,31 +9067,22 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-notification-v2 - operationId: $sourceDescriptions.default.getNotificationV2 - parameters: - - name: notificationId - in: path - value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - stepId: health + operationId: $sourceDescriptions.default.getHealth successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 401 - - workflowId: get-notification-v2-unauthenticated - summary: getNotificationV2 refuses an anonymous caller + - workflowId: get-health-unauthenticated + summary: getHealth refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-notification-v2 - operationId: $sourceDescriptions.default.getNotificationV2 - parameters: - - name: notificationId - in: path - value: not_00000000-0000-0000-0000-000000000000 + - stepId: get-health + operationId: $sourceDescriptions.default.getHealth successCriteria: - condition: $statusCode == 401 - - - workflowId: get-notification-v2s - summary: Notifications v2 + - workflowId: get-info-push + summary: Info push parameters: - reference: $components.parameters.userAgent x-security: @@ -8422,13 +9090,13 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: notifications-v2 - operationId: $sourceDescriptions.default.getNotificationV2s + - stepId: info-push + operationId: $sourceDescriptions.default.getInfoPush successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 400 - - workflowId: get-notification-v2s-query-parameters - summary: getNotificationV2s with every fillable query parameter + - workflowId: get-info-push-quick-menu-banner + summary: Info push quick menu banner parameters: - reference: $components.parameters.userAgent x-security: @@ -8436,27 +9104,41 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-notification-v2s - operationId: $sourceDescriptions.default.getNotificationV2s + - stepId: info-push-quick-menu-banner + operationId: $sourceDescriptions.default.getInfoPush parameters: - - name: limit + - name: include in: query - value: 1 + value: quick-menu-banner + - name: require + in: query + value: quick-menu-banner successCriteria: - condition: $statusCode == 200 - - workflowId: get-notification-v2s-unauthenticated - summary: getNotificationV2s refuses an anonymous caller + - workflowId: get-info-push-user-all + summary: Info push user all parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-notification-v2s - operationId: $sourceDescriptions.default.getNotificationV2s + - stepId: info-push-user-all + operationId: $sourceDescriptions.default.getInfoPush + parameters: + - name: include + in: query + value: user-all + - name: require + in: query + value: user-all successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-notifications - summary: Notification list + - workflowId: get-permission + summary: Get permission parameters: - reference: $components.parameters.userAgent x-security: @@ -8464,13 +9146,17 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: notifications - operationId: $sourceDescriptions.default.getNotifications + - stepId: get-permission + operationId: $sourceDescriptions.default.getPermission + parameters: + - name: permissionId + in: path + value: prms_fe07c8a7-a4ca-4eda-97e5-e241040ef6f8 successCriteria: - condition: $statusCode == 200 - - workflowId: get-notifications-query-parameters - summary: getNotifications with every fillable query parameter + - workflowId: get-permissions + summary: Permissions parameters: - reference: $components.parameters.userAgent x-security: @@ -8478,50 +9164,23 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-notifications - operationId: $sourceDescriptions.default.getNotifications - parameters: - - name: hidden - in: query - value: false - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 - - name: sent - in: query - value: false - successCriteria: - - condition: $statusCode == 200 - - - workflowId: get-notifications-unauthenticated - summary: getNotifications refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-notifications - operationId: $sourceDescriptions.default.getNotifications + - stepId: permissions + operationId: $sourceDescriptions.default.getPermissions successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 403 - - workflowId: mark-notification-as-read-unauthenticated - summary: markNotificationAsRead refuses an anonymous caller + - workflowId: get-system-time + summary: System time parameters: - reference: $components.parameters.userAgent steps: - - stepId: mark-notification-as-read - operationId: $sourceDescriptions.default.markNotificationAsRead - parameters: - - name: notificationId - in: path - value: not_00000000-0000-0000-0000-000000000000 + - stepId: system-time + operationId: $sourceDescriptions.default.getSystemTime successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: reply-notification-v2-not-found - summary: replyNotificationV2 refuses a resource that does not exist + - workflowId: accept-friend-request-not-found + summary: acceptFriendRequest refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -8529,8 +9188,8 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: reply-notification-v2 - operationId: $sourceDescriptions.default.replyNotificationV2 + - stepId: accept-friend-request + operationId: $sourceDescriptions.default.acceptFriendRequest parameters: - name: notificationId in: path @@ -8538,13 +9197,13 @@ workflows: successCriteria: - condition: $statusCode == 404 - - workflowId: reply-notification-v2-unauthenticated - summary: replyNotificationV2 refuses an anonymous caller + - workflowId: accept-friend-request-unauthenticated + summary: acceptFriendRequest refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: reply-notification-v2 - operationId: $sourceDescriptions.default.replyNotificationV2 + - stepId: accept-friend-request + operationId: $sourceDescriptions.default.acceptFriendRequest parameters: - name: notificationId in: path @@ -8552,8 +9211,8 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: respond-notification-v2-not-found - summary: respondNotificationV2 refuses a resource that does not exist + - workflowId: acknowledge-notification-v2-not-found + summary: acknowledgeNotificationV2 refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -8561,26 +9220,22 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: respond-notification-v2 - operationId: $sourceDescriptions.default.respondNotificationV2 + - stepId: acknowledge-notification-v2 + operationId: $sourceDescriptions.default.acknowledgeNotificationV2 parameters: - name: notificationId in: path value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - requestBody: - contentType: application/json - payload: - responseType: test successCriteria: - condition: $statusCode == 404 - - workflowId: respond-notification-v2-unauthenticated - summary: respondNotificationV2 refuses an anonymous caller + - workflowId: acknowledge-notification-v2-unauthenticated + summary: acknowledgeNotificationV2 refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: respond-notification-v2 - operationId: $sourceDescriptions.default.respondNotificationV2 + - stepId: acknowledge-notification-v2 + operationId: $sourceDescriptions.default.acknowledgeNotificationV2 parameters: - name: notificationId in: path @@ -8588,132 +9243,2791 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: clear-all-player-moderations-unauthenticated - summary: clearAllPlayerModerations refuses an anonymous caller + - workflowId: clear-notifications-unauthenticated + summary: clearNotifications refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: clear-all-player-moderations - operationId: $sourceDescriptions.default.clearAllPlayerModerations + - stepId: clear-notifications + operationId: $sourceDescriptions.default.clearNotifications successCriteria: - condition: $statusCode == 401 - - workflowId: get-player-moderations-unauthenticated - summary: getPlayerModerations refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-player-moderations - operationId: $sourceDescriptions.default.getPlayerModerations - successCriteria: - - condition: $statusCode == 401 - - workflowId: player-moderation-lifecycle - summary: Creates then clears real player moderations + - workflowId: notification-lifecycle + summary: Invite the account to its own instance, then read, see and delete the + notification parameters: - reference: $components.parameters.userAgent x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken + failureActions: + - name: cleanup + type: goto + stepId: hide-notification steps: - - stepId: player-moderations - operationId: $sourceDescriptions.default.getPlayerModerations - successCriteria: - - condition: $statusCode == 200 - - - stepId: moderate-user - operationId: $sourceDescriptions.default.moderateUser + - stepId: create-instance + operationId: $sourceDescriptions.default.createInstance requestBody: contentType: application/json payload: - moderated: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 - type: unmute + worldId: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + type: private + region: use + ownerId: $workflows.session.outputs.userId + canRequestInvite: true successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/targetUserId == - 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' + onFailure: + - name: stop + type: end - - stepId: player-moderations-filtered - operationId: $sourceDescriptions.default.getPlayerModerations + outputs: + instanceId: $response.body#/instanceId + + - stepId: invite-self + operationId: $sourceDescriptions.default.inviteMyselfTo parameters: - - name: type - in: query - value: unmute + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - name: instanceId + in: path + value: $steps.create-instance.outputs.instanceId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/0/targetUserId == - 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' - - condition: $response.body#/0/type == 'unmute' + - condition: $response.body#/id != null + onFailure: + - name: stop + type: end - - stepId: clear-player-moderations - operationId: $sourceDescriptions.default.clearAllPlayerModerations + outputs: + notificationId: $response.body#/id + + - stepId: notification + operationId: $sourceDescriptions.default.getNotificationV2 + parameters: + - name: notificationId + in: path + value: $steps.invite-self.outputs.notificationId + successCriteria: + - condition: $statusCode == 403 + + - stepId: get-notification + operationId: $sourceDescriptions.default.getNotification + parameters: + - name: notificationId + in: path + value: $steps.invite-self.outputs.notificationId successCriteria: - condition: $statusCode == 200 - - workflowId: moderate-user-unauthenticated - summary: moderateUser refuses an anonymous caller + - stepId: mark-read + operationId: $sourceDescriptions.default.markNotificationAsRead + parameters: + - name: notificationId + in: path + value: $steps.invite-self.outputs.notificationId + successCriteria: + - condition: $statusCode == 200 + + - stepId: respond-invite + operationId: $sourceDescriptions.default.respondInvite + parameters: + - name: notificationId + in: path + value: $steps.invite-self.outputs.notificationId + requestBody: + contentType: application/json + payload: + responseSlot: 0 + successCriteria: + - condition: $statusCode == 400 + + - stepId: hide-notification + operationId: $sourceDescriptions.default.deleteNotification + parameters: + - name: notificationId + in: path + value: $steps.invite-self.outputs.notificationId + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - workflowId: delete-all-notification-v2s-unauthenticated + summary: deleteAllNotificationV2s refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: moderate-user - operationId: $sourceDescriptions.default.moderateUser + - stepId: delete-all-notification-v2s + operationId: $sourceDescriptions.default.deleteAllNotificationV2s successCriteria: - condition: $statusCode == 401 - - workflowId: unmoderate-user-unauthenticated - summary: unmoderateUser refuses an anonymous caller + - workflowId: delete-notification-unauthenticated + summary: deleteNotification refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: unmoderate-user - operationId: $sourceDescriptions.default.unmoderateUser + - stepId: delete-notification + operationId: $sourceDescriptions.default.deleteNotification + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: delete-print-unauthenticated - summary: deletePrint refuses an anonymous caller + - workflowId: delete-notification-v2-not-found + summary: deleteNotificationV2 refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: delete-print - operationId: $sourceDescriptions.default.deletePrint + - stepId: delete-notification-v2 + operationId: $sourceDescriptions.default.deleteNotificationV2 parameters: - - name: printId + - name: notificationId in: path - value: prnt_00000000-0000-0000-0000-000000000000 + value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 404 - - workflowId: edit-print-unauthenticated - summary: editPrint refuses an anonymous caller + - workflowId: delete-notification-v2-unauthenticated + summary: deleteNotificationV2 refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: edit-print + - stepId: delete-notification-v2 + operationId: $sourceDescriptions.default.deleteNotificationV2 + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-notification-not-found + summary: getNotification refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-notification + operationId: $sourceDescriptions.default.getNotification + parameters: + - name: notificationId + in: path + value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: get-notification-unauthenticated + summary: getNotification refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-notification + operationId: $sourceDescriptions.default.getNotification + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-notification-v2-not-found + summary: getNotificationV2 refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-notification-v2 + operationId: $sourceDescriptions.default.getNotificationV2 + parameters: + - name: notificationId + in: path + value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 403 + + - workflowId: get-notification-v2-unauthenticated + summary: getNotificationV2 refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-notification-v2 + operationId: $sourceDescriptions.default.getNotificationV2 + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-notification-v2s + summary: Notifications v2 + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: notifications-v2 + operationId: $sourceDescriptions.default.getNotificationV2s + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-notification-v2s-query-parameters + summary: getNotificationV2s with every fillable query parameter + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-notification-v2s + operationId: $sourceDescriptions.default.getNotificationV2s + parameters: + - name: limit + in: query + value: 1 + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-notification-v2s-unauthenticated + summary: getNotificationV2s refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-notification-v2s + operationId: $sourceDescriptions.default.getNotificationV2s + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-notifications + summary: Notification list + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: notifications + operationId: $sourceDescriptions.default.getNotifications + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-notifications-query-parameters + summary: getNotifications with every fillable query parameter + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-notifications + operationId: $sourceDescriptions.default.getNotifications + parameters: + - name: hidden + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: 1 + - name: sent + in: query + value: false + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-notifications-unauthenticated + summary: getNotifications refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-notifications + operationId: $sourceDescriptions.default.getNotifications + successCriteria: + - condition: $statusCode == 401 + + - workflowId: mark-notification-as-read-unauthenticated + summary: markNotificationAsRead refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: mark-notification-as-read + operationId: $sourceDescriptions.default.markNotificationAsRead + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: reply-notification-v2-not-found + summary: replyNotificationV2 refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: reply-notification-v2 + operationId: $sourceDescriptions.default.replyNotificationV2 + parameters: + - name: notificationId + in: path + value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: reply-notification-v2-unauthenticated + summary: replyNotificationV2 refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: reply-notification-v2 + operationId: $sourceDescriptions.default.replyNotificationV2 + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: respond-notification-v2-not-found + summary: respondNotificationV2 refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: respond-notification-v2 + operationId: $sourceDescriptions.default.respondNotificationV2 + parameters: + - name: notificationId + in: path + value: not_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + requestBody: + contentType: application/json + payload: + responseType: test + successCriteria: + - condition: $statusCode == 404 + + - workflowId: respond-notification-v2-unauthenticated + summary: respondNotificationV2 refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: respond-notification-v2 + operationId: $sourceDescriptions.default.respondNotificationV2 + parameters: + - name: notificationId + in: path + value: not_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: clear-all-player-moderations-unauthenticated + summary: clearAllPlayerModerations refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: clear-all-player-moderations + operationId: $sourceDescriptions.default.clearAllPlayerModerations + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-player-moderations-unauthenticated + summary: getPlayerModerations refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-player-moderations + operationId: $sourceDescriptions.default.getPlayerModerations + successCriteria: + - condition: $statusCode == 401 + - workflowId: player-moderation-lifecycle + summary: Creates then clears real player moderations + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: player-moderations + operationId: $sourceDescriptions.default.getPlayerModerations + successCriteria: + - condition: $statusCode == 200 + + - stepId: moderate-user + operationId: $sourceDescriptions.default.moderateUser + requestBody: + contentType: application/json + payload: + moderated: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + type: unmute + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/targetUserId == + 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' + + - stepId: player-moderations-filtered + operationId: $sourceDescriptions.default.getPlayerModerations + parameters: + - name: type + in: query + value: unmute + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/0/targetUserId == + 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' + - condition: $response.body#/0/type == 'unmute' + + - stepId: clear-player-moderations + operationId: $sourceDescriptions.default.clearAllPlayerModerations + successCriteria: + - condition: $statusCode == 200 + + - workflowId: moderate-user-unauthenticated + summary: moderateUser refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: moderate-user + operationId: $sourceDescriptions.default.moderateUser + successCriteria: + - condition: $statusCode == 401 + + - workflowId: unmoderate-user-unauthenticated + summary: unmoderateUser refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: unmoderate-user + operationId: $sourceDescriptions.default.unmoderateUser + successCriteria: + - condition: $statusCode == 401 + + - workflowId: delete-print-unauthenticated + summary: deletePrint refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: delete-print + operationId: $sourceDescriptions.default.deletePrint + parameters: + - name: printId + in: path + value: prnt_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: edit-print-unauthenticated + summary: editPrint refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: edit-print operationId: $sourceDescriptions.default.editPrint parameters: - - name: printId + - name: printId + in: path + value: prnt_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-print-unauthenticated + summary: getPrint refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-print + operationId: $sourceDescriptions.default.getPrint + parameters: + - name: printId + in: path + value: prnt_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-user-prints + summary: User prints + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: user-prints + operationId: $sourceDescriptions.default.getUserPrints + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-user-prints-unauthenticated + summary: getUserPrints refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-user-prints + operationId: $sourceDescriptions.default.getUserPrints + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: upload-print-unauthenticated + summary: uploadPrint refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: upload-print + operationId: $sourceDescriptions.default.uploadPrint + successCriteria: + - condition: $statusCode == 401 + + - workflowId: delete-prop-not-found + summary: deleteProp refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: delete-prop + operationId: $sourceDescriptions.default.deleteProp + parameters: + - name: propId + in: path + value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 403 + + - workflowId: delete-prop-unauthenticated + summary: deleteProp refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: delete-prop + operationId: $sourceDescriptions.default.deleteProp + parameters: + - name: propId + in: path + value: prop_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-prop-not-found + summary: getProp refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-prop + operationId: $sourceDescriptions.default.getProp + parameters: + - name: propId + in: path + value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: get-prop-unauthenticated + summary: getProp refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-prop + operationId: $sourceDescriptions.default.getProp + parameters: + - name: propId + in: path + value: prop_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-prop-publish-status-not-found + summary: getPropPublishStatus refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-prop-publish-status + operationId: $sourceDescriptions.default.getPropPublishStatus + parameters: + - name: propId + in: path + value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: list-props + summary: Props + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: props + operationId: $sourceDescriptions.default.listProps + successCriteria: + - condition: $statusCode == 200 || $statusCode == 403 + + - workflowId: list-props-query-parameters + summary: listProps with every fillable query parameter + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: list-props + operationId: $sourceDescriptions.default.listProps + parameters: + - name: n + in: query + value: 1 + - name: offset + in: query + value: 1 + successCriteria: + - condition: $statusCode == 200 + + - workflowId: list-props-unauthenticated + summary: listProps refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: list-props + operationId: $sourceDescriptions.default.listProps + parameters: + - name: authorId + in: query + value: id_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: publish-prop-not-found + summary: publishProp refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: publish-prop + operationId: $sourceDescriptions.default.publishProp + parameters: + - name: propId + in: path + value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: unpublish-prop-not-found + summary: unpublishProp refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: unpublish-prop + operationId: $sourceDescriptions.default.unpublishProp + parameters: + - name: propId + in: path + value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: update-prop-not-found + summary: updateProp refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: update-prop + operationId: $sourceDescriptions.default.updateProp + parameters: + - name: propId + in: path + value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 400 + + - workflowId: add-tags + summary: Tag changes on another user are rejected + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: add-tag-other-user + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.addTags + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + requestBody: + contentType: application/json + payload: + tags: + - language_kor + successCriteria: + - condition: $statusCode == 401 || $statusCode == 403 || $statusCode == 404 + + - workflowId: add-tags-unauthenticated + summary: addTags refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: add-tags + operationId: $sourceDescriptions.default.addTags + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: check-user-persistence-exists-not-found + summary: checkUserPersistenceExists refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: check-user-persistence-exists + operationId: $sourceDescriptions.default.checkUserPersistenceExists + parameters: + - name: userId + in: path + value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: worldId + in: path + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 403 + + - workflowId: check-user-persistence-exists-unauthenticated + summary: checkUserPersistenceExists refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: check-user-persistence-exists + operationId: $sourceDescriptions.default.checkUserPersistenceExists + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: delete-all-user-persistence-data-unauthenticated + summary: deleteAllUserPersistenceData refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: delete-all-user-persistence-data + operationId: $sourceDescriptions.default.deleteAllUserPersistenceData + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: delete-user-persistence-not-found + summary: deleteUserPersistence refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: delete-user-persistence + operationId: $sourceDescriptions.default.deleteUserPersistence + parameters: + - name: userId + in: path + value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: worldId + in: path + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 403 + + - workflowId: delete-user-persistence-unauthenticated + summary: deleteUserPersistence refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: delete-user-persistence + operationId: $sourceDescriptions.default.deleteUserPersistence + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-blocked-groups + summary: Blocked groups + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: blocked-groups + operationId: $sourceDescriptions.default.getBlockedGroups + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-blocked-groups-unauthenticated + summary: getBlockedGroups refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-blocked-groups + operationId: $sourceDescriptions.default.getBlockedGroups + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: profile-update-restore + summary: Change every profile field the current user reflects, confirm each applied, restore them + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: marker + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: sh + args: + - -c + - openssl rand -hex 6 | tr -d '\n' + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + onFailure: + - name: stop + type: end + + outputs: + value: $response.body#/stdout + + - stepId: current-before + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getCurrentUser + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + outputs: + pronouns: $response.body#/pronouns + status: $response.body#/status + statusDescription: $response.body#/statusDescription + isBoopingEnabled: $response.body#/isBoopingEnabled + unsubscribe: $response.body#/unsubscribe + allowWorldsToCountFriendsInInstance: $response.body#/allowWorldsToCountFriendsInInstance + + - stepId: update-profile + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.updateUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + statusDescription: $steps.marker.outputs.value + pronouns: they/them + status: ask me + isBoopingEnabled: false + unsubscribe: false + allowWorldsToCountFriendsInInstance: false + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/statusDescription == $steps.marker.outputs.value + - condition: $response.body#/pronouns == 'they/them' + - condition: $response.body#/status == 'ask me' + - condition: $response.body#/isBoopingEnabled == false + - condition: $response.body#/unsubscribe == false + - condition: $response.body#/allowWorldsToCountFriendsInInstance == false + + - stepId: verify-current-user + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getCurrentUser + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/statusDescription == $steps.marker.outputs.value + - condition: $response.body#/pronouns == 'they/them' + - condition: $response.body#/status == 'ask me' + - condition: $response.body#/isBoopingEnabled == false + - condition: $response.body#/unsubscribe == false + - condition: $response.body#/allowWorldsToCountFriendsInInstance == false + + - stepId: verify-get-user + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/statusDescription == $steps.marker.outputs.value + - condition: $response.body#/pronouns == 'they/them' + - condition: $response.body#/status == 'ask me' + - condition: $response.body#/isBoopingEnabled == false + - condition: $response.body#/unsubscribe == false + - condition: $response.body#/allowWorldsToCountFriendsInInstance == false + + - stepId: restore-profile + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.updateUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + statusDescription: $steps.current-before.outputs.statusDescription + pronouns: $steps.current-before.outputs.pronouns + status: $steps.current-before.outputs.status + isBoopingEnabled: $steps.current-before.outputs.isBoopingEnabled + unsubscribe: $steps.current-before.outputs.unsubscribe + allowWorldsToCountFriendsInInstance: $steps.current-before.outputs.allowWorldsToCountFriendsInInstance + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/statusDescription == $steps.current-before.outputs.statusDescription + - condition: $response.body#/pronouns == $steps.current-before.outputs.pronouns + - condition: $response.body#/status == $steps.current-before.outputs.status + - condition: $response.body#/isBoopingEnabled == $steps.current-before.outputs.isBoopingEnabled + - condition: $response.body#/unsubscribe == $steps.current-before.outputs.unsubscribe + - condition: $response.body#/allowWorldsToCountFriendsInInstance == $steps.current-before.outputs.allowWorldsToCountFriendsInInstance + + - stepId: verify-restored + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/statusDescription == $steps.current-before.outputs.statusDescription + - condition: $response.body#/pronouns == $steps.current-before.outputs.pronouns + - condition: $response.body#/status == $steps.current-before.outputs.status + - condition: $response.body#/isBoopingEnabled == $steps.current-before.outputs.isBoopingEnabled + - condition: $response.body#/unsubscribe == $steps.current-before.outputs.unsubscribe + - condition: $response.body#/allowWorldsToCountFriendsInInstance == $steps.current-before.outputs.allowWorldsToCountFriendsInInstance + + - workflowId: get-invited-groups + summary: Invited groups + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: invited-groups + operationId: $sourceDescriptions.default.getInvitedGroups + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-invited-groups-unauthenticated + summary: getInvitedGroups refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-invited-groups + operationId: $sourceDescriptions.default.getInvitedGroups + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-mutual-friends + summary: Mutual friends + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: mutual-friends + operationId: $sourceDescriptions.default.getMutualFriends + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-mutual-friends-query-parameters + summary: getMutualFriends with every fillable query parameter + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-mutual-friends + operationId: $sourceDescriptions.default.getMutualFriends + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: n + in: query + value: 1 + - name: offset + in: query + value: 1 + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-mutual-friends-unauthenticated + summary: getMutualFriends refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-mutual-friends + operationId: $sourceDescriptions.default.getMutualFriends + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-mutual-groups + summary: Mutual groups + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: mutual-groups + operationId: $sourceDescriptions.default.getMutualGroups + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-mutual-groups-query-parameters + summary: getMutualGroups with every fillable query parameter + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-mutual-groups + operationId: $sourceDescriptions.default.getMutualGroups + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: n + in: query + value: 1 + - name: offset + in: query + value: 1 + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-mutual-groups-unauthenticated + summary: getMutualGroups refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-mutual-groups + operationId: $sourceDescriptions.default.getMutualGroups + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-mutuals + summary: Mutuals + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: mutuals + operationId: $sourceDescriptions.default.getMutuals + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-mutuals-unauthenticated + summary: getMutuals refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-mutuals + operationId: $sourceDescriptions.default.getMutuals + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-private-profile + summary: Private profile + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: private-profile + operationId: $sourceDescriptions.default.getPrivateProfile + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-private-profile-unauthenticated + summary: getPrivateProfile refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-private-profile + operationId: $sourceDescriptions.default.getPrivateProfile + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-public-profile + summary: Public profile + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: public-profile + operationId: $sourceDescriptions.default.getPublicProfile + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-public-profile-with-groups-and-worlds + summary: Public profile with groups and public worlds + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: public-profile + operationId: $sourceDescriptions.default.getPublicProfile + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: withGroupsAndWorlds + in: query + value: true + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/groups != null + - condition: $response.body#/publicWorlds != null + - condition: $response.body#/worldFavoriteLists != null + + - workflowId: get-public-profile-populated + summary: Public profile carrying badges, a banner, a custom theme and public worlds + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: public-profile + operationId: $sourceDescriptions.default.getPublicProfile + parameters: + - name: userId + in: path + value: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + - name: withGroupsAndWorlds + in: query + value: true + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/badges/0/badgeId != null + - condition: $response.body#/bannerUrl != null + - condition: $response.body#/backgroundTextureId != null + - condition: $response.body#/themeButtonColor != null + - condition: $response.body#/publicWorlds/0/id != null + + - workflowId: get-public-profile-unauthenticated + summary: getPublicProfile refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-public-profile + operationId: $sourceDescriptions.default.getPublicProfile + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-user + summary: Get user + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-user + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/id == 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' + + - workflowId: get-user-not-found + summary: getUser refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-user + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: get-user-own + summary: Get own user + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-own-user + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/id == $workflows.session.outputs.userId + + - workflowId: get-user-friends + summary: Get every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-user-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-user-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-get-user + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-get-user + operationId: $sourceDescriptions.default.getUser + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/id == $steps.online-friend.outputs.friends#/0/id + - condition: $response.body#/isFriend == true + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-user-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-user-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-get-user + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-get-user + operationId: $sourceDescriptions.default.getUser + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/id == $steps.offline-friend.outputs.friends#/0/id + - condition: $response.body#/isFriend == true + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-friend-status-friends + summary: Friend status of every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-friend-status-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-friend-status-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-friend-status + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-friend-status + operationId: $sourceDescriptions.default.getFriendStatus + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/isFriend == true + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-friend-status-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-friend-status-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-friend-status + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-friend-status + operationId: $sourceDescriptions.default.getFriendStatus + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/isFriend == true + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-mutuals-friends + summary: Mutuals with every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-mutuals-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-mutuals-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-mutuals + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-mutuals + operationId: $sourceDescriptions.default.getMutuals + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-mutuals-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-mutuals-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-mutuals + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-mutuals + operationId: $sourceDescriptions.default.getMutuals + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-mutual-friends-friends + summary: Mutual friends with every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-mutual-friends-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-mutual-friends-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-mutual-friends + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-mutual-friends + operationId: $sourceDescriptions.default.getMutualFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-mutual-friends-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-mutual-friends-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-mutual-friends + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-mutual-friends + operationId: $sourceDescriptions.default.getMutualFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-mutual-groups-friends + summary: Mutual groups with every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-mutual-groups-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-mutual-groups-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-mutual-groups + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-mutual-groups + operationId: $sourceDescriptions.default.getMutualGroups + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-mutual-groups-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-mutual-groups-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-mutual-groups + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-mutual-groups + operationId: $sourceDescriptions.default.getMutualGroups + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-user-groups-friends + summary: Groups of every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-user-groups-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-user-groups-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-user-groups + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-user-groups + operationId: $sourceDescriptions.default.getUserGroups + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-user-groups-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-user-groups-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-user-groups + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-user-groups + operationId: $sourceDescriptions.default.getUserGroups + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-user-represented-group-friends + summary: Represented group of every friend + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: online-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-user-represented-group-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: online-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-user-represented-group-friends-online-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: online-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.online-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: online-friend-here + type: goto + stepId: online-represented-group + criteria: + - condition: $response.body#/0/id != null + - name: no-online-friends-left + type: goto + stepId: offline-reset + outputs: + friends: $response.body + + - stepId: online-represented-group + operationId: $sourceDescriptions.default.getUserRepresentedGroup + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.online-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-online-friend + type: goto + stepId: online-counter + + - stepId: offline-reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-user-represented-group-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: offline-counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-user-represented-group-friends-offline-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: offline-friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.offline-counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: offline-friend-here + type: goto + stepId: offline-represented-group + criteria: + - condition: $response.body#/0/id != null + - name: no-offline-friends-left + type: end + outputs: + friends: $response.body + + - stepId: offline-represented-group + operationId: $sourceDescriptions.default.getUserRepresentedGroup + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.offline-friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: next-offline-friend + type: goto + stepId: offline-counter + + - workflowId: get-world-friend-instances + summary: Get the world of every online friend in one + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-world-friend-instances-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-world-friend-instances-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: friend-here + type: goto + stepId: get-user + criteria: + - condition: $response.body#/0/id != null + - name: no-friends-left + type: end + outputs: + friends: $response.body + + - stepId: get-user + operationId: $sourceDescriptions.default.getUser + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId + in: path + value: $steps.friend.outputs.friends#/0/id + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: in-a-world + type: goto + stepId: get-world + criteria: + - context: $response.body#/worldId + condition: ^wrld_ + type: regex + - name: not-in-a-world + type: goto + stepId: counter + outputs: + worldId: $response.body#/worldId + instanceId: $response.body#/instanceId + + - stepId: get-world + operationId: $sourceDescriptions.default.getWorld + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: worldId + in: path + value: $steps.get-user.outputs.worldId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/id == $steps.get-user.outputs.worldId + onSuccess: + - name: next-friend + type: goto + stepId: counter + + - workflowId: get-instance-friend-instances + summary: Get the instance of every online friend in one + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: reset + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - await Bun.write(process.argv[1], "0") + - test/.out/get-instance-friend-instances-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + + - stepId: counter + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: bun + args: + - -e + - const offset = Number(await Bun.file(process.argv[1]).text()); + await Bun.write(process.argv[1], String(offset + 1)); + process.stdout.write(String(offset)) + - test/.out/get-instance-friend-instances-offset + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + outputs: + offset: $response.body#/stdout + + - stepId: friend + operationId: $sourceDescriptions.default.getFriends + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: offline + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: $steps.counter.outputs.offset + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: friend-here + type: goto + stepId: get-user + criteria: + - condition: $response.body#/0/id != null + - name: no-friends-left + type: end + outputs: + friends: $response.body + + - stepId: get-user + operationId: $sourceDescriptions.default.getUser + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + parameters: + - name: userId in: path - value: prnt_00000000-0000-0000-0000-000000000000 + value: $steps.friend.outputs.friends#/0/id successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + onSuccess: + - name: in-a-world + type: goto + stepId: get-instance + criteria: + - context: $response.body#/worldId + condition: ^wrld_ + type: regex + - name: not-in-a-world + type: goto + stepId: counter + outputs: + worldId: $response.body#/worldId + instanceId: $response.body#/instanceId - - workflowId: get-print-unauthenticated - summary: getPrint refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-print - operationId: $sourceDescriptions.default.getPrint + - stepId: get-instance + operationId: $sourceDescriptions.default.getInstance + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken parameters: - - name: printId + - name: worldId in: path - value: prnt_00000000-0000-0000-0000-000000000000 + value: $steps.get-user.outputs.worldId + - name: instanceId + in: path + value: $steps.get-user.outputs.instanceId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + - condition: $response.body#/worldId == $steps.get-user.outputs.worldId + onSuccess: + - name: next-friend + type: goto + stepId: counter - - workflowId: get-user-prints - summary: User prints + - workflowId: friend-note-update-restore + summary: Writes a note on a friend, checks every read of it, then restores the original parameters: - reference: $components.parameters.userAgent x-security: @@ -8721,137 +12035,223 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: user-prints - operationId: $sourceDescriptions.default.getUserPrints + - stepId: friend + operationId: $sourceDescriptions.default.getFriends + parameters: + - name: offline + in: query + value: true + - name: n + in: query + value: 1 + successCriteria: + - condition: $statusCode == 200 + onSuccess: + - name: friend-here + type: goto + stepId: read-original + criteria: + - condition: $response.body#/0/id != null + - name: no-friend + type: end + outputs: + friends: $response.body + + - stepId: read-original + operationId: $sourceDescriptions.default.getUser parameters: - name: userId in: path - value: $workflows.session.outputs.userId + value: $steps.friend.outputs.friends#/0/id successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + outputs: + note: $response.body#/note - - workflowId: get-user-prints-unauthenticated - summary: getUserPrints refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-user-prints - operationId: $sourceDescriptions.default.getUserPrints + - stepId: update-note + operationId: $sourceDescriptions.default.updateUserNote + requestBody: + contentType: application/json + payload: + targetUserId: $steps.friend.outputs.friends#/0/id + note: Written by the specification test suite + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/targetUserId == $steps.friend.outputs.friends#/0/id + - condition: $response.body#/note == 'Written by the specification test suite' + + - stepId: read-updated + operationId: $sourceDescriptions.default.getUser parameters: - name: userId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: $steps.friend.outputs.friends#/0/id successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + - condition: $response.body#/note == 'Written by the specification test suite' - - workflowId: upload-print-unauthenticated - summary: uploadPrint refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: upload-print - operationId: $sourceDescriptions.default.uploadPrint + - stepId: restore-note + operationId: $sourceDescriptions.default.updateUserNote + requestBody: + contentType: application/json + payload: + targetUserId: $steps.friend.outputs.friends#/0/id + note: $steps.read-original.outputs.note successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: delete-prop-not-found - summary: deleteProp refuses a resource that does not exist - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: delete-prop - operationId: $sourceDescriptions.default.deleteProp + - stepId: read-restored + operationId: $sourceDescriptions.default.getUser parameters: - - name: propId + - name: userId in: path - value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: $steps.friend.outputs.friends#/0/id successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 + - condition: $response.body#/note == $steps.read-original.outputs.note - - workflowId: delete-prop-unauthenticated - summary: deleteProp refuses an anonymous caller + - workflowId: get-user-unauthenticated + summary: getUser refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-prop - operationId: $sourceDescriptions.default.deleteProp + - stepId: get-user + operationId: $sourceDescriptions.default.getUser parameters: - - name: propId + - name: userId in: path - value: prop_00000000-0000-0000-0000-000000000000 + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: get-prop-not-found - summary: getProp refuses a resource that does not exist + - workflowId: get-user-unknown + summary: Update unknown user parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-prop - operationId: $sourceDescriptions.default.getProp + - stepId: update-unknown-user + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getUser parameters: - - name: propId + - name: userId in: path - value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 404 - - workflowId: get-prop-unauthenticated - summary: getProp refuses an anonymous caller + - workflowId: user-tag-round-trip + summary: Add a profile tag, confirm it applied, remove it, confirm it is gone parameters: - reference: $components.parameters.userAgent + failureActions: + - name: cleanup + type: goto + stepId: restore steps: - - stepId: get-prop - operationId: $sourceDescriptions.default.getProp + - stepId: verify-absent-first + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getUser parameters: - - name: propId + - name: userId in: path - value: prop_00000000-0000-0000-0000-000000000000 + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + - context: $response.body#/tags + condition: ^(?!.*language_kor).*$ + type: regex + onFailure: + - name: stop + type: end - - workflowId: get-prop-publish-status-not-found - summary: getPropPublishStatus refuses a resource that does not exist - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: get-prop-publish-status - operationId: $sourceDescriptions.default.getPropPublishStatus + - stepId: add-tag + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.addTags parameters: - - name: propId + - name: userId in: path - value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + tags: + - language_kor successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 + - context: $response.body#/tags + condition: language_kor + type: regex - - workflowId: list-props - summary: Props - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: props - operationId: $sourceDescriptions.default.listProps + - stepId: verify-applied + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 200 || $statusCode == 403 + - condition: $statusCode == 200 + - context: $response.body#/tags + condition: language_kor + type: regex + + - stepId: restore + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.removeTags + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + tags: + - language_kor + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - stepId: verify-restored + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getUser + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + - context: $response.body#/tags + condition: ^(?!.*language_kor).*$ + type: regex + onFailure: + - name: stop + type: end - - workflowId: list-props-query-parameters - summary: listProps with every fillable query parameter + - workflowId: get-user-all-group-permissions + summary: Group permissions parameters: - reference: $components.parameters.userAgent x-security: @@ -8859,34 +12259,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: list-props - operationId: $sourceDescriptions.default.listProps + - stepId: group-permissions + operationId: $sourceDescriptions.default.getUserAllGroupPermissions parameters: - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 + - name: userId + in: path + value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 - - workflowId: list-props-unauthenticated - summary: listProps refuses an anonymous caller + - workflowId: get-user-all-group-permissions-unauthenticated + summary: getUserAllGroupPermissions refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: list-props - operationId: $sourceDescriptions.default.listProps + - stepId: get-user-all-group-permissions + operationId: $sourceDescriptions.default.getUserAllGroupPermissions parameters: - - name: authorId - in: query - value: id_00000000-0000-0000-0000-000000000000 + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: publish-prop-not-found - summary: publishProp refuses a resource that does not exist + - workflowId: get-user-by-name + summary: User by name parameters: - reference: $components.parameters.userAgent x-security: @@ -8894,35 +12291,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: publish-prop - operationId: $sourceDescriptions.default.publishProp + - stepId: user-by-name + operationId: $sourceDescriptions.default.getUserByName parameters: - - name: propId + - name: username in: path - value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: $workflows.session.outputs.displayName successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 403 - - workflowId: unpublish-prop-not-found - summary: unpublishProp refuses a resource that does not exist + - workflowId: get-user-by-name-unauthenticated + summary: getUserByName refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: unpublish-prop - operationId: $sourceDescriptions.default.unpublishProp + - stepId: get-user-by-name + operationId: $sourceDescriptions.default.getUserByName parameters: - - name: propId + - name: username in: path - value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: test successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 401 - - workflowId: update-prop-not-found - summary: updateProp refuses a resource that does not exist + - workflowId: get-user-feedback + summary: User feedback parameters: - reference: $components.parameters.userAgent x-security: @@ -8930,45 +12323,28 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-prop - operationId: $sourceDescriptions.default.updateProp - parameters: - - name: propId - in: path - value: prop_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - successCriteria: - - condition: $statusCode == 400 - - - workflowId: add-tags - summary: Tag changes on another user are rejected - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: add-tag-other-user - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.addTags + - stepId: user-feedback + operationId: $sourceDescriptions.default.getUserFeedback parameters: - name: userId in: path - value: usr_00000000-0000-0000-0000-000000000000 - requestBody: - contentType: application/json - payload: - tags: - - language_kor + value: $workflows.session.outputs.userId + - name: n + in: query + value: 100 + - name: offset + in: query + value: 0 successCriteria: - - condition: $statusCode == 401 || $statusCode == 403 || $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: add-tags-unauthenticated - summary: addTags refuses an anonymous caller + - workflowId: get-user-feedback-unauthenticated + summary: getUserFeedback refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: add-tags - operationId: $sourceDescriptions.default.addTags + - stepId: get-user-feedback + operationId: $sourceDescriptions.default.getUserFeedback parameters: - name: userId in: path @@ -8976,8 +12352,8 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: check-user-persistence-exists-not-found - summary: checkUserPersistenceExists refuses a resource that does not exist + - workflowId: get-user-group-instances + summary: Group instances parameters: - reference: $components.parameters.userAgent x-security: @@ -8985,51 +12361,48 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: check-user-persistence-exists - operationId: $sourceDescriptions.default.checkUserPersistenceExists + - stepId: group-instances + operationId: $sourceDescriptions.default.getUserGroupInstances parameters: - name: userId in: path - value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: worldId - in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 - - workflowId: check-user-persistence-exists-unauthenticated - summary: checkUserPersistenceExists refuses an anonymous caller + - workflowId: get-user-group-instances-unauthenticated + summary: getUserGroupInstances refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: check-user-persistence-exists - operationId: $sourceDescriptions.default.checkUserPersistenceExists + - stepId: get-user-group-instances + operationId: $sourceDescriptions.default.getUserGroupInstances parameters: - name: userId in: path value: usr_00000000-0000-0000-0000-000000000000 - - name: worldId - in: path - value: wrld_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: delete-all-user-persistence-data-unauthenticated - summary: deleteAllUserPersistenceData refuses an anonymous caller + - workflowId: get-user-group-instances-for-group-unauthenticated + summary: getUserGroupInstancesForGroup refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-all-user-persistence-data - operationId: $sourceDescriptions.default.deleteAllUserPersistenceData + - stepId: get-user-group-instances-for-group + operationId: $sourceDescriptions.default.getUserGroupInstancesForGroup parameters: - name: userId in: path value: usr_00000000-0000-0000-0000-000000000000 + - name: groupId + in: path + value: grp_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: delete-user-persistence-not-found - summary: deleteUserPersistence refuses a resource that does not exist + - workflowId: get-user-group-requests + summary: Group requests parameters: - reference: $components.parameters.userAgent x-security: @@ -9037,37 +12410,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: delete-user-persistence - operationId: $sourceDescriptions.default.deleteUserPersistence + - stepId: group-requests + operationId: $sourceDescriptions.default.getUserGroupRequests parameters: - name: userId in: path - value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: worldId - in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 - - workflowId: delete-user-persistence-unauthenticated - summary: deleteUserPersistence refuses an anonymous caller + - workflowId: get-user-group-requests-unauthenticated + summary: getUserGroupRequests refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-user-persistence - operationId: $sourceDescriptions.default.deleteUserPersistence + - stepId: get-user-group-requests + operationId: $sourceDescriptions.default.getUserGroupRequests parameters: - name: userId in: path value: usr_00000000-0000-0000-0000-000000000000 - - name: worldId - in: path - value: wrld_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: get-blocked-groups - summary: Blocked groups + - workflowId: get-user-groups + summary: User groups parameters: - reference: $components.parameters.userAgent x-security: @@ -9075,8 +12442,8 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: blocked-groups - operationId: $sourceDescriptions.default.getBlockedGroups + - stepId: user-groups + operationId: $sourceDescriptions.default.getUserGroups parameters: - name: userId in: path @@ -9084,13 +12451,13 @@ workflows: successCriteria: - condition: $statusCode == 200 - - workflowId: get-blocked-groups-unauthenticated - summary: getBlockedGroups refuses an anonymous caller + - workflowId: get-user-groups-unauthenticated + summary: getUserGroups refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-blocked-groups - operationId: $sourceDescriptions.default.getBlockedGroups + - stepId: get-user-groups + operationId: $sourceDescriptions.default.getUserGroups parameters: - name: userId in: path @@ -9098,140 +12465,146 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: profile-update-restore - summary: Update the writable profile fields, confirm they applied, restore them + - workflowId: group-cancel-request + summary: Cancelling a join request we never made + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: marker - operationId: $sourceDescriptions.local.execute - requestBody: - contentType: application/json - payload: - command: sh - args: - - -c - - openssl rand -hex 6 | tr -d '\n' + - stepId: cancel-request + operationId: $sourceDescriptions.default.cancelGroupRequest + parameters: + - name: groupId + in: path + value: $inputs.groupId + successCriteria: + - condition: $statusCode == 400 + + - workflowId: group-owner-cannot-leave + summary: The owner is refused when leaving their own group + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: fixture-group + operationId: $sourceDescriptions.default.getGroup + parameters: + - name: groupId + in: path + value: $inputs.groupId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/exitCode == 0 + - condition: $response.body#/ownerId == $workflows.session.outputs.userId onFailure: - name: stop type: end - outputs: - value: $response.body#/stdout - - - stepId: current-before - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getCurrentUser + - stepId: leave + operationId: $sourceDescriptions.default.leaveGroup + parameters: + - name: groupId + in: path + value: $inputs.groupId successCriteria: - - condition: $statusCode == 200 - onFailure: - - name: stop - type: end - - outputs: - bioLinks: $response.body#/bioLinks - pronouns: $response.body#/pronouns - status: $response.body#/status - statusDescription: $response.body#/statusDescription - isBoopingEnabled: $response.body#/isBoopingEnabled - unsubscribe: $response.body#/unsubscribe + - condition: $statusCode == 403 - - stepId: update-profile - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.updateUser + - workflowId: group-representation + summary: Represent the group, then stop representing it + inputs: + type: object + required: + - groupId + properties: + groupId: + type: string + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: represent + operationId: $sourceDescriptions.default.updateGroupRepresentation parameters: - - name: userId + - name: groupId in: path - value: $workflows.session.outputs.userId + value: $inputs.groupId requestBody: contentType: application/json payload: - bio: $steps.marker.outputs.value - statusDescription: $steps.marker.outputs.value - pronouns: they/them - status: active - bioLinks: $steps.current-before.outputs.bioLinks - isBoopingEnabled: $steps.current-before.outputs.isBoopingEnabled - unsubscribe: $steps.current-before.outputs.unsubscribe + isRepresenting: true successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/bio == $steps.marker.outputs.value - - condition: $response.body#/statusDescription == $steps.marker.outputs.value - - condition: $response.body#/pronouns == 'they/them' - - condition: $response.body#/status == 'active' - - stepId: verify-current-user - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getCurrentUser + - stepId: represented-group + operationId: $sourceDescriptions.default.getUserRepresentedGroup + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/bio == $steps.marker.outputs.value + - condition: $response.body#/isRepresenting == true - - stepId: verify-get-user - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUser + - stepId: public-profile + operationId: $sourceDescriptions.default.getPublicProfile parameters: - name: userId in: path value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/bio == $steps.marker.outputs.value - - stepId: restore-profile - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.updateUser + - stepId: stop-representing + operationId: $sourceDescriptions.default.updateGroupRepresentation parameters: - - name: userId + - name: groupId in: path - value: $workflows.session.outputs.userId + value: $inputs.groupId requestBody: contentType: application/json payload: - bio: "" - statusDescription: $steps.current-before.outputs.statusDescription - pronouns: $steps.current-before.outputs.pronouns - status: $steps.current-before.outputs.status + isRepresenting: false successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/bio == '' - - condition: $response.body#/pronouns == $steps.current-before.outputs.pronouns - - condition: $response.body#/status == $steps.current-before.outputs.status - - stepId: verify-restored - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUser + - workflowId: get-user-note-unauthenticated + summary: getUserNote refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-user-note + operationId: $sourceDescriptions.default.getUserNote parameters: - - name: userId + - name: userNoteId in: path - value: $workflows.session.outputs.userId + value: unot_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/bio == '' + - condition: $statusCode == 401 - - workflowId: get-invited-groups - summary: Invited groups + - workflowId: get-user-notes + summary: User notes parameters: - reference: $components.parameters.userAgent x-security: @@ -9239,31 +12612,30 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: invited-groups - operationId: $sourceDescriptions.default.getInvitedGroups + - stepId: user-notes + operationId: $sourceDescriptions.default.getUserNotes parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - name: n + in: query + value: 100 + - name: offset + in: query + value: 0 successCriteria: - condition: $statusCode == 200 - - workflowId: get-invited-groups-unauthenticated - summary: getInvitedGroups refuses an anonymous caller + - workflowId: get-user-notes-unauthenticated + summary: getUserNotes refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-invited-groups - operationId: $sourceDescriptions.default.getInvitedGroups - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - stepId: get-user-notes + operationId: $sourceDescriptions.default.getUserNotes successCriteria: - condition: $statusCode == 401 - - workflowId: get-mutual-friends - summary: Mutual friends + - workflowId: get-user-represented-group + summary: Represented group parameters: - reference: $components.parameters.userAgent x-security: @@ -9271,8 +12643,8 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: mutual-friends - operationId: $sourceDescriptions.default.getMutualFriends + - stepId: represented-group + operationId: $sourceDescriptions.default.getUserRepresentedGroup parameters: - name: userId in: path @@ -9280,8 +12652,22 @@ workflows: successCriteria: - condition: $statusCode == 200 - - workflowId: get-mutual-friends-query-parameters - summary: getMutualFriends with every fillable query parameter + - workflowId: get-user-represented-group-unauthenticated + summary: getUserRepresentedGroup refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: get-user-represented-group + operationId: $sourceDescriptions.default.getUserRepresentedGroup + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-user-tutorial-status + summary: Tutorial status parameters: - reference: $components.parameters.userAgent x-security: @@ -9289,28 +12675,22 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-mutual-friends - operationId: $sourceDescriptions.default.getMutualFriends + - stepId: tutorial-status + operationId: $sourceDescriptions.default.getUserTutorialStatus parameters: - name: userId in: path value: $workflows.session.outputs.userId - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 successCriteria: - condition: $statusCode == 200 - - workflowId: get-mutual-friends-unauthenticated - summary: getMutualFriends refuses an anonymous caller + - workflowId: get-user-tutorial-status-unauthenticated + summary: getUserTutorialStatus refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-mutual-friends - operationId: $sourceDescriptions.default.getMutualFriends + - stepId: get-user-tutorial-status + operationId: $sourceDescriptions.default.getUserTutorialStatus parameters: - name: userId in: path @@ -9318,8 +12698,8 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: get-mutual-groups - summary: Mutual groups + - workflowId: get-user-tutorial-status-platforms + summary: getUserTutorialStatus keys a tutorial by the platform and store headers parameters: - reference: $components.parameters.userAgent x-security: @@ -9327,17 +12707,72 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: mutual-groups - operationId: $sourceDescriptions.default.getMutualGroups + - stepId: read-android + operationId: $sourceDescriptions.default.getUserTutorialStatus parameters: - name: userId in: path value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: android + - name: X-Store + in: header + value: suite successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/tutorialKey == 'android:suite:v1' - - workflowId: get-mutual-groups-query-parameters - summary: getMutualGroups with every fillable query parameter + - stepId: read-ios + operationId: $sourceDescriptions.default.getUserTutorialStatus + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: ios + - name: X-Store + in: header + value: suite + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/tutorialKey == 'ios:suite:v1' + + - stepId: read-standalonewindows + operationId: $sourceDescriptions.default.getUserTutorialStatus + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: standalonewindows + - name: X-Store + in: header + value: suite + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/tutorialKey == 'standalonewindows:suite:v1' + + - stepId: read-spectest + operationId: $sourceDescriptions.default.getUserTutorialStatus + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: spectest + - name: X-Store + in: header + value: suite + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/tutorialKey == 'null:suite:v1' + + - workflowId: user-tutorial-lifecycle + summary: Completes a tutorial, clears every platform tutorial, then restores the account's own parameters: - reference: $components.parameters.userAgent x-security: @@ -9345,37 +12780,99 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-mutual-groups - operationId: $sourceDescriptions.default.getMutualGroups + - stepId: complete + operationId: $sourceDescriptions.default.completeUserTutorial parameters: - name: userId in: path value: $workflows.session.outputs.userId - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 + - name: X-Platform + in: header + value: spectest + - name: X-Store + in: header + value: suite + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/id == $workflows.session.outputs.userId + onFailure: + - name: stop + type: end + + - stepId: read-completed + operationId: $sourceDescriptions.default.getUserTutorialStatus + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: spectest + - name: X-Store + in: header + value: suite + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/completed == true + - condition: $response.body#/tutorialKey == 'null:suite:v1' + onFailure: + - name: stop + type: end + + - stepId: clear + operationId: $sourceDescriptions.default.clearUserTutorials + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: spectest + - name: X-Store + in: header + value: suite + successCriteria: + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end + + - stepId: restore + operationId: $sourceDescriptions.default.completeUserTutorial + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: standalonewindows + - name: X-Store + in: header + value: steam successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: get-mutual-groups-unauthenticated - summary: getMutualGroups refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-mutual-groups - operationId: $sourceDescriptions.default.getMutualGroups + - stepId: read-restored + operationId: $sourceDescriptions.default.getUserTutorialStatus parameters: - name: userId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: $workflows.session.outputs.userId + - name: X-Platform + in: header + value: spectest + - name: X-Store + in: header + value: suite successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + - condition: $response.body#/completed == false - - workflowId: get-mutuals - summary: Mutuals + - workflowId: complete-user-tutorial-forbidden + summary: completeUserTutorial refuses another user's tutorials parameters: - reference: $components.parameters.userAgent x-security: @@ -9383,22 +12880,22 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: mutuals - operationId: $sourceDescriptions.default.getMutuals + - stepId: complete-user-tutorial + operationId: $sourceDescriptions.default.completeUserTutorial parameters: - name: userId in: path - value: $workflows.session.outputs.userId + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 403 - - workflowId: get-mutuals-unauthenticated - summary: getMutuals refuses an anonymous caller + - workflowId: complete-user-tutorial-unauthenticated + summary: completeUserTutorial refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-mutuals - operationId: $sourceDescriptions.default.getMutuals + - stepId: complete-user-tutorial + operationId: $sourceDescriptions.default.completeUserTutorial parameters: - name: userId in: path @@ -9406,8 +12903,8 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: get-private-profile - summary: Private profile + - workflowId: clear-user-tutorials-forbidden + summary: clearUserTutorials refuses another user's tutorials parameters: - reference: $components.parameters.userAgent x-security: @@ -9415,22 +12912,22 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: private-profile - operationId: $sourceDescriptions.default.getPrivateProfile + - stepId: clear-user-tutorials + operationId: $sourceDescriptions.default.clearUserTutorials parameters: - name: userId in: path - value: $workflows.session.outputs.userId + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 403 - - workflowId: get-private-profile-unauthenticated - summary: getPrivateProfile refuses an anonymous caller + - workflowId: clear-user-tutorials-unauthenticated + summary: clearUserTutorials refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-private-profile - operationId: $sourceDescriptions.default.getPrivateProfile + - stepId: clear-user-tutorials + operationId: $sourceDescriptions.default.clearUserTutorials parameters: - name: userId in: path @@ -9438,40 +12935,40 @@ workflows: successCriteria: - condition: $statusCode == 401 - - workflowId: get-public-profile - summary: Public profile + - workflowId: remove-tags-unauthenticated + summary: removeTags refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: public-profile - operationId: $sourceDescriptions.default.getPublicProfile + - stepId: remove-tags + operationId: $sourceDescriptions.default.removeTags parameters: - name: userId in: path - value: $workflows.session.outputs.userId + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: get-public-profile-unauthenticated - summary: getPublicProfile refuses an anonymous caller + - workflowId: search-active-users + summary: Active user search is withdrawn parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-public-profile - operationId: $sourceDescriptions.default.getPublicProfile + - stepId: search-active-users + operationId: $sourceDescriptions.default.searchActiveUsers parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - name: search + in: query + value: test successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 404 - - workflowId: get-user - summary: Get user + - workflowId: search-users + summary: Search users parameters: - reference: $components.parameters.userAgent x-security: @@ -9479,18 +12976,17 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-user - operationId: $sourceDescriptions.default.getUser + - stepId: search-users + operationId: $sourceDescriptions.default.searchUsers parameters: - - name: userId - in: path - value: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + - name: search + in: query + value: tupper successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/id == 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' - - workflowId: get-user-not-found - summary: getUser refuses a resource that does not exist + - workflowId: search-users-no-parameters + summary: Search no parameters parameters: - reference: $components.parameters.userAgent x-security: @@ -9498,17 +12994,13 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-user - operationId: $sourceDescriptions.default.getUser - parameters: - - name: userId - in: path - value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - stepId: search-no-parameters + operationId: $sourceDescriptions.default.searchUsers successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: get-user-own - summary: Get own user + - workflowId: search-users-query-parameters + summary: searchUsers with every fillable query parameter parameters: - reference: $components.parameters.userAgent x-security: @@ -9516,145 +13008,182 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-own-user - operationId: $sourceDescriptions.default.getUser + - stepId: search-users + operationId: $sourceDescriptions.default.searchUsers parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - name: isInternalVariant + in: query + value: false + - name: offset + in: query + value: 1 successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/id == $workflows.session.outputs.userId - - workflowId: get-user-unauthenticated - summary: getUser refuses an anonymous caller + - workflowId: search-users-unauthenticated + summary: searchUsers refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user - operationId: $sourceDescriptions.default.getUser - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - stepId: search-users + operationId: $sourceDescriptions.default.searchUsers successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-unknown - summary: Update unknown user + - workflowId: search-users-with-limit + summary: Search with limit parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-unknown-user - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUser + - stepId: search-with-limit + operationId: $sourceDescriptions.default.searchUsers + parameters: + - name: search + in: query + value: a + - name: n + in: query + value: 5 + successCriteria: + - condition: $statusCode == 200 + + - workflowId: update-badge-not-found + summary: updateBadge refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: update-badge + operationId: $sourceDescriptions.default.updateBadge parameters: - name: userId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: badgeId + in: path + value: id_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 403 - - workflowId: user-tag-round-trip - summary: Add a profile tag, confirm it applied, remove it, confirm it is gone + - workflowId: update-badge-unauthenticated + summary: updateBadge refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: verify-absent-first - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUser + - stepId: update-badge + operationId: $sourceDescriptions.default.updateBadge parameters: - name: userId in: path - value: $workflows.session.outputs.userId + value: usr_00000000-0000-0000-0000-000000000000 + - name: badgeId + in: path + value: bdg_00000000-0000-0000-0000-000000000000 successCriteria: - - condition: $statusCode == 200 - - context: $response.body#/tags - condition: ^(?!.*language_kor).*$ - type: regex - onFailure: - - name: stop - type: end + - condition: $statusCode == 401 - - stepId: add-tag + - workflowId: update-user + summary: Update other user + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: update-other-user x-security: - schemeName: authCookie values: apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.addTags + operationId: $sourceDescriptions.default.updateUser parameters: - name: userId in: path - value: $workflows.session.outputs.userId + value: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 requestBody: contentType: application/json payload: - tags: - - language_kor + bio: should-be-rejected successCriteria: - - condition: $statusCode == 200 - - context: $response.body#/tags - condition: language_kor - type: regex + - condition: $statusCode == 401 || $statusCode == 403 - - stepId: verify-applied - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUser - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - workflowId: update-user-note-unauthenticated + summary: updateUserNote refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: update-user-note + operationId: $sourceDescriptions.default.updateUserNote successCriteria: - - condition: $statusCode == 200 - - context: $response.body#/tags - condition: language_kor - type: regex - - - stepId: restore - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.removeTags - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - condition: $statusCode == 401 + - workflowId: user-note-lifecycle + summary: Writes a note against another user, then reads it back by id + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: update-note + operationId: $sourceDescriptions.default.updateUserNote requestBody: contentType: application/json payload: - tags: - - language_kor + targetUserId: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 + note: system_haha_we_actually_ended_up_documenting_this_one_too successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/targetUserId == + 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' + onFailure: + - name: stop + type: end - - stepId: verify-restored - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.getUser + outputs: + userNoteId: $response.body#/id + + - stepId: get-note + operationId: $sourceDescriptions.default.getUserNote parameters: - - name: userId + - name: userNoteId in: path - value: $workflows.session.outputs.userId + value: $steps.update-note.outputs.userNoteId successCriteria: - condition: $statusCode == 200 - - context: $response.body#/tags - condition: ^(?!.*language_kor).*$ - type: regex + - condition: $response.body#/targetUserId == + 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' - - workflowId: get-user-all-group-permissions - summary: Group permissions + - workflowId: add-world-tags-unauthenticated + summary: addWorldTags refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: add-world-tags + operationId: $sourceDescriptions.default.addWorldTags + parameters: + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: create-world-unauthenticated + summary: createWorld refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: create-world + operationId: $sourceDescriptions.default.createWorld + successCriteria: + - condition: $statusCode == 401 + + - workflowId: delete-world-not-found + summary: deleteWorld refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -9662,31 +13191,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: group-permissions - operationId: $sourceDescriptions.default.getUserAllGroupPermissions + - stepId: delete-world + operationId: $sourceDescriptions.default.deleteWorld parameters: - - name: userId + - name: worldId in: path - value: $workflows.session.outputs.userId + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - condition: $statusCode == 200 - - workflowId: get-user-all-group-permissions-unauthenticated - summary: getUserAllGroupPermissions refuses an anonymous caller + - workflowId: delete-world-unauthenticated + summary: deleteWorld refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-all-group-permissions - operationId: $sourceDescriptions.default.getUserAllGroupPermissions + - stepId: delete-world + operationId: $sourceDescriptions.default.deleteWorld parameters: - - name: userId + - name: worldId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: wrld_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-by-name - summary: User by name + - workflowId: delete-world-platform-not-found + summary: deleteWorldPlatform refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -9694,31 +13223,37 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: user-by-name - operationId: $sourceDescriptions.default.getUserByName + - stepId: delete-world-platform + operationId: $sourceDescriptions.default.deleteWorldPlatform parameters: - - name: username + - name: worldId in: path - value: $workflows.session.outputs.displayName + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - name: publishedPlatform + in: path + value: standalonewindows successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 404 - - workflowId: get-user-by-name-unauthenticated - summary: getUserByName refuses an anonymous caller + - workflowId: delete-world-platform-unauthenticated + summary: deleteWorldPlatform refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-by-name - operationId: $sourceDescriptions.default.getUserByName + - stepId: delete-world-platform + operationId: $sourceDescriptions.default.deleteWorldPlatform parameters: - - name: username + - name: worldId in: path - value: test + value: wrld_00000000-0000-0000-0000-000000000000 + - name: publishedPlatform + in: path + value: standalonewindows successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-feedback - summary: User feedback + - workflowId: get-active-worlds + summary: Active worlds parameters: - reference: $components.parameters.userAgent x-security: @@ -9726,37 +13261,56 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: user-feedback - operationId: $sourceDescriptions.default.getUserFeedback + - stepId: active-worlds + operationId: $sourceDescriptions.default.getActiveWorlds + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-active-worlds-query-parameters + summary: getActiveWorlds with every fillable query parameter + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: get-active-worlds + operationId: $sourceDescriptions.default.getActiveWorlds parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - name: featured + in: query + value: false - name: n in: query - value: 100 + value: 1 - name: offset in: query - value: 0 + value: 1 + - name: order + in: query + value: ascending + - name: releaseStatus + in: query + value: public + - name: sort + in: query + value: _created_at successCriteria: - condition: $statusCode == 200 - - workflowId: get-user-feedback-unauthenticated - summary: getUserFeedback refuses an anonymous caller + - workflowId: get-active-worlds-unauthenticated + summary: getActiveWorlds refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-feedback - operationId: $sourceDescriptions.default.getUserFeedback - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - stepId: get-active-worlds + operationId: $sourceDescriptions.default.getActiveWorlds successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-group-instances - summary: Group instances + - workflowId: get-favorited-worlds + summary: Favorited worlds parameters: - reference: $components.parameters.userAgent x-security: @@ -9764,48 +13318,56 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: group-instances - operationId: $sourceDescriptions.default.getUserGroupInstances - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - stepId: favorited-worlds + operationId: $sourceDescriptions.default.getFavoritedWorlds successCriteria: - condition: $statusCode == 200 - - workflowId: get-user-group-instances-unauthenticated - summary: getUserGroupInstances refuses an anonymous caller + - workflowId: get-favorited-worlds-query-parameters + summary: getFavoritedWorlds with every fillable query parameter parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-user-group-instances - operationId: $sourceDescriptions.default.getUserGroupInstances + - stepId: get-favorited-worlds + operationId: $sourceDescriptions.default.getFavoritedWorlds parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - name: featured + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: 1 + - name: order + in: query + value: ascending + - name: releaseStatus + in: query + value: public + - name: sort + in: query + value: _created_at successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-user-group-instances-for-group-unauthenticated - summary: getUserGroupInstancesForGroup refuses an anonymous caller + - workflowId: get-favorited-worlds-unauthenticated + summary: getFavoritedWorlds refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-group-instances-for-group - operationId: $sourceDescriptions.default.getUserGroupInstancesForGroup - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: groupId - in: path - value: grp_00000000-0000-0000-0000-000000000000 + - stepId: get-favorited-worlds + operationId: $sourceDescriptions.default.getFavoritedWorlds successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-group-requests - summary: Group requests + - workflowId: get-recent-worlds + summary: Recent worlds parameters: - reference: $components.parameters.userAgent x-security: @@ -9813,31 +13375,13 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: group-requests - operationId: $sourceDescriptions.default.getUserGroupRequests - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - - workflowId: get-user-group-requests-unauthenticated - summary: getUserGroupRequests refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-user-group-requests - operationId: $sourceDescriptions.default.getUserGroupRequests - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - stepId: recent-worlds + operationId: $sourceDescriptions.default.getRecentWorlds successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: get-user-groups - summary: User groups + - workflowId: get-recent-worlds-query-parameters + summary: getRecentWorlds with every fillable query parameter parameters: - reference: $components.parameters.userAgent x-security: @@ -9845,31 +13389,42 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: user-groups - operationId: $sourceDescriptions.default.getUserGroups + - stepId: get-recent-worlds + operationId: $sourceDescriptions.default.getRecentWorlds parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId + - name: featured + in: query + value: false + - name: n + in: query + value: 1 + - name: offset + in: query + value: 1 + - name: order + in: query + value: ascending + - name: releaseStatus + in: query + value: public + - name: sort + in: query + value: _created_at successCriteria: - condition: $statusCode == 200 - - workflowId: get-user-groups-unauthenticated - summary: getUserGroups refuses an anonymous caller + - workflowId: get-recent-worlds-unauthenticated + summary: getRecentWorlds refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 + - stepId: get-recent-worlds + operationId: $sourceDescriptions.default.getRecentWorlds successCriteria: - condition: $statusCode == 401 - - workflowId: group-cancel-request - summary: Cancelling a join request we never made + - workflowId: get-world-black-cat + summary: Black cat parameters: - reference: $components.parameters.userAgent x-security: @@ -9877,33 +13432,19 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups + - stepId: black-cat + operationId: $sourceDescriptions.default.getWorld parameters: - - name: userId + - name: worldId in: path - value: $workflows.session.outputs.userId + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - - stepId: cancel-request - operationId: $sourceDescriptions.default.cancelGroupRequest - parameters: - - name: groupId - in: path - value: $steps.own-groups.outputs.groupId - successCriteria: - - condition: $statusCode == 400 + - condition: $response.body#/id == 'wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b' + - condition: $response.body#/storeId != null - - workflowId: group-owner-cannot-leave - summary: The owner is refused when leaving their own group + - workflowId: get-world-not-found + summary: getWorld refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -9911,33 +13452,17 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/ownerId == $workflows.session.outputs.userId - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - - stepId: leave - operationId: $sourceDescriptions.default.leaveGroup + - stepId: get-world + operationId: $sourceDescriptions.default.getWorld parameters: - - name: groupId + - name: worldId in: path - value: $steps.own-groups.outputs.groupId + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 404 - - workflowId: group-representation - summary: Represent the group, then stop representing it + - workflowId: get-world-vrchat-home + summary: Vrchat home parameters: - reference: $components.parameters.userAgent x-security: @@ -9945,83 +13470,35 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: own-groups - operationId: $sourceDescriptions.default.getUserGroups - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/0/groupId != null - onFailure: - - name: stop - type: end - - outputs: - groupId: $response.body#/0/groupId - - - stepId: represent - operationId: $sourceDescriptions.default.updateGroupRepresentation - parameters: - - name: groupId - in: path - value: $steps.own-groups.outputs.groupId - requestBody: - contentType: application/json - payload: - isRepresenting: true - successCriteria: - - condition: $statusCode == 200 - - - stepId: represented-group - operationId: $sourceDescriptions.default.getUserRepresentedGroup - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - condition: $response.body#/isRepresenting == true - - - stepId: public-profile - operationId: $sourceDescriptions.default.getPublicProfile - parameters: - - name: userId - in: path - value: $workflows.session.outputs.userId - successCriteria: - - condition: $statusCode == 200 - - - stepId: stop-representing - operationId: $sourceDescriptions.default.updateGroupRepresentation + - stepId: vrchat-home + operationId: $sourceDescriptions.default.getWorld parameters: - - name: groupId + - name: worldId in: path - value: $steps.own-groups.outputs.groupId - requestBody: - contentType: application/json - payload: - isRepresenting: false + value: wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/id == 'wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd' - - workflowId: get-user-note-unauthenticated - summary: getUserNote refuses an anonymous caller + - workflowId: get-world-instance-unauthenticated + summary: getWorldInstance refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-note - operationId: $sourceDescriptions.default.getUserNote + - stepId: get-world-instance + operationId: $sourceDescriptions.default.getWorldInstance parameters: - - name: userNoteId + - name: worldId in: path - value: unot_00000000-0000-0000-0000-000000000000 + value: wrld_00000000-0000-0000-0000-000000000000 + - name: instanceId + in: path + value: 0 successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-notes - summary: User notes + - workflowId: get-world-metadata + summary: World metadata parameters: - reference: $components.parameters.userAgent x-security: @@ -10029,30 +13506,35 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: user-notes - operationId: $sourceDescriptions.default.getUserNotes + - stepId: world-metadata + operationId: $sourceDescriptions.default.getWorldMetadata parameters: - - name: n - in: query - value: 100 - - name: offset - in: query - value: 0 + - name: worldId + in: path + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b successCriteria: - condition: $statusCode == 200 - - workflowId: get-user-notes-unauthenticated - summary: getUserNotes refuses an anonymous caller + - workflowId: get-world-metadata-not-found + summary: getWorldMetadata refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-user-notes - operationId: $sourceDescriptions.default.getUserNotes + - stepId: get-world-metadata + operationId: $sourceDescriptions.default.getWorldMetadata + parameters: + - name: worldId + in: path + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 404 - - workflowId: get-user-represented-group - summary: Represented group + - workflowId: get-world-publish-status + summary: World publish status parameters: - reference: $components.parameters.userAgent x-security: @@ -10060,31 +13542,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: represented-group - operationId: $sourceDescriptions.default.getUserRepresentedGroup + - stepId: world-publish-status + operationId: $sourceDescriptions.default.getWorldPublishStatus parameters: - - name: userId + - name: worldId in: path - value: $workflows.session.outputs.userId + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b successCriteria: - condition: $statusCode == 200 - - workflowId: get-user-represented-group-unauthenticated - summary: getUserRepresentedGroup refuses an anonymous caller + - workflowId: get-world-publish-status-unauthenticated + summary: getWorldPublishStatus refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-represented-group - operationId: $sourceDescriptions.default.getUserRepresentedGroup + - stepId: get-world-publish-status + operationId: $sourceDescriptions.default.getWorldPublishStatus parameters: - - name: userId + - name: worldId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: wrld_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: get-user-tutorial-status - summary: Tutorial status + - workflowId: publish-world-not-found + summary: publishWorld refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -10092,45 +13574,54 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: tutorial-status - operationId: $sourceDescriptions.default.getUserTutorialStatus + - stepId: publish-world + operationId: $sourceDescriptions.default.publishWorld parameters: - - name: userId + - name: worldId in: path - value: $workflows.session.outputs.userId + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 404 - - workflowId: get-user-tutorial-status-unauthenticated - summary: getUserTutorialStatus refuses an anonymous caller + - workflowId: publish-world-unauthenticated + summary: publishWorld refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-user-tutorial-status - operationId: $sourceDescriptions.default.getUserTutorialStatus + - stepId: publish-world + operationId: $sourceDescriptions.default.publishWorld parameters: - - name: userId + - name: worldId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: wrld_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: remove-tags-unauthenticated - summary: removeTags refuses an anonymous caller + - workflowId: remove-world-tags + summary: Removing tags from a world we do not own is refused parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - stepId: remove-tags - operationId: $sourceDescriptions.default.removeTags + operationId: $sourceDescriptions.default.removeWorldTags parameters: - - name: userId + - name: worldId in: path - value: usr_00000000-0000-0000-0000-000000000000 + value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + requestBody: + contentType: application/json + payload: + tags: + - author_tag_test successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 403 - - workflowId: search-active-users - summary: Active user search is withdrawn + - workflowId: search-worlds + summary: Search worlds parameters: - reference: $components.parameters.userAgent x-security: @@ -10138,17 +13629,13 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-active-users - operationId: $sourceDescriptions.default.searchActiveUsers - parameters: - - name: search - in: query - value: test + - stepId: search-worlds + operationId: $sourceDescriptions.default.searchWorlds successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: search-users - summary: Search users + - workflowId: search-worlds-friends + summary: searchWorlds for the worlds of the caller's friends parameters: - reference: $components.parameters.userAgent x-security: @@ -10156,17 +13643,17 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-users - operationId: $sourceDescriptions.default.searchUsers + - stepId: search-worlds + operationId: $sourceDescriptions.default.searchWorlds parameters: - - name: search + - name: user in: query - value: tupper + value: friends successCriteria: - condition: $statusCode == 200 - - workflowId: search-users-no-parameters - summary: Search no parameters + - workflowId: search-worlds-invalid-user + summary: searchWorlds names the values user accepts parameters: - reference: $components.parameters.userAgent x-security: @@ -10174,13 +13661,17 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-no-parameters - operationId: $sourceDescriptions.default.searchUsers + - stepId: search-worlds + operationId: $sourceDescriptions.default.searchWorlds + parameters: + - name: user + in: query + value: x successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 400 - - workflowId: search-users-query-parameters - summary: searchUsers with every fillable query parameter + - workflowId: search-worlds-query-parameters + summary: searchWorlds with every fillable query parameter parameters: - reference: $components.parameters.userAgent x-security: @@ -10188,30 +13679,51 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-users - operationId: $sourceDescriptions.default.searchUsers + - stepId: search-worlds + operationId: $sourceDescriptions.default.searchWorlds parameters: - - name: isInternalVariant + - name: avatarSpecific + in: query + value: false + - name: featured + in: query + value: false + - name: fuzzy in: query value: false + - name: n + in: query + value: 1 - name: offset in: query value: 1 + - name: order + in: query + value: ascending + - name: releaseStatus + in: query + value: public + - name: sort + in: query + value: _created_at + - name: user + in: query + value: me successCriteria: - condition: $statusCode == 200 - - workflowId: search-users-unauthenticated - summary: searchUsers refuses an anonymous caller + - workflowId: search-worlds-unauthenticated + summary: searchWorlds refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: search-users - operationId: $sourceDescriptions.default.searchUsers + - stepId: search-worlds + operationId: $sourceDescriptions.default.searchWorlds successCriteria: - condition: $statusCode == 401 - - workflowId: search-users-with-limit - summary: Search with limit + - workflowId: unpublish-world-not-found + summary: unpublishWorld refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -10219,20 +13731,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-with-limit - operationId: $sourceDescriptions.default.searchUsers + - stepId: unpublish-world + operationId: $sourceDescriptions.default.unpublishWorld parameters: - - name: search - in: query - value: a - - name: n - in: query - value: 5 + - name: worldId + in: path + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 404 - - workflowId: update-badge-not-found - summary: updateBadge refuses a resource that does not exist + - workflowId: unpublish-world-unauthenticated + summary: unpublishWorld refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: unpublish-world + operationId: $sourceDescriptions.default.unpublishWorld + parameters: + - name: worldId + in: path + value: wrld_00000000-0000-0000-0000-000000000000 + successCriteria: + - condition: $statusCode == 401 + + - workflowId: update-world-not-found + summary: updateWorld refuses a resource that does not exist parameters: - reference: $components.parameters.userAgent x-security: @@ -10240,68 +13763,67 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-badge - operationId: $sourceDescriptions.default.updateBadge + - stepId: update-world + operationId: $sourceDescriptions.default.updateWorld parameters: - - name: userId - in: path - value: usr_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: badgeId + - name: worldId in: path - value: id_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 400 - - workflowId: update-badge-unauthenticated - summary: updateBadge refuses an anonymous caller + - workflowId: update-world-unauthenticated + summary: updateWorld refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: update-badge - operationId: $sourceDescriptions.default.updateBadge + - stepId: update-world + operationId: $sourceDescriptions.default.updateWorld parameters: - - name: userId - in: path - value: usr_00000000-0000-0000-0000-000000000000 - - name: badgeId + - name: worldId in: path - value: bdg_00000000-0000-0000-0000-000000000000 + value: wrld_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: update-user - summary: Update other user + - workflowId: get-cosmetics-portalskin + summary: Cosmetics of type portalskin parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-other-user - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - operationId: $sourceDescriptions.default.updateUser + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics parameters: - - name: userId + - name: itemType in: path - value: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 - requestBody: - contentType: application/json - payload: - bio: should-be-rejected + value: portalskin successCriteria: - - condition: $statusCode == 401 || $statusCode == 403 + - condition: $statusCode == 200 - - workflowId: update-user-note-unauthenticated - summary: updateUserNote refuses an anonymous caller + - workflowId: get-cosmetics-droneskin + summary: Cosmetics of type droneskin parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-user-note - operationId: $sourceDescriptions.default.updateUserNote + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics + parameters: + - name: itemType + in: path + value: droneskin successCriteria: - - condition: $statusCode == 401 - - workflowId: user-note-lifecycle - summary: Writes a note against another user, then reads it back by id + - condition: $statusCode == 200 + + - workflowId: get-cosmetics-warpeffect + summary: Cosmetics of type warpeffect parameters: - reference: $components.parameters.userAgent x-security: @@ -10309,61 +13831,89 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-note - operationId: $sourceDescriptions.default.updateUserNote - requestBody: - contentType: application/json - payload: - targetUserId: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469 - note: system_haha_we_actually_ended_up_documenting_this_one_too + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics + parameters: + - name: itemType + in: path + value: warpeffect successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/targetUserId == - 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' - onFailure: - - name: stop - type: end - - outputs: - userNoteId: $response.body#/id - - stepId: get-note - operationId: $sourceDescriptions.default.getUserNote + - workflowId: get-cosmetics-nameplateeffect + summary: Cosmetics of type nameplateEffect + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics parameters: - - name: userNoteId + - name: itemType in: path - value: $steps.update-note.outputs.userNoteId + value: nameplateEffect successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/targetUserId == - 'usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469' - - workflowId: add-world-tags-unauthenticated - summary: addWorldTags refuses an anonymous caller + - workflowId: get-cosmetics-profileeffect + summary: Cosmetics of type profileEffect parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: add-world-tags - operationId: $sourceDescriptions.default.addWorldTags + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics parameters: - - name: worldId + - name: itemType in: path - value: wrld_00000000-0000-0000-0000-000000000000 + value: profileEffect successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: create-world-unauthenticated - summary: createWorld refuses an anonymous caller + - workflowId: get-cosmetics-profilebackground + summary: Cosmetics of type profileBackground parameters: - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: create-world - operationId: $sourceDescriptions.default.createWorld + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics + parameters: + - name: itemType + in: path + value: profileBackground + successCriteria: + - condition: $statusCode == 200 + + - workflowId: get-cosmetics-iconframe + summary: Cosmetics of type iconFrame + parameters: + - reference: $components.parameters.userAgent + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + steps: + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics + parameters: + - name: itemType + in: path + value: iconFrame successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: delete-world-not-found - summary: deleteWorld refuses a resource that does not exist + - workflowId: get-cosmetics-invalid-type + summary: getCosmetics names the types it accepts parameters: - reference: $components.parameters.userAgent x-security: @@ -10371,31 +13921,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: delete-world - operationId: $sourceDescriptions.default.deleteWorld + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics parameters: - - name: worldId + - name: itemType in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: sticker successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 400 - - workflowId: delete-world-unauthenticated - summary: deleteWorld refuses an anonymous caller + - workflowId: get-cosmetics-unauthenticated + summary: getCosmetics refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-world - operationId: $sourceDescriptions.default.deleteWorld + - stepId: cosmetic-index + operationId: $sourceDescriptions.default.getCosmetics parameters: - - name: worldId + - name: itemType in: path - value: wrld_00000000-0000-0000-0000-000000000000 + value: iconFrame successCriteria: - condition: $statusCode == 401 - - workflowId: delete-world-platform-not-found - summary: deleteWorldPlatform refuses a resource that does not exist + - workflowId: get-favorite-group-contents + summary: Favorite group contents parameters: - reference: $components.parameters.userAgent x-security: @@ -10403,51 +13953,70 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: delete-world-platform - operationId: $sourceDescriptions.default.deleteWorldPlatform + - stepId: favorite-group-contents + operationId: $sourceDescriptions.default.getFavoriteGroupContents parameters: - - name: worldId + - name: favoriteGroupType in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - - name: publishedPlatform + value: world + - name: favoriteGroupName in: path - value: standalonewindows + value: world1 + - name: ownerId + in: query + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 + - condition: $response.body#/favorites/0/world/id != null - - workflowId: delete-world-platform-unauthenticated - summary: deleteWorldPlatform refuses an anonymous caller + - workflowId: get-favorite-group-contents-unauthenticated + summary: getFavoriteGroupContents refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: delete-world-platform - operationId: $sourceDescriptions.default.deleteWorldPlatform + - stepId: favorite-group-contents + operationId: $sourceDescriptions.default.getFavoriteGroupContents parameters: - - name: worldId + - name: favoriteGroupType in: path - value: wrld_00000000-0000-0000-0000-000000000000 - - name: publishedPlatform + value: world + - name: favoriteGroupName in: path - value: standalonewindows + value: world1 successCriteria: - condition: $statusCode == 401 - - workflowId: get-active-worlds - summary: Active worlds + - workflowId: get-beta + summary: Beta program parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: active-worlds - operationId: $sourceDescriptions.default.getActiveWorlds + - stepId: beta + operationId: $sourceDescriptions.default.getBeta + parameters: + - name: betaName + in: path + value: ios-closed-beta successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/betaName == 'ios-closed-beta' - - workflowId: get-active-worlds-query-parameters - summary: getActiveWorlds with every fillable query parameter + - workflowId: get-beta-not-found + summary: getBeta refuses a resource that does not exist + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: beta + operationId: $sourceDescriptions.default.getBeta + parameters: + - name: betaName + in: path + value: 3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + successCriteria: + - condition: $statusCode == 404 + + - workflowId: get-beta-registration-not-found + summary: getBetaRegistration refuses a beta the caller has not registered for parameters: - reference: $components.parameters.userAgent x-security: @@ -10455,42 +14024,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-active-worlds - operationId: $sourceDescriptions.default.getActiveWorlds + - stepId: beta-registration + operationId: $sourceDescriptions.default.getBetaRegistration parameters: - - name: featured - in: query - value: false - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 - - name: order - in: query - value: ascending - - name: releaseStatus - in: query - value: public - - name: sort - in: query - value: _created_at + - name: betaName + in: path + value: ios-closed-beta successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 404 - - workflowId: get-active-worlds-unauthenticated - summary: getActiveWorlds refuses an anonymous caller + - workflowId: get-beta-registration-unauthenticated + summary: getBetaRegistration refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-active-worlds - operationId: $sourceDescriptions.default.getActiveWorlds + - stepId: beta-registration + operationId: $sourceDescriptions.default.getBetaRegistration + parameters: + - name: betaName + in: path + value: ios-closed-beta successCriteria: - condition: $statusCode == 401 - - workflowId: get-favorited-worlds - summary: Favorited worlds + - workflowId: get-frontend-branches + summary: Frontend branches parameters: - reference: $components.parameters.userAgent x-security: @@ -10498,13 +14056,23 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: favorited-worlds - operationId: $sourceDescriptions.default.getFavoritedWorlds + - stepId: frontend-branches + operationId: $sourceDescriptions.default.getFrontendBranches successCriteria: - condition: $statusCode == 200 - - workflowId: get-favorited-worlds-query-parameters - summary: getFavoritedWorlds with every fillable query parameter + - workflowId: get-frontend-branches-unauthenticated + summary: getFrontendBranches refuses an anonymous caller + parameters: + - reference: $components.parameters.userAgent + steps: + - stepId: frontend-branches + operationId: $sourceDescriptions.default.getFrontendBranches + successCriteria: + - condition: $statusCode == 401 + + - workflowId: get-user-client-config + summary: User client config parameters: - reference: $components.parameters.userAgent x-security: @@ -10512,42 +14080,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-favorited-worlds - operationId: $sourceDescriptions.default.getFavoritedWorlds + - stepId: client-config + operationId: $sourceDescriptions.default.getUserClientConfig parameters: - - name: featured - in: query - value: false - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 - - name: order - in: query - value: ascending - - name: releaseStatus - in: query - value: public - - name: sort - in: query - value: _created_at + - name: userId + in: path + value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 - - workflowId: get-favorited-worlds-unauthenticated - summary: getFavoritedWorlds refuses an anonymous caller + - workflowId: get-user-client-config-unauthenticated + summary: getUserClientConfig refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-favorited-worlds - operationId: $sourceDescriptions.default.getFavoritedWorlds + - stepId: client-config + operationId: $sourceDescriptions.default.getUserClientConfig + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: get-recent-worlds - summary: Recent worlds + - workflowId: get-public-profile-as-self + summary: Public profile as its own owner parameters: - reference: $components.parameters.userAgent x-security: @@ -10555,94 +14112,137 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: recent-worlds - operationId: $sourceDescriptions.default.getRecentWorlds + - stepId: public-profile + operationId: $sourceDescriptions.default.getPublicProfile + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + - name: asSelf + in: query + value: true successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/currentAvatar != null + - condition: $response.body#/iconType != null + - condition: $response.body#/status != null - - workflowId: get-recent-worlds-query-parameters - summary: getRecentWorlds with every fillable query parameter + - workflowId: profile-bio-update-restore + summary: Update the bio through the profile, confirm it applied, restore it parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-recent-worlds - operationId: $sourceDescriptions.default.getRecentWorlds + - stepId: marker + operationId: $sourceDescriptions.local.execute + requestBody: + contentType: application/json + payload: + command: sh + args: + - -c + - openssl rand -hex 6 | tr -d '\n' + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/exitCode == 0 + onFailure: + - name: stop + type: end + + outputs: + value: $response.body#/stdout + + - stepId: profile-before + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getPublicProfile parameters: - - name: featured - in: query - value: false - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 - - name: order - in: query - value: ascending - - name: releaseStatus - in: query - value: public - - name: sort - in: query - value: _created_at + - name: userId + in: path + value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: get-recent-worlds-unauthenticated - summary: getRecentWorlds refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: get-recent-worlds - operationId: $sourceDescriptions.default.getRecentWorlds + outputs: + bio: $response.body#/bio + bioLinks: $response.body#/bioLinks + + - stepId: update-profile + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.updateProfile + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + bio: $steps.marker.outputs.value + bioLinks: $steps.profile-before.outputs.bioLinks successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 + - condition: $response.body#/bio == $steps.marker.outputs.value - - workflowId: get-world-black-cat - summary: Black cat - parameters: - - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken - steps: - - stepId: black-cat - operationId: $sourceDescriptions.default.getWorld + - stepId: verify-profile + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.getPublicProfile + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/bio == $steps.marker.outputs.value + + - stepId: restore-profile + x-security: + - schemeName: authCookie + values: + apiKey: $workflows.session.outputs.sessionToken + operationId: $sourceDescriptions.default.updateProfile parameters: - - name: worldId + - name: userId in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + bio: $steps.profile-before.outputs.bio + bioLinks: $steps.profile-before.outputs.bioLinks successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/id == 'wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b' - - condition: $response.body#/storeId != null + - condition: $response.body#/bio == $steps.profile-before.outputs.bio - - workflowId: get-world-not-found - summary: getWorld refuses a resource that does not exist + - workflowId: update-profile-unauthenticated + summary: updateProfile refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-world - operationId: $sourceDescriptions.default.getWorld + - stepId: update-profile + operationId: $sourceDescriptions.default.updateProfile parameters: - - name: worldId + - name: userId in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: usr_00000000-0000-0000-0000-000000000000 + requestBody: + contentType: application/json + payload: + bio: "" successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 401 - - workflowId: get-world-vrchat-home - summary: Vrchat home + - workflowId: get-age-verification-status + summary: Age verification status parameters: - reference: $components.parameters.userAgent x-security: @@ -10650,35 +14250,24 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: vrchat-home - operationId: $sourceDescriptions.default.getWorld - parameters: - - name: worldId - in: path - value: wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd + - stepId: age-verification-status + operationId: $sourceDescriptions.default.getAgeVerificationStatus successCriteria: - condition: $statusCode == 200 - - condition: $response.body#/id == 'wrld_4432ea9b-729c-46e3-8eaf-846aa0a37fdd' + - condition: $response.body#/status != null - - workflowId: get-world-instance-unauthenticated - summary: getWorldInstance refuses an anonymous caller + - workflowId: get-age-verification-status-unauthenticated + summary: getAgeVerificationStatus refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-world-instance - operationId: $sourceDescriptions.default.getWorldInstance - parameters: - - name: worldId - in: path - value: wrld_00000000-0000-0000-0000-000000000000 - - name: instanceId - in: path - value: 0 + - stepId: age-verification-status + operationId: $sourceDescriptions.default.getAgeVerificationStatus successCriteria: - condition: $statusCode == 401 - - workflowId: get-world-metadata - summary: World metadata + - workflowId: get-economy-status + summary: Economy status parameters: - reference: $components.parameters.userAgent x-security: @@ -10686,35 +14275,25 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: world-metadata - operationId: $sourceDescriptions.default.getWorldMetadata - parameters: - - name: worldId - in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + - stepId: economy-status + operationId: $sourceDescriptions.default.getEconomyStatus successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/economyOnline != null + - condition: $response.body#/economyState != null - - workflowId: get-world-metadata-not-found - summary: getWorldMetadata refuses a resource that does not exist + - workflowId: get-economy-status-unauthenticated + summary: getEconomyStatus refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: get-world-metadata - operationId: $sourceDescriptions.default.getWorldMetadata - parameters: - - name: worldId - in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + - stepId: economy-status + operationId: $sourceDescriptions.default.getEconomyStatus successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 401 - - workflowId: get-world-publish-status - summary: World publish status + - workflowId: get-economy-balance + summary: Economy balance parameters: - reference: $components.parameters.userAgent x-security: @@ -10722,31 +14301,32 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: world-publish-status - operationId: $sourceDescriptions.default.getWorldPublishStatus + - stepId: economy-balance + operationId: $sourceDescriptions.default.getEconomyBalance parameters: - - name: worldId + - name: userId in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b + value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 + - condition: $response.body#/balance != null - - workflowId: get-world-publish-status-unauthenticated - summary: getWorldPublishStatus refuses an anonymous caller + - workflowId: get-economy-balance-unauthenticated + summary: getEconomyBalance refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: get-world-publish-status - operationId: $sourceDescriptions.default.getWorldPublishStatus + - stepId: economy-balance + operationId: $sourceDescriptions.default.getEconomyBalance parameters: - - name: worldId + - name: userId in: path - value: wrld_00000000-0000-0000-0000-000000000000 + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: publish-world-not-found - summary: publishWorld refuses a resource that does not exist + - workflowId: get-economy-account-limits + summary: Economy account with its spending limits parameters: - reference: $components.parameters.userAgent x-security: @@ -10754,31 +14334,20 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: publish-world - operationId: $sourceDescriptions.default.publishWorld - parameters: - - name: worldId - in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 - successCriteria: - - condition: $statusCode == 404 - - - workflowId: publish-world-unauthenticated - summary: publishWorld refuses an anonymous caller - parameters: - - reference: $components.parameters.userAgent - steps: - - stepId: publish-world - operationId: $sourceDescriptions.default.publishWorld + - stepId: economy-account + operationId: $sourceDescriptions.default.getEconomyAccount parameters: - - name: worldId + - name: userId in: path - value: wrld_00000000-0000-0000-0000-000000000000 + value: $workflows.session.outputs.userId + - name: getLimits + in: query + value: true successCriteria: - - condition: $statusCode == 401 + - condition: $statusCode == 200 - - workflowId: remove-world-tags - summary: Removing tags from a world we do not own is refused + - workflowId: get-favorite-groups-by-type + summary: Favorite groups of one type parameters: - reference: $components.parameters.userAgent x-security: @@ -10786,36 +14355,36 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: remove-tags - operationId: $sourceDescriptions.default.removeWorldTags + - stepId: favorite-groups + operationId: $sourceDescriptions.default.getFavoriteGroupsByType parameters: - - name: worldId + - name: favoriteGroupType in: path - value: wrld_4cf554b4-430c-4f8f-b53e-1f294eed230b - requestBody: - contentType: application/json - payload: - tags: - - author_tag_test + value: world + - name: ownerId + in: query + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 403 + - condition: $statusCode == 200 + - condition: $response.body#/favoriteGroups/0/id != null + - condition: $response.body#/maxFavoriteGroups != null - - workflowId: search-worlds - summary: Search worlds + - workflowId: get-favorite-groups-by-type-unauthenticated + summary: getFavoriteGroupsByType refuses an anonymous caller parameters: - reference: $components.parameters.userAgent - x-security: - - schemeName: authCookie - values: - apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-worlds - operationId: $sourceDescriptions.default.searchWorlds + - stepId: favorite-groups + operationId: $sourceDescriptions.default.getFavoriteGroupsByType + parameters: + - name: favoriteGroupType + in: path + value: world successCriteria: - - condition: $statusCode == 200 + - condition: $statusCode == 401 - - workflowId: search-worlds-query-parameters - summary: searchWorlds with every fillable query parameter + - workflowId: get-user-cosmetics + summary: A user's cosmetics parameters: - reference: $components.parameters.userAgent x-security: @@ -10823,51 +14392,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: search-worlds - operationId: $sourceDescriptions.default.searchWorlds + - stepId: user-cosmetics + operationId: $sourceDescriptions.default.getUserCosmetics parameters: - - name: avatarSpecific - in: query - value: false - - name: featured - in: query - value: false - - name: fuzzy - in: query - value: false - - name: n - in: query - value: 1 - - name: offset - in: query - value: 1 - - name: order - in: query - value: ascending - - name: releaseStatus - in: query - value: public - - name: sort - in: query - value: _created_at - - name: user - in: query - value: me + - name: userId + in: path + value: $workflows.session.outputs.userId successCriteria: - condition: $statusCode == 200 - - workflowId: search-worlds-unauthenticated - summary: searchWorlds refuses an anonymous caller + - workflowId: get-user-cosmetics-unauthenticated + summary: getUserCosmetics refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: search-worlds - operationId: $sourceDescriptions.default.searchWorlds + - stepId: user-cosmetics + operationId: $sourceDescriptions.default.getUserCosmetics + parameters: + - name: userId + in: path + value: usr_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: unpublish-world-not-found - summary: unpublishWorld refuses a resource that does not exist + - workflowId: get-product-listing-products + summary: The products a listing sells parameters: - reference: $components.parameters.userAgent x-security: @@ -10875,31 +14424,31 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: unpublish-world - operationId: $sourceDescriptions.default.unpublishWorld + - stepId: listing-products + operationId: $sourceDescriptions.default.getProductListingProducts parameters: - - name: worldId + - name: productId in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: prod_c9d1cf9b-e3be-4bed-8386-49f0a8d32910 successCriteria: - - condition: $statusCode == 404 + - condition: $statusCode == 200 - - workflowId: unpublish-world-unauthenticated - summary: unpublishWorld refuses an anonymous caller + - workflowId: get-product-listing-products-unauthenticated + summary: getProductListingProducts refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: unpublish-world - operationId: $sourceDescriptions.default.unpublishWorld + - stepId: listing-products + operationId: $sourceDescriptions.default.getProductListingProducts parameters: - - name: worldId + - name: productId in: path - value: wrld_00000000-0000-0000-0000-000000000000 + value: prod_00000000-0000-0000-0000-000000000000 successCriteria: - condition: $statusCode == 401 - - workflowId: update-world-not-found - summary: updateWorld refuses a resource that does not exist + - workflowId: client-config-update-restore + summary: Update a client config setting and put it back parameters: - reference: $components.parameters.userAgent x-security: @@ -10907,25 +14456,62 @@ workflows: values: apiKey: $workflows.session.outputs.sessionToken steps: - - stepId: update-world - operationId: $sourceDescriptions.default.updateWorld + - stepId: config-before + operationId: $sourceDescriptions.default.getUserClientConfig parameters: - - name: worldId + - name: userId in: path - value: wrld_3f2a9c14-8d7b-4e05-a6c3-1b9e5d0f7a82 + value: $workflows.session.outputs.userId successCriteria: - - condition: $statusCode == 400 + - condition: $statusCode == 200 + onFailure: + - name: stop + type: end - - workflowId: update-world-unauthenticated - summary: updateWorld refuses an anonymous caller + outputs: + accessReduceDecorAnim: $response.body#/accessReduceDecorAnim + + - stepId: config-toggle + operationId: $sourceDescriptions.default.updateUserClientConfig + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + accessReduceDecorAnim: true + successCriteria: + - condition: $statusCode == 200 + - condition: $response.body#/accessReduceDecorAnim == true + + - stepId: config-restore + operationId: $sourceDescriptions.default.updateUserClientConfig + parameters: + - name: userId + in: path + value: $workflows.session.outputs.userId + requestBody: + contentType: application/json + payload: + accessReduceDecorAnim: $steps.config-before.outputs.accessReduceDecorAnim + successCriteria: + - condition: $statusCode == 200 + + - workflowId: update-user-client-config-unauthenticated + summary: updateUserClientConfig refuses an anonymous caller parameters: - reference: $components.parameters.userAgent steps: - - stepId: update-world - operationId: $sourceDescriptions.default.updateWorld + - stepId: client-config + operationId: $sourceDescriptions.default.updateUserClientConfig parameters: - - name: worldId + - name: userId in: path - value: wrld_00000000-0000-0000-0000-000000000000 + value: usr_00000000-0000-0000-0000-000000000000 + requestBody: + contentType: application/json + payload: + accessReduceDecorAnim: false successCriteria: - condition: $statusCode == 401 diff --git a/test/report.sh b/test/report.sh new file mode 100755 index 00000000..33e2b990 --- /dev/null +++ b/test/report.sh @@ -0,0 +1,181 @@ +#!/bin/sh +# Renders the last run's JSON report, as Markdown for GitHub's step summary or +# as workflow commands that annotate the workflow which failed. +# +# respect names the check that failed but not the request behind it, so a CI log +# says `status code check` and leaves you to find the URL and the status code +# yourself. The JSON report carries both. +# +# sh test/report.sh >> "$GITHUB_STEP_SUMMARY" +# sh test/report.sh --format github +set -eu + +cd "$(dirname "$0")/.." + +format=markdown +if [ "${1:-}" = "--format" ]; then + format="$2" + shift 2 +fi + +report="${1:-test/.out/respect.json}" +[ -s "$report" ] || exit 0 + +# respect records no line numbers, so an annotation has to find its own. A +# workflow and step id are unique together, and both keys sit at a fixed depth. +lines=$(awk ' + /^ - workflowId: / { workflow = $3; next } + /^ - stepId: / { printf "%s\t%s\t%d\n", workflow, $3, NR } +' test/arazzo.yaml | jq -R -s ' + split("\n") + | map(select(length > 0) | split("\t")) + | map({key: (.[0] + "\t" + .[1]), value: (.[2] | tonumber)}) + | from_entries +') + +jq -r --argjson lines "$lines" --arg format "$format" ' + # A `goto` failure action runs its target as a nested workflow, which respect + # records among the steps it jumped from rather than beside them. Only the + # leaves carry checks, so a cleanup that fails would go unreported. + def leaves: .executedSteps[] | if .type == "workflow" then leaves else . end; + [ + .files[].executedWorkflows[] + | .workflowId as $workflow + | leaves + | { + workflow: $workflow, + step: .stepId, + method: ((.request.method // "?") | ascii_upcase), + path: ((.request.url // "") | sub("^https?://[^/]+"; "")), + code: (.response.statusCode // 0), + checks: [.checks[] | select(.passed | not)], + } + | select(.checks | length > 0) + ] as $steps + | ([.files[].executedWorkflows[]] | length) as $total + # A schema check reports what failed, sometimes the values it would have + # accepted, then a code frame quoting the whole response body. The prose is + # what is worth reading, so take lines until the frame starts. + # + # The frame colours every line: one message came to 14MB, holding an escape + # sequence for each, and stripping those from the whole string rebuilds it + # once per escape and takes minutes. Cut to a prefix before the regex. + | def detail: + # Ajv shouts the keyword it failed on. + def tidy: + sub("^REQUIRED must have required property "; "missing required property ") + | sub("^UNEVALUATEDPROPERTIES must NOT have unevaluated properties: "; "undocumented property ") + | sub("^ENUM must be equal to one of the allowed values"; "not one of the allowed values") + | sub("^TYPE "; "") + | sub("\\.$"; ""); + if .condition then .condition + else + [ + (.message // "") + | split("\n")[] + # Every line of a code frame carries a gutter, and a frame can run + # to megabytes. Finding the prose by substring rather than by regex + # is what keeps that affordable: the same lines, ninety times faster. + | select(index("|") | not) + | gsub("\u001b\\[[0-9;]*m"; "") + | select(test("\\S")) + ] + # One message can carry several failures, each opening with the keyword + # Ajv failed on. Anything else continues the failure above it, whether + # that is the values it would have taken or a sentence on the cause. + # Ajv repeats a failure once per element it rejected, and the same + # wording twice says nothing the first did not. + | map(sub("^ +"; "") | sub(" +$"; "")) + | reduce .[] as $line ( + []; + if (length > 0) and (($line | test("^[A-Z][A-Z]")) | not) + then .[0:-1] + [.[-1] + " " + $line] + else . + [$line] + end + ) + | map(tidy) + | reduce .[] as $item ([]; if index([$item]) then . else . + [$item] end) + | join("; ") + end; + def rows($severity): + [ + $steps[] + | . as $step + | .checks[] + | select(.severity == $severity) + | $step + {check: .name, detail: detail} + ]; + # The annotation already points at the step, so its name would only repeat + # the line it sits on. The check name is worth printing when it carries no + # detail of its own. + def summary: + if .detail == "" then .check else .detail end; + + # Failures run long enough that no table column can hold them. A workflow can + # fail several steps, and a step several checks, so each nests under the one + # it belongs to rather than repeating it. + def markdown: + def unique_in_order: reduce .[] as $item ([]; if index([$item]) then . else . + [$item] end); + def entries($severity): + [ + rows($severity) + | group_by(.workflow)[] + | ["- **\(.[0].workflow)**"] + + [ + group_by(.step)[] + | [" - `\(.[0].step)`"] + + [ + group_by([.code, .method, .path])[] + | [" - `\(.[0].code) \(.[0].method) \(.[0].path)`"] + + ([.[] | summary | split("; ")[]] | unique_in_order | map(" - \(.)")) + ] + ] + ] + | flatten; + def plural($n; $noun): "\($n) \($noun)\(if $n == 1 then "" else "s" end)"; + def section($title; $severity): + entries($severity) as $entries + | rows($severity) as $rows + | if ($entries | length) == 0 then empty + else + [ + "### \($title) (\(plural($rows | map(.workflow) | unique | length; "workflow")), \(plural($rows | length; "check")))", + "" + ] + + $entries + + [""] + end; + ([section("Failures"; "error"), section("Warnings"; "warn")] | flatten) as $sections + | if ($sections | length) == 0 then ["All \($total) workflows passed."] else $sections end; + + # https://docs.github.com/actions/reference/workflow-commands-for-github-actions + # + # GitHub shows ten annotations of each level per step and drops the rest, but + # the runner calls its API for every one it is given. A run whose session + # failed fails every workflow it has, so this cap is what keeps the step from + # spending minutes on annotations nobody will see. The summary keeps them all. + # + # GitHub heads each annotation with the step that emitted it, so a title only + # repeats that. The workflow, the check and the request go in the body. + def github: + def message: gsub("%"; "%25") | gsub("\r"; "%0D") | gsub("\n"; "%0A"); + def command($level; $severity): + rows($severity) as $all + | [ + $all[0:10][] + | ($lines[.workflow + "\t" + .step] // 0) as $line + | (if $line == 0 then "" else ",line=\($line)" end) as $anchor + | ("\(.workflow): \(summary) — \(.code) \(.method) \(.path)" | message) as $body + | "::\($level) file=test/arazzo.yaml\($anchor)::\($body)" + ] + + ( + if ($all | length) > 10 + then ["::notice::\(($all | length) - 10) further \($severity) checks, listed in the run summary."] + else [] + end + ); + command("error"; "error") + command("warning"; "warn"); + + (if $format == "github" then github else markdown end) + | .[] +' "$report" diff --git a/test/run.sh b/test/run.sh index fbe0e3db..fe011971 100755 --- a/test/run.sh +++ b/test/run.sh @@ -22,6 +22,7 @@ fi # An empty input is worse than a missing one: respect sends the literal # `{userId}` in the path. : "${VRCHAT_FRIEND_ID:?unset — see test/.env.example}" +: "${VRCHAT_GROUP_ID:?unset — see test/.env.example}" : "${VRCHAT_EMAIL:?unset — see test/.env.example}" mkdir -p test/.out/har @@ -48,9 +49,10 @@ curl -sf --retry 20 --retry-delay 1 --retry-connrefused -o /dev/null \ # `coverage` and `drift` read as a whole-suite record. skips='--skip logout --skip invite-message-lifecycle' capture=test/.out/har/arazzo.har +report=test/.out/respect.json for argument do case $argument in - -w | --workflow) skips=''; capture=test/.out/partial.har ;; + -w | --workflow) skips=''; capture=test/.out/partial.har; report=test/.out/partial.json ;; esac done @@ -74,7 +76,9 @@ fi redocly respect test/arazzo.yaml \ ${skips} \ --har-output "$capture" \ + --json-output "$report" \ --input friendId="$VRCHAT_FRIEND_ID" \ + --input groupId="$VRCHAT_GROUP_ID" \ --input username="${VRCHAT_USERNAME:-$VRCHAT_EMAIL}" \ --input email="$VRCHAT_EMAIL" \ --severity "$TEST_SEVERITY" \