diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 625dc32..35c9829 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -16,7 +16,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '22' cache: 'npm' cache-dependency-path: data_models/package-lock.json @@ -34,7 +34,14 @@ jobs: npx tsp compile . --emit=@typespec/json-schema chmod +x promote.sh ./promote.sh - + + - name: Generate Workouts OpenAPI spec + run: | + cd data_models + npx tsp compile specs/data_models/PlannedWorkouts.tsp --config specs/data_models/tspconfig.yaml --output-dir .. + mv ../@typespec/openapi3/workouts.yaml ../workouts.yaml + rm -rf ../@typespec + - name: Bundle OpenAPI v5 specification run: | redocly bundle v5.yaml -o v5-bundled.yaml @@ -42,11 +49,12 @@ jobs: - name: Bundle OpenAPI v6 specification run: | redocly bundle v6.yaml -o v6-bundled.yaml - + - name: Validate bundled specifications run: | redocly lint v5-bundled.yaml redocly lint v6-bundled.yaml + redocly lint workouts.yaml - name: Upload bundled specifications uses: actions/upload-artifact@v4 @@ -55,6 +63,7 @@ jobs: path: | v5-bundled.yaml v6-bundled.yaml + workouts.yaml retention-days: 90 - name: Upload schemas @@ -65,6 +74,7 @@ jobs: retention-days: 90 - name: Create Release + id: create_release if: startsWith(github.ref, 'refs/tags/') uses: actions/create-release@v1 env: @@ -74,14 +84,15 @@ jobs: release_name: Release ${{ github.ref_name }} body: | ## Changes - + This release includes updated OpenAPI specifications and JSON schemas. - + ### Artifacts - `v5-bundled.yaml` - Bundled OpenAPI v5 specification - - `v6-bundled.yaml` - Bundled OpenAPI v6 specification + - `v6-bundled.yaml` - Bundled OpenAPI v6 specification + - `workouts.yaml` - Planned Workouts API specification - `schemas.zip` - All generated JSON schemas - + draft: false prerelease: false @@ -96,7 +107,7 @@ jobs: asset_name: v5-bundled.yaml asset_content_type: application/yaml - - name: Upload Release Asset - v6 Bundle + - name: Upload Release Asset - v6 Bundle if: startsWith(github.ref, 'refs/tags/') uses: actions/upload-release-asset@v1 env: @@ -105,4 +116,15 @@ jobs: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./v6-bundled.yaml asset_name: v6-bundled.yaml + asset_content_type: application/yaml + + - name: Upload Release Asset - Planned Workouts + if: startsWith(github.ref, 'refs/tags/') + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./workouts.yaml + asset_name: workouts.yaml asset_content_type: application/yaml \ No newline at end of file diff --git a/data_models/package-lock.json b/data_models/package-lock.json index c36d859..827dfbf 100644 --- a/data_models/package-lock.json +++ b/data_models/package-lock.json @@ -8,7 +8,10 @@ "name": "terra_data_models", "version": "0.1.0", "dependencies": { - "@typespec/json-schema": "^1.0.0" + "@typespec/http": "latest", + "@typespec/json-schema": "latest", + "@typespec/openapi3": "latest", + "@typespec/rest": "latest" }, "devDependencies": { "@types/node": "latest", @@ -24,24 +27,22 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "license": "MIT", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "license": "MIT", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "engines": { "node": ">=6.9.0" } @@ -322,20 +323,26 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@inquirer/ansi": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/ansi/-/ansi-2.0.3.tgz", + "integrity": "sha512-g44zhR3NIKVs0zUesa4iMzExmZpLUdTLRMCStqX3GE5NT6VkPcxQGJ+uC8tDgBUC/vB1rUhUd55cOf++4NZcmw==", + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + } + }, "node_modules/@inquirer/checkbox": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.6.tgz", - "integrity": "sha512-62u896rWCtKKE43soodq5e/QcRsA22I+7/4Ov7LESWnKRO6BVo2A1DFLDmXL9e28TB0CfHc3YtkbPm7iwajqkg==", - "license": "MIT", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-5.0.4.tgz", + "integrity": "sha512-DrAMU3YBGMUAp6ArwTIp/25CNDtDbxk7UjIrrtM25JVVrlVYlVzHh5HR1BDFu9JMyUoZ4ZanzeaHqNDttf3gVg==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.6", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.1", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -347,16 +354,15 @@ } }, "node_modules/@inquirer/confirm": { - "version": "5.1.10", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.10.tgz", - "integrity": "sha512-FxbQ9giWxUWKUk2O5XZ6PduVnH2CZ/fmMKMBkH71MHJvWr7WL5AHKevhzF1L5uYWB2P548o1RzVxrNd3dpmk6g==", - "license": "MIT", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-6.0.4.tgz", + "integrity": "sha512-WdaPe7foUnoGYvXzH4jp4wH/3l+dBhZ3uwhKjXjwdrq5tEIFaANxj6zrGHxLdsIA0yKM0kFPVcEalOZXBB5ISA==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6" + "@inquirer/core": "^11.1.1", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -368,22 +374,20 @@ } }, "node_modules/@inquirer/core": { - "version": "10.1.11", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.11.tgz", - "integrity": "sha512-BXwI/MCqdtAhzNQlBEFE7CEflhPkl/BqvAuV/aK6lW3DClIfYVDWPP/kXuXHtBWC7/EEbNqd/1BGq2BGBBnuxw==", - "license": "MIT", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-11.1.1.tgz", + "integrity": "sha512-hV9o15UxX46OyQAtaoMqAOxGR8RVl1aZtDx1jHbCtSJy1tBdTfKxLPKf7utsE4cRy4tcmCQ4+vdV+ca+oNxqNA==", "dependencies": { - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.6", - "ansi-escapes": "^4.3.2", + "@inquirer/ansi": "^2.0.3", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3", "cli-width": "^4.1.0", - "mute-stream": "^2.0.0", + "mute-stream": "^3.0.0", "signal-exit": "^4.1.0", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" + "wrap-ansi": "^9.0.2" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -395,17 +399,16 @@ } }, "node_modules/@inquirer/editor": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.11.tgz", - "integrity": "sha512-YoZr0lBnnLFPpfPSNsQ8IZyKxU47zPyVi9NLjCWtna52//M/xuL0PGPAxHxxYhdOhnvY2oBafoM+BI5w/JK7jw==", - "license": "MIT", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-5.0.4.tgz", + "integrity": "sha512-QI3Jfqcv6UO2/VJaEFONH8Im1ll++Xn/AJTBn9Xf+qx2M+H8KZAdQ5sAe2vtYlo+mLW+d7JaMJB4qWtK4BG3pw==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6", - "external-editor": "^3.1.0" + "@inquirer/core": "^11.1.1", + "@inquirer/external-editor": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -417,17 +420,35 @@ } }, "node_modules/@inquirer/expand": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.13.tgz", - "integrity": "sha512-HgYNWuZLHX6q5y4hqKhwyytqAghmx35xikOGY3TcgNiElqXGPas24+UzNPOwGUZa5Dn32y25xJqVeUcGlTv+QQ==", - "license": "MIT", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-5.0.4.tgz", + "integrity": "sha512-0I/16YwPPP0Co7a5MsomlZLpch48NzYfToyqYAOWtBmaXSB80RiNQ1J+0xx2eG+Wfxt0nHtpEWSRr6CzNVnOGg==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6", - "yoctocolors-cjs": "^2.1.2" + "@inquirer/core": "^11.1.1", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-2.0.3.tgz", + "integrity": "sha512-LgyI7Agbda74/cL5MvA88iDpvdXI2KuMBCGRkbCl2Dg1vzHeOgs+s0SDcXV7b+WZJrv2+ERpWSM65Fpi9VfY3w==", + "dependencies": { + "chardet": "^2.1.1", + "iconv-lite": "^0.7.2" + }, + "engines": { + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -439,25 +460,23 @@ } }, "node_modules/@inquirer/figures": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.11.tgz", - "integrity": "sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==", - "license": "MIT", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-2.0.3.tgz", + "integrity": "sha512-y09iGt3JKoOCBQ3w4YrSJdokcD8ciSlMIWsD+auPu+OZpfxLuyz+gICAQ6GCBOmJJt4KEQGHuZSVff2jiNOy7g==", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" } }, "node_modules/@inquirer/input": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.1.10.tgz", - "integrity": "sha512-kV3BVne3wJ+j6reYQUZi/UN9NZGZLxgc/tfyjeK3mrx1QI7RXPxGp21IUTv+iVHcbP4ytZALF8vCHoxyNSC6qg==", - "license": "MIT", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-5.0.4.tgz", + "integrity": "sha512-4B3s3jvTREDFvXWit92Yc6jF1RJMDy2VpSqKtm4We2oVU65YOh2szY5/G14h4fHlyQdpUmazU5MPCFZPRJ0AOw==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6" + "@inquirer/core": "^11.1.1", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -469,16 +488,15 @@ } }, "node_modules/@inquirer/number": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.13.tgz", - "integrity": "sha512-IrLezcg/GWKS8zpKDvnJ/YTflNJdG0qSFlUM/zNFsdi4UKW/CO+gaJpbMgQ20Q58vNKDJbEzC6IebdkprwL6ew==", - "license": "MIT", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-4.0.4.tgz", + "integrity": "sha512-CmMp9LF5HwE+G/xWsC333TlCzYYbXMkcADkKzcawh49fg2a1ryLc7JL1NJYYt1lJ+8f4slikNjJM9TEL/AljYQ==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6" + "@inquirer/core": "^11.1.1", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -490,17 +508,16 @@ } }, "node_modules/@inquirer/password": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.13.tgz", - "integrity": "sha512-NN0S/SmdhakqOTJhDwOpeBEEr8VdcYsjmZHDb0rblSh2FcbXQOr+2IApP7JG4WE3sxIdKytDn4ed3XYwtHxmJQ==", - "license": "MIT", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-5.0.4.tgz", + "integrity": "sha512-ZCEPyVYvHK4W4p2Gy6sTp9nqsdHQCfiPXIP9LbJVW4yCinnxL/dDDmPaEZVysGrj8vxVReRnpfS2fOeODe9zjg==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6", - "ansi-escapes": "^4.3.2" + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.1", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -512,24 +529,23 @@ } }, "node_modules/@inquirer/prompts": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.5.1.tgz", - "integrity": "sha512-5AOrZPf2/GxZ+SDRZ5WFplCA2TAQgK3OYrXCYmJL5NaTu4ECcoWFlfUZuw7Es++6Njv7iu/8vpYJhuzxUH76Vg==", - "license": "MIT", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-8.2.0.tgz", + "integrity": "sha512-rqTzOprAj55a27jctS3vhvDDJzYXsr33WXTjODgVOru21NvBo9yIgLIAf7SBdSV0WERVly3dR6TWyp7ZHkvKFA==", "dependencies": { - "@inquirer/checkbox": "^4.1.6", - "@inquirer/confirm": "^5.1.10", - "@inquirer/editor": "^4.2.11", - "@inquirer/expand": "^4.0.13", - "@inquirer/input": "^4.1.10", - "@inquirer/number": "^3.0.13", - "@inquirer/password": "^4.0.13", - "@inquirer/rawlist": "^4.1.1", - "@inquirer/search": "^3.0.13", - "@inquirer/select": "^4.2.1" + "@inquirer/checkbox": "^5.0.4", + "@inquirer/confirm": "^6.0.4", + "@inquirer/editor": "^5.0.4", + "@inquirer/expand": "^5.0.4", + "@inquirer/input": "^5.0.4", + "@inquirer/number": "^4.0.4", + "@inquirer/password": "^5.0.4", + "@inquirer/rawlist": "^5.2.0", + "@inquirer/search": "^4.1.0", + "@inquirer/select": "^5.0.4" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -541,17 +557,15 @@ } }, "node_modules/@inquirer/rawlist": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.1.tgz", - "integrity": "sha512-VBUC0jPN2oaOq8+krwpo/mf3n/UryDUkKog3zi+oIi8/e5hykvdntgHUB9nhDM78RubiyR1ldIOfm5ue+2DeaQ==", - "license": "MIT", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-5.2.0.tgz", + "integrity": "sha512-CciqGoOUMrFo6HxvOtU5uL8fkjCmzyeB6fG7O1vdVAZVSopUBYECOwevDBlqNLyyYmzpm2Gsn/7nLrpruy9RFg==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/type": "^3.0.6", - "yoctocolors-cjs": "^2.1.2" + "@inquirer/core": "^11.1.1", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -563,18 +577,16 @@ } }, "node_modules/@inquirer/search": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.0.13.tgz", - "integrity": "sha512-9g89d2c5Izok/Gw/U7KPC3f9kfe5rA1AJ24xxNZG0st+vWekSk7tB9oE+dJv5JXd0ZSijomvW0KPMoBd8qbN4g==", - "license": "MIT", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-4.1.0.tgz", + "integrity": "sha512-EAzemfiP4IFvIuWnrHpgZs9lAhWDA0GM3l9F4t4mTQ22IFtzfrk8xbkMLcAN7gmVML9O/i+Hzu8yOUyAaL6BKA==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.6", - "yoctocolors-cjs": "^2.1.2" + "@inquirer/core": "^11.1.1", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -586,19 +598,17 @@ } }, "node_modules/@inquirer/select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.2.1.tgz", - "integrity": "sha512-gt1Kd5XZm+/ddemcT3m23IP8aD8rC9drRckWoP/1f7OL46Yy2FGi8DSmNjEjQKtPl6SV96Kmjbl6p713KXJ/Jg==", - "license": "MIT", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-5.0.4.tgz", + "integrity": "sha512-s8KoGpPYMEQ6WXc0dT9blX2NtIulMdLOO3LA1UKOiv7KFWzlJ6eLkEYTDBIi+JkyKXyn8t/CD6TinxGjyLt57g==", "dependencies": { - "@inquirer/core": "^10.1.11", - "@inquirer/figures": "^1.0.11", - "@inquirer/type": "^3.0.6", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" + "@inquirer/ansi": "^2.0.3", + "@inquirer/core": "^11.1.1", + "@inquirer/figures": "^2.0.3", + "@inquirer/type": "^4.0.3" }, "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -610,12 +620,11 @@ } }, "node_modules/@inquirer/type": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.6.tgz", - "integrity": "sha512-/mKVCtVpyBu3IDarv0G+59KC4stsD5mDsGpYh+GKs1NZT88Jh52+cuoA1AtLk2Q0r/quNl+1cSUyLRHBFeD0XA==", - "license": "MIT", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-4.0.3.tgz", + "integrity": "sha512-cKZN7qcXOpj1h+1eTTcGDVLaBIHNMT1Rz9JqJP5MnEJ0JhgVWllx7H/tahUp5YEK1qaByH2Itb8wLG/iScD5kw==", "engines": { - "node": ">=18" + "node": ">=23.5.0 || ^22.13.0 || ^21.7.0 || ^20.12.0" }, "peerDependencies": { "@types/node": ">=18" @@ -630,7 +639,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "license": "ISC", "dependencies": { "minipass": "^7.0.4" }, @@ -673,11 +681,91 @@ "node": ">= 8" } }, + "node_modules/@scalar/helpers": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.2.6.tgz", + "integrity": "sha512-A471YFBCj7ZOlGIkAYnU8oYgeyts82ZNX+4UicrlmKv3eAQ+kwboN3Dy0R6u1lcA/+I/zzeXi/fBObsT7P9qTA==", + "engines": { + "node": ">=20" + } + }, + "node_modules/@scalar/json-magic": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@scalar/json-magic/-/json-magic-0.8.10.tgz", + "integrity": "sha512-TWdKQ/hcy4erFQDp2MVlFoPesFep2VY96Q69cjLHmx5hxM0ZUBfmNB4lA8Uh3klgx5JmCDfSNIGjPFIpxlosUw==", + "dependencies": { + "@scalar/helpers": "0.2.6", + "yaml": "^2.8.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@scalar/openapi-parser": { + "version": "0.23.13", + "resolved": "https://registry.npmjs.org/@scalar/openapi-parser/-/openapi-parser-0.23.13.tgz", + "integrity": "sha512-YsljPOKOgQgZL/kBcEouwz2CUa+2hFfThlUZRWC2DFI2Fnw5Ur8F1IvGgPqCAHr9p2XMH+Z/Pag2jZUfLcxcww==", + "dependencies": { + "@scalar/json-magic": "0.9.0", + "@scalar/openapi-types": "0.5.3", + "@scalar/openapi-upgrader": "0.1.7", + "ajv": "^8.17.1", + "ajv-draft-04": "^1.0.0", + "ajv-formats": "^3.0.1", + "jsonpointer": "^5.0.1", + "leven": "^4.0.0", + "yaml": "^2.8.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@scalar/openapi-parser/node_modules/@scalar/helpers": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@scalar/helpers/-/helpers-0.2.7.tgz", + "integrity": "sha512-uFTcdi3XYDDuaJLWiMuM3ijQit1OBw7AkuOuujReY8L9UmUQHY56erYg0+Db3llTsinuIYFh+eS/WX/sYuevYQ==", + "engines": { + "node": ">=20" + } + }, + "node_modules/@scalar/openapi-parser/node_modules/@scalar/json-magic": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@scalar/json-magic/-/json-magic-0.9.0.tgz", + "integrity": "sha512-aSWd8rd3O73Ak9Ylson2TywvOuTjjOYiXydl9Cn8Ip/r7fi+h0QqAGom5gqo/WewrhySF9v+H/sW/Qmd05T/Kg==", + "dependencies": { + "@scalar/helpers": "0.2.7", + "yaml": "^2.8.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@scalar/openapi-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@scalar/openapi-types/-/openapi-types-0.5.3.tgz", + "integrity": "sha512-m4n/Su3K01d15dmdWO1LlqecdSPKuNjuokrJLdiQ485kW/hRHbXW1QP6tJL75myhw/XhX5YhYAR+jrwnGjXiMw==", + "dependencies": { + "zod": "^4.1.11" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@scalar/openapi-upgrader": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@scalar/openapi-upgrader/-/openapi-upgrader-0.1.7.tgz", + "integrity": "sha512-065froUtqvaHjyeJtyitf8tb+k7oh7nU0OinAHYbj1Bqgwb1s2+uKMqHYHEES5CNpp+2xtL4lxup6Aq29yW+sQ==", + "dependencies": { + "@scalar/openapi-types": "0.5.3" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/@sindresorhus/merge-streams": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", - "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", - "license": "MIT", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", "engines": { "node": ">=18" }, @@ -945,40 +1033,38 @@ } }, "node_modules/@typespec/asset-emitter": { - "version": "0.70.1", - "resolved": "https://registry.npmjs.org/@typespec/asset-emitter/-/asset-emitter-0.70.1.tgz", - "integrity": "sha512-X8hRA7LLWkNIWqAkWaWoa84PzDMUvjj3qCLQKT29k5twS419nN1GGT7BQaDQnYfPTsSssEFxgRgugr0AAErEsA==", - "license": "MIT", + "version": "0.78.0", + "resolved": "https://registry.npmjs.org/@typespec/asset-emitter/-/asset-emitter-0.78.0.tgz", + "integrity": "sha512-TA9MzNI+SJEYKNWdbSsWXhjnVOL+2VvsBqzExXKQmoN6zxu3dAImqrMG/oTA6FS4pbCU4vmWgLUiOmikvjm22Q==", "engines": { "node": ">=20.0.0" }, "peerDependencies": { - "@typespec/compiler": "^1.0.0" + "@typespec/compiler": "^1.8.0" } }, "node_modules/@typespec/compiler": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-1.0.0.tgz", - "integrity": "sha512-QFy0otaB4xkN4kQmYyT17yu3OVhN0gti9+EKnZqs5JFylw2Xecx22BPwUE1Byj42pZYg5d9WlO+WwmY5ALtRDg==", - "license": "MIT", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-1.8.0.tgz", + "integrity": "sha512-FeLb7Q0z6Bh5dDpqtnU2RlWiIWWWF7rujx2xGMta5dcTuIOZ4jbdyz1hVdxk4iM4qadvaSV4ey/qrSuffNoh3w==", "dependencies": { - "@babel/code-frame": "~7.26.2", - "@inquirer/prompts": "^7.4.0", + "@babel/code-frame": "~7.27.1", + "@inquirer/prompts": "^8.0.1", "ajv": "~8.17.1", "change-case": "~5.4.4", "env-paths": "^3.0.0", - "globby": "~14.1.0", + "globby": "~16.0.0", "is-unicode-supported": "^2.1.0", "mustache": "~4.2.0", "picocolors": "~1.1.1", - "prettier": "~3.5.3", + "prettier": "~3.7.4", "semver": "^7.7.1", - "tar": "^7.4.3", + "tar": "^7.5.2", "temporal-polyfill": "^0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.12", - "yaml": "~2.7.0", - "yargs": "~17.7.2" + "yaml": "~2.8.2", + "yargs": "~18.0.0" }, "bin": { "tsp": "cmd/tsp.js", @@ -988,20 +1074,109 @@ "node": ">=20.0.0" } }, + "node_modules/@typespec/http": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@typespec/http/-/http-1.8.0.tgz", + "integrity": "sha512-ZKa4RISabwL8cUAmE3BkoNmtCYRjerO0+1Ba6XdDJKG+vJC5EGM2hkDf+ZmYsYZgrX0cvbhPXUKKh28zBV60hw==", + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "^1.8.0", + "@typespec/streams": "^0.78.0" + }, + "peerDependenciesMeta": { + "@typespec/streams": { + "optional": true + } + } + }, "node_modules/@typespec/json-schema": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@typespec/json-schema/-/json-schema-1.0.0.tgz", - "integrity": "sha512-brI0acknyywlkIMM/HU1l87uq6sQWPh6NmvxgxDn84/YEF0SklZoQ/PXuBGYhwpBRuHrxi/LSjWLmKaMsyX8Jw==", - "license": "MIT", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@typespec/json-schema/-/json-schema-1.8.0.tgz", + "integrity": "sha512-FEcU2A/POu+cMuJE0mZrzGL/6ONUlbuOWbZZK2NSUfcMCpN0kHtKwEwui3fw3KaSIUqOaAJX9vE8vE47CT3bAA==", "dependencies": { - "@typespec/asset-emitter": "^0.70.0", - "yaml": "~2.7.0" + "@typespec/asset-emitter": "^0.78.0", + "yaml": "~2.8.2" }, "engines": { "node": ">=20.0.0" }, "peerDependencies": { - "@typespec/compiler": "^1.0.0" + "@typespec/compiler": "^1.8.0" + } + }, + "node_modules/@typespec/openapi": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-1.8.0.tgz", + "integrity": "sha512-v+RIJpx7vALBSGQmnUWemvXjnrk50HAVqJeg0RbaF3VUnh66Z4itsoNJJmIIc+HmBJng8Ie0V7xv3l02ek6HWA==", + "peer": true, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "^1.8.0", + "@typespec/http": "^1.8.0" + } + }, + "node_modules/@typespec/openapi3": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-1.8.0.tgz", + "integrity": "sha512-lmFJZEHjx20iTZqGaVJytlNjpPsPpXZGRs/ur8X0nx1vRcXtfM9IemZ0Chi6hWgo+AFq91lex9nocJEUn+uMMw==", + "dependencies": { + "@scalar/json-magic": "^0.8.2", + "@scalar/openapi-parser": "^0.23.3", + "@scalar/openapi-types": "^0.5.0", + "@typespec/asset-emitter": "^0.78.0", + "yaml": "~2.8.2" + }, + "bin": { + "tsp-openapi3": "cmd/tsp-openapi3.js" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "^1.8.0", + "@typespec/events": "^0.78.0", + "@typespec/http": "^1.8.0", + "@typespec/json-schema": "^1.8.0", + "@typespec/openapi": "^1.8.0", + "@typespec/sse": "^0.78.0", + "@typespec/streams": "^0.78.0", + "@typespec/versioning": "^0.78.0" + }, + "peerDependenciesMeta": { + "@typespec/events": { + "optional": true + }, + "@typespec/json-schema": { + "optional": true + }, + "@typespec/sse": { + "optional": true + }, + "@typespec/streams": { + "optional": true + }, + "@typespec/versioning": { + "optional": true + }, + "@typespec/xml": { + "optional": true + } + } + }, + "node_modules/@typespec/rest": { + "version": "0.78.0", + "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.78.0.tgz", + "integrity": "sha512-1clnDw1JbBvjLcfFvEvHdIrnsQuQI5/Cl6mRIrzWWX0pKJ+R89rCdZD1KpidEXw4B4qscD48LsssyrEIFLtuPg==", + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "^1.8.0", + "@typespec/http": "^1.8.0" } }, "node_modules/acorn": { @@ -1043,34 +1218,51 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "license": "MIT", + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "dependencies": { - "type-fest": "^0.21.3" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "ajv": "^8.0.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -1152,16 +1344,14 @@ "license": "MIT" }, "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "license": "MIT" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz", + "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==" }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } @@ -1170,46 +1360,28 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "license": "ISC", "engines": { "node": ">= 12" } }, "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=20" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1222,6 +1394,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, "license": "MIT" }, "node_modules/concat-map": { @@ -1272,10 +1445,9 @@ "license": "MIT" }, "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==" }, "node_modules/env-paths": { "version": "3.0.0", @@ -1293,7 +1465,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", "engines": { "node": ">=6" } @@ -1550,20 +1721,6 @@ "node": ">=0.10.0" } }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1704,11 +1861,21 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -1736,20 +1903,19 @@ } }, "node_modules/globby": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", - "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", - "license": "MIT", + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-16.0.0.tgz", + "integrity": "sha512-ejy4TJFga99yW6Q0uhM3pFawKWZmtZzZD/v/GwI5+9bCV5Ew+D2pSND6W7fUes5UykqSsJkUfxFVdRh7Q1+P3Q==", "dependencies": { - "@sindresorhus/merge-streams": "^2.1.0", + "@sindresorhus/merge-streams": "^4.0.0", "fast-glob": "^3.3.3", - "ignore": "^7.0.3", - "path-type": "^6.0.0", + "ignore": "^7.0.5", + "is-path-inside": "^4.0.0", "slash": "^5.1.0", - "unicorn-magic": "^0.3.0" + "unicorn-magic": "^0.4.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1773,22 +1939,24 @@ } }, "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/ignore": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz", - "integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==", - "license": "MIT", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "engines": { "node": ">= 4" } @@ -1829,15 +1997,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1859,6 +2018,17 @@ "node": ">=0.12.0" } }, + "node_modules/is-path-inside": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz", + "integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-unicode-supported": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", @@ -1881,8 +2051,7 @@ "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "node_modules/js-yaml": { "version": "4.1.0", @@ -1917,6 +2086,14 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -1927,6 +2104,17 @@ "json-buffer": "3.0.1" } }, + "node_modules/leven": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-4.1.0.tgz", + "integrity": "sha512-KZ9W9nWDT7rF7Dazg8xyLHGLrmpgq2nVNFUckhqdW3szVP6YhCpp/RAnpmVExA9JvrMynjwSLVrEj3AepHR6ew==", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2006,16 +2194,14 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "license": "MIT", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "dependencies": { "minipass": "^7.1.2" }, @@ -2023,21 +2209,6 @@ "node": ">= 18" } }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2055,12 +2226,11 @@ } }, "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "license": "ISC", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-3.0.0.tgz", + "integrity": "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==", "engines": { - "node": "^18.17.0 || >=20.5.0" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/natural-compare": { @@ -2088,15 +2258,6 @@ "node": ">= 0.8.0" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -2162,23 +2323,10 @@ "node": ">=8" } }, - "node_modules/path-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", - "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -2203,10 +2351,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", - "license": "MIT", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz", + "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==", "bin": { "prettier": "bin/prettier.cjs" }, @@ -2247,15 +2394,6 @@ ], "license": "MIT" }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -2311,8 +2449,7 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "license": "MIT" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { "version": "7.7.2", @@ -2353,7 +2490,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", "engines": { "node": ">=14" }, @@ -2365,7 +2501,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "license": "MIT", "engines": { "node": ">=14.16" }, @@ -2374,29 +2509,33 @@ } }, "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dependencies": { - "ansi-regex": "^5.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, "node_modules/strip-json-comments": { @@ -2426,16 +2565,14 @@ } }, "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "license": "ISC", + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz", + "integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "engines": { @@ -2457,18 +2594,6 @@ "integrity": "sha512-n+noVpIqz4hYgFSMOSiINNOUOMFtV5cZQNCmmszA6GiVFVRt3G7AqVyhXjhCSmowvQn+NsGn+jMDMKJYHd3bSQ==", "license": "ISC" }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2507,18 +2632,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", @@ -2541,12 +2654,11 @@ "license": "MIT" }, "node_modules/unicorn-magic": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", - "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", - "license": "MIT", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.4.0.tgz", + "integrity": "sha512-wH590V9VNgYH9g3lH9wWjTrUoKsjLF6sGLjhR4sH1LWpLmCOH0Zf7PukhDA8BiS7KHe4oPNkcTHqYkj7SOGUOw==", "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2632,24 +2744,36 @@ } }, "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", "engines": { "node": ">=10" } @@ -2658,48 +2782,46 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "license": "BlueOak-1.0.0", "engines": { "node": ">=18" } }, "node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", - "license": "ISC", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14" + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" } }, "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", "dependencies": { - "cliui": "^8.0.1", + "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", + "string-width": "^7.2.0", "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "yargs-parser": "^22.0.0" }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yocto-queue": { @@ -2715,16 +2837,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/colinhacks" } } } diff --git a/data_models/package.json b/data_models/package.json index 6a33b4a..73e6605 100644 --- a/data_models/package.json +++ b/data_models/package.json @@ -37,6 +37,9 @@ "private": true, "packageManager": "npm@11.4.1+sha512.fcee43884166b6f9c5d04535fb95650e9708b6948a1f797eddf40e9778646778a518dfa32651b1c62ff36f4ac42becf177ca46ca27d53f24b539190c8d91802b", "dependencies": { - "@typespec/json-schema": "^1.0.0" + "@typespec/json-schema": "latest", + "@typespec/http": "latest", + "@typespec/rest": "latest", + "@typespec/openapi3": "latest" } } diff --git a/data_models/specs/data_models/PlannedWorkouts.tsp b/data_models/specs/data_models/PlannedWorkouts.tsp new file mode 100644 index 0000000..be615d9 --- /dev/null +++ b/data_models/specs/data_models/PlannedWorkouts.tsp @@ -0,0 +1,608 @@ +import "@typespec/http"; +import "@typespec/rest"; +import "@typespec/openapi3"; + +using TypeSpec.Http; +using TypeSpec.Rest; + +@service(#{ + title: "Terra Workouts + Planned Workouts API", +}) +@server("https://access.tryterra.co/api/v2", "Production server") +@useAuth([ApiKeyAuth, ApiKeyAuth]) +namespace Terra.Workouts; + +/** Common headers required for all Terra API requests */ +model TerraHeaders { + @header("dev-id") + devId: string; + + @header("x-api-key") + apiKey: string; +} + +// ===== ENUMS ===== + +/** Sport type for the workout. Use the `environment` field on the template for indoor/outdoor/pool distinction. */ +enum SportType { + running: "running", + cycling: "cycling", + swimming: "swimming", + strength: "strength", + rowing: "rowing", + yoga: "yoga", + pilates: "pilates", + cardio: "cardio", +} + +/** Environment type for the workout (indoor/outdoor/pool) */ +enum EnvironmentType { + indoor: "indoor", + outdoor: "outdoor", + pool: "pool", +} + +/** Completion condition type - how a step ends */ +enum CompletionConditionType { + time: "time", + distance: "distance", + calories: "calories", + reps: "reps", + open: "open", + hr_less_than: "hr_less_than", + hr_greater_than: "hr_greater_than", + power_less_than: "power_less_than", + power_greater_than: "power_greater_than", +} + +/** Intensity type for a workout step */ +enum IntensityType { + warmup: "warmup", + active: "active", + rest: "rest", + recovery: "recovery", + cooldown: "cooldown", +} + +/** Target type for intensity */ +enum TargetType { + /** No specific target */ + open: "open", + + /** Absolute speed in m/s (range: value_low/value_high) */ + speed: "speed", + /** Pace in min/km (range: value_low/value_high) */ + pace: "pace", + + /** Absolute heart rate in BPM (range: value_low/value_high) */ + heart_rate: "heart_rate", + /** Percentage of max HR (range: value_low/value_high). Requires max_heart_rate in plan request. */ + heart_rate_max_percentage: "heart_rate_max_percentage", + /** Percentage of threshold HR (range: value_low/value_high). Requires threshold_heart_rate in plan request. */ + heart_rate_threshold_percentage: "heart_rate_threshold_percentage", + /** Heart rate zone 1-5 (exact: value) */ + heart_rate_zone: "heart_rate_zone", + /** Lap-based HR target (range: value_low/value_high) */ + heart_rate_lap: "heart_rate_lap", + + /** Absolute power in watts (range: value_low/value_high) */ + power: "power", + /** Percentage of FTP (range: value_low/value_high). Requires ftp in plan request. */ + power_percentage: "power_percentage", + /** Power zone 1-7 (exact: value) */ + power_zone: "power_zone", + + /** Cadence in RPM or SPM (range or exact) */ + cadence: "cadence", + /** Rate of perceived exertion 1-10 (exact: value) */ + rpe: "rpe", + + /** Percentage of threshold speed (range: value_low/value_high). Requires threshold_speed in plan request. */ + speed_percentage: "speed_percentage", + + /** Lap-based speed target (range: value_low/value_high) */ + speed_lap: "speed_lap", + + /** Swimming stroke type - no numeric value needed */ + swim_stroke: "swim_stroke", + + /** Repetition count (exact: value) */ + repetition: "repetition", + + /** Training Stress Score (exact: value) */ + tss: "tss", + /** Intensity Factor (exact: value) */ + `if`: "if", +} + +/** Weight unit */ +enum WeightUnit { + kg: "kg", + lbs: "lbs", +} + +/** Swimming stroke values */ +enum SwimStroke { + freestyle: "freestyle", + backstroke: "backstroke", + breaststroke: "breaststroke", + butterfly: "butterfly", + mixed: "mixed", + drill: "drill", + im: "im", +} + +/** Swimming drill type */ +enum DrillType { + kick: "kick", + pull: "pull", + drill: "drill", +} + +/** Swimming equipment values */ +enum SwimEquipment { + none: "none", + kickboard: "kickboard", + paddles: "paddles", + pull_buoy: "pull_buoy", + fins: "fins", + snorkel: "snorkel", +} + +// ===== MODELS ===== + +/** Completion condition defining how a step ends */ +model CompletionCondition { + /** Type of completion condition */ + type: CompletionConditionType; + + /** Value for the completion condition (e.g., 1800 seconds, 5000 meters, 10 reps) */ + @minValue(0) + value?: float32; +} + +/** + * Intensity target for a workout step. + * + * **Important**: Use EITHER `value` (exact target) OR `value_low`/`value_high` (range target), never both. + * + * - **No value targets**: `open` — no fields needed + * - **Exact value targets**: `repetition`, `rpe`, `heart_rate_zone`, `power_zone`, `tss`, `if`, `swim_stroke` — use `value` only + * - **Range targets**: `speed`, `pace`, `heart_rate`, `power`, `cadence`, all `*_percentage`, `*_lap` — use `value_low` and/or `value_high` + * + * Specifying both `value` and `value_low`/`value_high` will return a 400 error. + */ +@example(#{target_type: TargetType.heart_rate, value_low: 140, value_high: 160}, #{ title: "Heart rate zone (range)" }) +@example(#{target_type: TargetType.rpe, value: 7}, #{ title: "RPE (exact value)" }) +@example(#{target_type: TargetType.open}, #{ title: "Open target (no value)" }) +model IntensityTarget { + /** Type of target */ + target_type: TargetType; + + /** + * Exact value target. Use for target types that take a single value (e.g., rpe, zone, repetition). + * Cannot be combined with value_low/value_high. + */ + @minValue(0) + value?: float32; + + /** + * Low end of target range. Use for target types that take a range (e.g., speed, heart_rate, power). + * Cannot be combined with value. + */ + @minValue(0) + value_low?: float32; + + /** + * High end of target range. Use for target types that take a range. + * Cannot be combined with value. Must be greater than value_low if both are provided. + */ + @minValue(0) + value_high?: float32; +} + +/** Strength data attached to a step (only valid when sport is strength) */ +model StrengthData { + /** Name of exercise shown to the athlete */ + exercise_name?: string; + + /** Load used for the exercise */ + @minValue(0) + weight?: float32; + + /** Display unit for weight */ + weight_display_unit?: WeightUnit; +} + +/** Swimming data attached to a step (only valid when using swimming sport type) */ +model SwimmingStepData { + /** Swim stroke focus */ + stroke?: SwimStroke; + + /** Drill type (when stroke is drill) */ + drill_type?: DrillType; + + /** Optional swim equipment */ + equipment?: SwimEquipment; +} + +/** A single workout step within a step block */ +model WorkoutStep { + /** How this step completes */ + completion_condition: CompletionCondition; + + /** Intensity type for this step */ + intensity_type: IntensityType; + + /** Target intensities for this step (heart rate, power, pace, etc.) */ + intensity_targets?: IntensityTarget[]; + + /** Optional notes shown to the athlete */ + notes?: string; + + /** Optional strength payload (strength sport only) */ + strength?: StrengthData; + + /** Optional swimming payload (swimming sport only) */ + swimming?: SwimmingStepData; +} + +/** A block of steps that can repeat */ +model StepBlock { + /** Steps within this block */ + steps: WorkoutStep[]; + + /** + * Completion condition for the block (controls repeats). + * + * Examples: + * - `{ "type": "reps", "value": 4 }` - Repeat block 4 times + * - `{ "type": "time", "value": 1200 }` - Repeat until 20 minutes total + * - `{ "type": "distance", "value": 5000 }` - Repeat until 5km total + * - `{ "type": "open" }` - No repeat (single execution) + * + * If omitted, the block executes once (no repeat). + */ + completion_condition?: CompletionCondition; +} + +/** Complete workout template */ +model WorkoutTemplate { + /** Workout name/title */ + name: string; + + /** Sport/activity type */ + sport: SportType; + + /** Blocks of steps that make up the workout */ + step_blocks: StepBlock[]; + + /** Optional workout description */ + description?: string; + + /** Indoor/outdoor/pool environment */ + environment?: EnvironmentType; + + /** For lap_swimming: pool length in meters (can be overridden at scheduling time) */ + @minValue(0) + pool_length_meters?: float32; + + /** Estimated total duration in seconds (read-only, populated on retrieval) */ + estimated_duration_seconds?: float32; + + /** Estimated total distance in meters (read-only, populated on retrieval) */ + estimated_distance_meters?: float32; + + /** Estimated total calories (read-only, populated on retrieval) */ + estimated_calories?: float32; +} + +/** Coercion warning returned when workout features cannot be fully represented */ +model CoercionWarning { + /** JSON path to the field that was coerced (e.g., "step_blocks[0].steps[0].intensity_targets") */ + path: string; + + /** Human-readable warning message describing what was coerced */ + message: string; +} + +// ===== REQUEST/RESPONSE MODELS ===== + +/** Request to create a workout template */ +model CreateWorkoutTemplateRequest is WorkoutTemplate {} + +/** Response from creating a workout template */ +model CreateWorkoutTemplateResponse { + status: "success"; + workout_id: string; +} + +/** Workout template with its ID (returned by GET endpoints) */ +model WorkoutTemplateWithId is WorkoutTemplate { + /** Unique identifier for this workout template */ + workout_id: string; +} + +/** Response from listing workout templates */ +model ListWorkoutTemplatesResponse is Array {} + +/** Response from deleting a workout template */ +model DeleteWorkoutTemplateResponse { + status: "success"; +} + +/** Request body to plan (schedule) a workout for an athlete */ +model PlanWorkoutRequest { + /** Planned/scheduled date in YYYY-MM-DD format */ + @pattern("^\\d{4}-\\d{2}-\\d{2}$") + planned_date: string; + + /** + * User's threshold heart rate in BPM. + * Used to resolve heart_rate_threshold_percentage targets when the device doesn't support native percentages. + */ + @minValue(0) + threshold_heart_rate?: float32; + + /** + * User's maximum heart rate in BPM. + * Used to resolve heart_rate_max_percentage targets when the device doesn't support native percentages. + */ + @minValue(0) + max_heart_rate?: float32; + + /** + * User's threshold speed in m/s. + * Used to resolve speed_percentage targets when the device doesn't support native percentages. + */ + @minValue(0) + threshold_speed?: float32; + + /** + * User's functional threshold power in watts. + * Used to resolve power_percentage targets when the device doesn't support native percentages. + */ + @minValue(0) + ftp?: float32; + + /** + * Pool length in meters (overrides template value for lap swimming workouts). + * If not provided, uses the value from the workout template. + */ + @minValue(0) + pool_length_meters?: float32; +} + +/** Response from planning a workout */ +model PlanWorkoutResponse { + status: "success"; + planned_workout_id: string; + provider_workout_id?: string; + coercion_warnings?: CoercionWarning[]; +} + +/** Request to update a planned workout */ +model UpdatePlannedWorkoutRequest { + /** New planned date in YYYY-MM-DD format */ + @pattern("^\\d{4}-\\d{2}-\\d{2}$") + planned_date: string; +} + +/** Response from updating a planned workout */ +model UpdatePlannedWorkoutResponse { + status: "success"; + planned_workout_id?: string; + coercion_warnings?: CoercionWarning[]; +} + +/** Individual planned workout in list/get response */ +model PlannedWorkout { + planned_workout_id: string; + workout_id?: string; + + @pattern("^\\d{4}-\\d{2}-\\d{2}$") + planned_date: string; + + provider_workout_id?: string; + coercion_warnings?: CoercionWarning[]; + is_external: boolean; + created_at: string; + last_updated_at: string; +} + +/** Response from listing planned workouts */ +model ListPlannedWorkoutsResponse { + planned_workouts: PlannedWorkout[]; +} + +// ===== API ENDPOINTS ===== + +/** Workout Templates */ +@route("/workouts") +namespace Workouts { + /** + * Create a workout template + * + * POST /workouts + */ + @post + @route("") + op createWorkoutTemplate( + ...TerraHeaders, + @body body: CreateWorkoutTemplateRequest + ): { + @statusCode statusCode: 200; + @body body: CreateWorkoutTemplateResponse; + } | { + @statusCode statusCode: 400; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * List all workout templates + * + * GET /workouts + */ + @get + @route("") + op listWorkoutTemplates( + ...TerraHeaders, + ): ListWorkoutTemplatesResponse | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * Get a workout template by ID + * + * GET /workouts/{workout_id} + */ + @get + @route("/{workout_id}") + op getWorkoutTemplate( + ...TerraHeaders, + @path workout_id: string, + ): WorkoutTemplateWithId | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * Delete a workout template + * + * DELETE /workouts/{workout_id} + */ + @delete + @route("/{workout_id}") + op deleteWorkoutTemplate( + ...TerraHeaders, + @path workout_id: string, + ): DeleteWorkoutTemplateResponse | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * Plan (schedule) a workout for an athlete + * + * POST /workouts/{workout_id}/plan?user_id=USER_ID + */ + @post + @route("/{workout_id}/plan") + op planWorkout( + ...TerraHeaders, + @path workout_id: string, + @query user_id: string, + @body body: PlanWorkoutRequest + ): { + @statusCode statusCode: 201; + @body body: PlanWorkoutResponse; + } | { + @statusCode statusCode: 400; + @body error: { detail: string }; + } | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 424; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; +} + +/** Planned Workouts */ +@route("/plannedWorkouts") +namespace PlannedWorkouts { + /** + * List planned workouts + * + * GET /plannedWorkouts?user_id=USER_ID&start_date=YYYY-MM-DD&end_date=YYYY-MM-DD + */ + @get + @route("") + op listPlannedWorkouts( + ...TerraHeaders, + @query user_id: string, + @query start_date?: string, + @query end_date?: string + ): ListPlannedWorkoutsResponse | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * Get a planned workout by ID + * + * GET /plannedWorkouts/{planned_workout_id} + */ + @get + @route("/{planned_workout_id}") + op getPlannedWorkout( + ...TerraHeaders, + @path planned_workout_id: string + ): PlannedWorkout | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * Update a planned workout + * + * PATCH /plannedWorkouts/{planned_workout_id}?user_id=USER_ID + */ + @patch + @route("/{planned_workout_id}") + op updatePlannedWorkout( + ...TerraHeaders, + @path planned_workout_id: string, + @query user_id: string, + @body body: UpdatePlannedWorkoutRequest + ): UpdatePlannedWorkoutResponse | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 424; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; + + /** + * Delete a planned workout + * + * DELETE /plannedWorkouts/{planned_workout_id}?user_id=USER_ID + */ + @delete + @route("/{planned_workout_id}") + op deletePlannedWorkout( + ...TerraHeaders, + @path planned_workout_id: string, + @query user_id: string + ): { + @statusCode statusCode: 204; + } | { + @statusCode statusCode: 404; + @body error: { detail: string }; + } | { + @statusCode statusCode: 500; + @body error: { detail: string }; + }; +} diff --git a/data_models/specs/data_models/tspconfig.yaml b/data_models/specs/data_models/tspconfig.yaml new file mode 100644 index 0000000..e74d636 --- /dev/null +++ b/data_models/specs/data_models/tspconfig.yaml @@ -0,0 +1,7 @@ +emit: + - "@typespec/openapi3" +options: + "@typespec/openapi3": + output-file: workouts.yaml + openapi-versions: + - "3.1.0" diff --git a/workouts.yaml b/workouts.yaml new file mode 100644 index 0000000..1942bef --- /dev/null +++ b/workouts.yaml @@ -0,0 +1,1039 @@ +openapi: 3.1.0 +info: + title: Terra Workouts + Planned Workouts API + version: 0.0.0 +tags: [] +paths: + /plannedWorkouts: + get: + operationId: PlannedWorkouts_listPlannedWorkouts + description: |- + List planned workouts + + GET /plannedWorkouts?user_id=USER_ID&start_date=YYYY-MM-DD&end_date=YYYY-MM-DD + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: user_id + in: query + required: true + schema: + type: string + explode: false + - name: start_date + in: query + required: false + schema: + type: string + explode: false + - name: end_date + in: query + required: false + schema: + type: string + explode: false + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListPlannedWorkoutsResponse' + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + /plannedWorkouts/{planned_workout_id}: + get: + operationId: PlannedWorkouts_getPlannedWorkout + description: |- + Get a planned workout by ID + + GET /plannedWorkouts/{planned_workout_id} + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: planned_workout_id + in: path + required: true + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/PlannedWorkout' + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + patch: + operationId: PlannedWorkouts_updatePlannedWorkout + description: |- + Update a planned workout + + PATCH /plannedWorkouts/{planned_workout_id}?user_id=USER_ID + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: planned_workout_id + in: path + required: true + schema: + type: string + - name: user_id + in: query + required: true + schema: + type: string + explode: false + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/UpdatePlannedWorkoutResponse' + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '424': + description: Client error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/UpdatePlannedWorkoutRequest' + delete: + operationId: PlannedWorkouts_deletePlannedWorkout + description: |- + Delete a planned workout + + DELETE /plannedWorkouts/{planned_workout_id}?user_id=USER_ID + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: planned_workout_id + in: path + required: true + schema: + type: string + - name: user_id + in: query + required: true + schema: + type: string + explode: false + responses: + '204': + description: 'There is no content to send for this request, but the headers may be useful. ' + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + /workouts: + post: + operationId: Workouts_createWorkoutTemplate + description: |- + Create a workout template + + POST /workouts + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateWorkoutTemplateResponse' + '400': + description: The server could not understand the request due to invalid syntax. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateWorkoutTemplateRequest' + get: + operationId: Workouts_listWorkoutTemplates + description: |- + List all workout templates + + GET /workouts + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListWorkoutTemplatesResponse' + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + /workouts/{workout_id}: + get: + operationId: Workouts_getWorkoutTemplate + description: |- + Get a workout template by ID + + GET /workouts/{workout_id} + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: workout_id + in: path + required: true + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/WorkoutTemplateWithId' + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + delete: + operationId: Workouts_deleteWorkoutTemplate + description: |- + Delete a workout template + + DELETE /workouts/{workout_id} + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: workout_id + in: path + required: true + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteWorkoutTemplateResponse' + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + /workouts/{workout_id}/plan: + post: + operationId: Workouts_planWorkout + description: |- + Plan (schedule) a workout for an athlete + + POST /workouts/{workout_id}/plan?user_id=USER_ID + parameters: + - $ref: '#/components/parameters/TerraHeaders.devId' + - $ref: '#/components/parameters/TerraHeaders.apiKey' + - name: workout_id + in: path + required: true + schema: + type: string + - name: user_id + in: query + required: true + schema: + type: string + explode: false + responses: + '201': + description: The request has succeeded and a new resource has been created as a result. + content: + application/json: + schema: + $ref: '#/components/schemas/PlanWorkoutResponse' + '400': + description: The server could not understand the request due to invalid syntax. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '404': + description: The server cannot find the requested resource. + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '424': + description: Client error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + '500': + description: Server error + content: + application/json: + schema: + type: object + properties: + detail: + type: string + required: + - detail + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/PlanWorkoutRequest' +security: + - ApiKeyAuth: [] + ApiKeyAuth_: [] +components: + parameters: + TerraHeaders.apiKey: + name: x-api-key + in: header + required: true + schema: + type: string + TerraHeaders.devId: + name: dev-id + in: header + required: true + schema: + type: string + schemas: + CoercionWarning: + type: object + required: + - path + - message + properties: + path: + type: string + description: JSON path to the field that was coerced (e.g., "step_blocks[0].steps[0].intensity_targets") + message: + type: string + description: Human-readable warning message describing what was coerced + description: Coercion warning returned when workout features cannot be fully represented + CompletionCondition: + type: object + required: + - type + properties: + type: + allOf: + - $ref: '#/components/schemas/CompletionConditionType' + description: Type of completion condition + value: + type: number + format: float + minimum: 0 + description: Value for the completion condition (e.g., 1800 seconds, 5000 meters, 10 reps) + description: Completion condition defining how a step ends + CompletionConditionType: + type: string + enum: + - time + - distance + - calories + - reps + - open + - hr_less_than + - hr_greater_than + - power_less_than + - power_greater_than + description: Completion condition type - how a step ends + CreateWorkoutTemplateRequest: + type: object + required: + - name + - sport + - step_blocks + properties: + name: + type: string + description: Workout name/title + sport: + allOf: + - $ref: '#/components/schemas/SportType' + description: Sport/activity type + step_blocks: + type: array + items: + $ref: '#/components/schemas/StepBlock' + description: Blocks of steps that make up the workout + description: + type: string + description: Optional workout description + environment: + allOf: + - $ref: '#/components/schemas/EnvironmentType' + description: Indoor/outdoor/pool environment + pool_length_meters: + type: number + format: float + minimum: 0 + description: 'For lap_swimming: pool length in meters (can be overridden at scheduling time)' + estimated_duration_seconds: + type: number + format: float + description: Estimated total duration in seconds (read-only, populated on retrieval) + estimated_distance_meters: + type: number + format: float + description: Estimated total distance in meters (read-only, populated on retrieval) + estimated_calories: + type: number + format: float + description: Estimated total calories (read-only, populated on retrieval) + description: Request to create a workout template + CreateWorkoutTemplateResponse: + type: object + required: + - status + - workout_id + properties: + status: + type: string + enum: + - success + workout_id: + type: string + description: Response from creating a workout template + DeleteWorkoutTemplateResponse: + type: object + required: + - status + properties: + status: + type: string + enum: + - success + description: Response from deleting a workout template + DrillType: + type: string + enum: + - kick + - pull + - drill + description: Swimming drill type + EnvironmentType: + type: string + enum: + - indoor + - outdoor + - pool + description: Environment type for the workout (indoor/outdoor/pool) + IntensityTarget: + type: object + required: + - target_type + properties: + target_type: + allOf: + - $ref: '#/components/schemas/TargetType' + description: Type of target + value: + type: number + format: float + minimum: 0 + description: |- + Exact value target. Use for target types that take a single value (e.g., rpe, zone, repetition). + Cannot be combined with value_low/value_high. + value_low: + type: number + format: float + minimum: 0 + description: |- + Low end of target range. Use for target types that take a range (e.g., speed, heart_rate, power). + Cannot be combined with value. + value_high: + type: number + format: float + minimum: 0 + description: |- + High end of target range. Use for target types that take a range. + Cannot be combined with value. Must be greater than value_low if both are provided. + description: |- + Intensity target for a workout step. + + **Important**: Use EITHER `value` (exact target) OR `value_low`/`value_high` (range target), never both. + + - **No value targets**: `open` — no fields needed + - **Exact value targets**: `repetition`, `rpe`, `heart_rate_zone`, `power_zone`, `tss`, `if`, `swim_stroke` — use `value` only + - **Range targets**: `speed`, `pace`, `heart_rate`, `power`, `cadence`, all `*_percentage`, `*_lap` — use `value_low` and/or `value_high` + + Specifying both `value` and `value_low`/`value_high` will return a 400 error. + examples: + - target_type: open + - target_type: rpe + value: 7 + - target_type: heart_rate + value_low: 140 + value_high: 160 + IntensityType: + type: string + enum: + - warmup + - active + - rest + - recovery + - cooldown + description: Intensity type for a workout step + ListPlannedWorkoutsResponse: + type: object + required: + - planned_workouts + properties: + planned_workouts: + type: array + items: + $ref: '#/components/schemas/PlannedWorkout' + description: Response from listing planned workouts + ListWorkoutTemplatesResponse: + type: array + items: + $ref: '#/components/schemas/WorkoutTemplateWithId' + description: Response from listing workout templates + PlanWorkoutRequest: + type: object + required: + - planned_date + properties: + planned_date: + type: string + pattern: ^\d{4}-\d{2}-\d{2}$ + description: Planned/scheduled date in YYYY-MM-DD format + threshold_heart_rate: + type: number + format: float + minimum: 0 + description: |- + User's threshold heart rate in BPM. + Used to resolve heart_rate_threshold_percentage targets when the device doesn't support native percentages. + max_heart_rate: + type: number + format: float + minimum: 0 + description: |- + User's maximum heart rate in BPM. + Used to resolve heart_rate_max_percentage targets when the device doesn't support native percentages. + threshold_speed: + type: number + format: float + minimum: 0 + description: |- + User's threshold speed in m/s. + Used to resolve speed_percentage targets when the device doesn't support native percentages. + ftp: + type: number + format: float + minimum: 0 + description: |- + User's functional threshold power in watts. + Used to resolve power_percentage targets when the device doesn't support native percentages. + pool_length_meters: + type: number + format: float + minimum: 0 + description: |- + Pool length in meters (overrides template value for lap swimming workouts). + If not provided, uses the value from the workout template. + description: Request body to plan (schedule) a workout for an athlete + PlanWorkoutResponse: + type: object + required: + - status + - planned_workout_id + properties: + status: + type: string + enum: + - success + planned_workout_id: + type: string + provider_workout_id: + type: string + coercion_warnings: + type: array + items: + $ref: '#/components/schemas/CoercionWarning' + description: Response from planning a workout + PlannedWorkout: + type: object + required: + - planned_workout_id + - planned_date + - is_external + - created_at + - last_updated_at + properties: + planned_workout_id: + type: string + workout_id: + type: string + planned_date: + type: string + pattern: ^\d{4}-\d{2}-\d{2}$ + provider_workout_id: + type: string + coercion_warnings: + type: array + items: + $ref: '#/components/schemas/CoercionWarning' + is_external: + type: boolean + created_at: + type: string + last_updated_at: + type: string + description: Individual planned workout in list/get response + SportType: + type: string + enum: + - running + - cycling + - swimming + - strength + - rowing + - yoga + - pilates + - cardio + description: Sport type for the workout. Use the `environment` field on the template for indoor/outdoor/pool distinction. + StepBlock: + type: object + required: + - steps + properties: + steps: + type: array + items: + $ref: '#/components/schemas/WorkoutStep' + description: Steps within this block + completion_condition: + allOf: + - $ref: '#/components/schemas/CompletionCondition' + description: |- + Completion condition for the block (controls repeats). + + Examples: + - `{ "type": "reps", "value": 4 }` - Repeat block 4 times + - `{ "type": "time", "value": 1200 }` - Repeat until 20 minutes total + - `{ "type": "distance", "value": 5000 }` - Repeat until 5km total + - `{ "type": "open" }` - No repeat (single execution) + + If omitted, the block executes once (no repeat). + description: A block of steps that can repeat + StrengthData: + type: object + properties: + exercise_name: + type: string + description: Name of exercise shown to the athlete + weight: + type: number + format: float + minimum: 0 + description: Load used for the exercise + weight_display_unit: + allOf: + - $ref: '#/components/schemas/WeightUnit' + description: Display unit for weight + description: Strength data attached to a step (only valid when sport is strength) + SwimEquipment: + type: string + enum: + - none + - kickboard + - paddles + - pull_buoy + - fins + - snorkel + description: Swimming equipment values + SwimStroke: + type: string + enum: + - freestyle + - backstroke + - breaststroke + - butterfly + - mixed + - drill + - im + description: Swimming stroke values + SwimmingStepData: + type: object + properties: + stroke: + allOf: + - $ref: '#/components/schemas/SwimStroke' + description: Swim stroke focus + drill_type: + allOf: + - $ref: '#/components/schemas/DrillType' + description: Drill type (when stroke is drill) + equipment: + allOf: + - $ref: '#/components/schemas/SwimEquipment' + description: Optional swim equipment + description: Swimming data attached to a step (only valid when using swimming sport type) + TargetType: + type: string + enum: + - open + - speed + - pace + - heart_rate + - heart_rate_max_percentage + - heart_rate_threshold_percentage + - heart_rate_zone + - heart_rate_lap + - power + - power_percentage + - power_zone + - cadence + - rpe + - speed_percentage + - speed_lap + - swim_stroke + - repetition + - tss + - if + description: Target type for intensity + UpdatePlannedWorkoutRequest: + type: object + required: + - planned_date + properties: + planned_date: + type: string + pattern: ^\d{4}-\d{2}-\d{2}$ + description: New planned date in YYYY-MM-DD format + description: Request to update a planned workout + UpdatePlannedWorkoutResponse: + type: object + required: + - status + properties: + status: + type: string + enum: + - success + planned_workout_id: + type: string + coercion_warnings: + type: array + items: + $ref: '#/components/schemas/CoercionWarning' + description: Response from updating a planned workout + WeightUnit: + type: string + enum: + - kg + - lbs + description: Weight unit + WorkoutStep: + type: object + required: + - completion_condition + - intensity_type + properties: + completion_condition: + allOf: + - $ref: '#/components/schemas/CompletionCondition' + description: How this step completes + intensity_type: + allOf: + - $ref: '#/components/schemas/IntensityType' + description: Intensity type for this step + intensity_targets: + type: array + items: + $ref: '#/components/schemas/IntensityTarget' + description: Target intensities for this step (heart rate, power, pace, etc.) + notes: + type: string + description: Optional notes shown to the athlete + strength: + allOf: + - $ref: '#/components/schemas/StrengthData' + description: Optional strength payload (strength sport only) + swimming: + allOf: + - $ref: '#/components/schemas/SwimmingStepData' + description: Optional swimming payload (swimming sport only) + description: A single workout step within a step block + WorkoutTemplate: + type: object + required: + - name + - sport + - step_blocks + properties: + name: + type: string + description: Workout name/title + sport: + allOf: + - $ref: '#/components/schemas/SportType' + description: Sport/activity type + step_blocks: + type: array + items: + $ref: '#/components/schemas/StepBlock' + description: Blocks of steps that make up the workout + description: + type: string + description: Optional workout description + environment: + allOf: + - $ref: '#/components/schemas/EnvironmentType' + description: Indoor/outdoor/pool environment + pool_length_meters: + type: number + format: float + minimum: 0 + description: 'For lap_swimming: pool length in meters (can be overridden at scheduling time)' + estimated_duration_seconds: + type: number + format: float + description: Estimated total duration in seconds (read-only, populated on retrieval) + estimated_distance_meters: + type: number + format: float + description: Estimated total distance in meters (read-only, populated on retrieval) + estimated_calories: + type: number + format: float + description: Estimated total calories (read-only, populated on retrieval) + description: Complete workout template + WorkoutTemplateWithId: + type: object + required: + - name + - sport + - step_blocks + - workout_id + properties: + name: + type: string + description: Workout name/title + sport: + allOf: + - $ref: '#/components/schemas/SportType' + description: Sport/activity type + step_blocks: + type: array + items: + $ref: '#/components/schemas/StepBlock' + description: Blocks of steps that make up the workout + description: + type: string + description: Optional workout description + environment: + allOf: + - $ref: '#/components/schemas/EnvironmentType' + description: Indoor/outdoor/pool environment + pool_length_meters: + type: number + format: float + minimum: 0 + description: 'For lap_swimming: pool length in meters (can be overridden at scheduling time)' + estimated_duration_seconds: + type: number + format: float + description: Estimated total duration in seconds (read-only, populated on retrieval) + estimated_distance_meters: + type: number + format: float + description: Estimated total distance in meters (read-only, populated on retrieval) + estimated_calories: + type: number + format: float + description: Estimated total calories (read-only, populated on retrieval) + workout_id: + type: string + description: Unique identifier for this workout template + description: Workout template with its ID (returned by GET endpoints) + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: x-api-key + ApiKeyAuth_: + type: apiKey + in: header + name: dev-id +servers: + - url: https://access.tryterra.co/api/v2 + description: Production server + variables: {}