diff --git a/.gitattributes b/.gitattributes index 1ff0c423042b..700db59da977 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,6 +3,9 @@ ############################################################################### * text=auto +# Use unix line endings always, even on Windows +.github/**/*.js text eol=lf + ############################################################################### # Set default behavior for command prompt diff. # diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100644 index 000000000000..4ebc8aea50e0 --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1 @@ +coverage diff --git a/.github/.prettierignore b/.github/.prettierignore new file mode 100644 index 000000000000..31053ae6be68 --- /dev/null +++ b/.github/.prettierignore @@ -0,0 +1,37 @@ +# python customizations +actions +agents +hooks +skills +workflows +PULL_REQUEST_TEMPLATE.md + +# this file +.prettierignore + +# code coverage +coverage + +# specs in test folders +fixtures +specification + +# auto-generated agentic workflow lock files +workflows/*.lock.yml + +# unmanaged files and folders +**/*instructions.md +chatmodes +ISSUE_TEMPLATE +policies +prompts +PULL_REQUEST_TEMPLATE + +# lock files for agent workflows +**/*.lock.yml + +# synced from external repos +workflows/post-apiview.yml + +# synced GitHub skills +.github/skills/azsdk-common-* \ No newline at end of file diff --git a/.github/.prettierrc.yaml b/.github/.prettierrc.yaml new file mode 100644 index 000000000000..caa7e1c7a610 --- /dev/null +++ b/.github/.prettierrc.yaml @@ -0,0 +1,15 @@ +# Keep in sync with eng/tools/.prettierrc.yaml + +plugins: + - prettier-plugin-organize-imports + +# Aligned with microsoft/typespec +printWidth: 100 + +overrides: + # tsconfig.json is actually parsed as JSONC + - files: + - tsconfig.json + - tsconfig.*.json + options: + parser: jsonc diff --git a/.github/actions/install-deps-github-script/action.yaml b/.github/actions/install-deps-github-script/action.yaml new file mode 100644 index 000000000000..7cce5a5ad982 --- /dev/null +++ b/.github/actions/install-deps-github-script/action.yaml @@ -0,0 +1,17 @@ +name: Install dependencies for github-script actions +description: Installs dependencies for github-script actions + +runs: + using: composite + + steps: + - uses: ./.github/actions/setup-node-install-deps + with: + # actions/github-script@v8 uses Node 24 + node-version: 24.x + # "--no-audit": improves performance + # "--no-fund": improves performance + # "--prefer-offline": improves performance + # "--omit dev": not needed at runtime, improves performance + install-command: "npm ci --no-audit --no-fund --prefer-offline --omit dev" + working-directory: ./.github diff --git a/.github/actions/setup-node-install-deps/action.yaml b/.github/actions/setup-node-install-deps/action.yaml new file mode 100644 index 000000000000..77c18ca91ae3 --- /dev/null +++ b/.github/actions/setup-node-install-deps/action.yaml @@ -0,0 +1,39 @@ +name: Setup Node and install dependencies +description: Uses specified Node version and installs dependencies (typically using "npm") + +inputs: + node-version: + description: "Node version to use" + default: 24.x + install-command: + description: "Command to install dependencies" + default: "npm ci --no-audit --no-fund --prefer-offline" + working-directory: + description: "Working directory" + default: "." + +runs: + using: "composite" + + steps: + - uses: actions/setup-node@v6 + with: + node-version: ${{ inputs.node-version }} + cache: "npm" + cache-dependency-path: ${{ inputs.working-directory }}/package-lock.json + + - run: | + echo "::group::$INSTALL_COMMAND" + $INSTALL_COMMAND + echo "::endgroup::" + shell: bash + env: + INSTALL_COMMAND: ${{ inputs.install-command }} + working-directory: ${{ inputs.working-directory }} + + - run: | + echo "::group::npm ls -a" + npm ls -a || true + echo "::endgroup::" + shell: bash + working-directory: ${{ inputs.working-directory }} diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..20e5ed096d67 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,74 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 # default:5 + cooldown: + default-days: 7 + exclude-paths: + - ".github/workflows/*.lock.{yaml,yml}" + - package-ecosystem: "npm" + directories: + - "/" + - "/eng/tools" + - "/eng/tools/**" + schedule: + interval: "daily" + open-pull-requests-limit: 10 # default:5 + cooldown: + default-days: 7 + exclude: + # Allow immediate updates of self-owned packages + - "@azure-tools/*" + - "@autorest/*" + - "@azure/*" + - "@microsoft.azure/*" + - "@typespec/*" + - "oav" + ignore: + # Updated manually to align with minimum supported Node version + - dependency-name: "@types/node" + # Updated manually by the team maintaining this package + - dependency-name: "@azure-tools/openai-typespec" + # Updated manually by the Liftr team + - dependency-name: "@azure-tools/typespec-liftr-base" + # Only allow patch updates for spec-gen-sdk + - dependency-name: "@azure-tools/spec-gen-sdk" + update-types: ["version-update:semver-minor", "version-update:semver-major"] + groups: + # Ships separately from other typespec packages + typespec-client-generator-cli: + patterns: + - "@azure-tools/typespec-client-generator-cli" + # Ships separately from other typespec packages + openapi-to-typespec: + patterns: + - "@autorest/openapi-to-typespec" + typespec: + patterns: + - "*typespec*" + eslint: + patterns: + - "*eslint*" + versioning-strategy: increase-if-necessary + - package-ecosystem: "npm" + directories: + - "/.github" + - "/.github/shared" + schedule: + interval: "daily" + open-pull-requests-limit: 10 # default:5 + cooldown: + default-days: 7 + ignore: + # Updated manually to align with minimum supported Node version + - dependency-name: "@types/node" + # Points to "github:actions/github-script" since package isn't published to npmjs + - dependency-name: "@types/github-script" + groups: + eslint: + patterns: + - "*eslint*" + versioning-strategy: increase-if-necessary diff --git a/.github/eslint.config.js b/.github/eslint.config.js new file mode 100644 index 000000000000..fb4765fea22f --- /dev/null +++ b/.github/eslint.config.js @@ -0,0 +1,16 @@ +import { defineConfig } from "eslint/config"; +import { defineBaseConfig } from "./shared/eslint.base.config.js"; + +export default defineConfig( + defineBaseConfig({ + // ensures the tsconfig path resolves relative to this file (so cannot be defined in base file) + // default is process.cwd() when running eslint, which may be incorrect + tsconfigRootDir: import.meta.dirname, + }), + { + ignores: [ + // generated by `vitest --coverage` + "shared/coverage/**", + ], + }, +); diff --git a/.github/package-lock.json b/.github/package-lock.json new file mode 100644 index 000000000000..4098cd12b5a5 --- /dev/null +++ b/.github/package-lock.json @@ -0,0 +1,3710 @@ +{ + "name": ".github", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.1.3", + "@js-temporal/polyfill": "0.5.1", + "debug": "^4.4.3", + "js-yaml": "^4.1.0", + "markdown-table": "^3.0.4", + "marked": "^18.0.0", + "simple-git": "^3.36.0", + "zod": "^4.3.5" + }, + "devDependencies": { + "@actions/github-script": "github:actions/github-script", + "@eslint/js": "^10.0.0", + "@octokit/endpoint": "^11.0.0", + "@octokit/rest": "^22.0.0", + "@octokit/types": "^16.0.0", + "@octokit/webhooks-types": "^7.5.1", + "@tsconfig/node20": "^20.1.4", + "@types/debug": "^4.1.12", + "@types/js-yaml": "^4.0.9", + "@types/node": "^20.0.0", + "@types/semver": "^7.7.1", + "@vitest/coverage-v8": "^4.1.0", + "cross-env": "^10.1.0", + "eslint": "^10.0.0", + "fflate": "0.8.2", + "globals": "^17.0.0", + "prettier": "3.8.3", + "prettier-plugin-organize-imports": "^4.2.0", + "semver": "^7.7.1", + "tinybench": "^6.0.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.58.0", + "vitest": "^4.1.0" + } + }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/github": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.1.tgz", + "integrity": "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/http-client": "^2.2.0", + "@octokit/core": "^5.0.1", + "@octokit/plugin-paginate-rest": "^9.2.2", + "@octokit/plugin-rest-endpoint-methods": "^10.4.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "undici": "^5.28.5" + } + }, + "node_modules/@actions/github-script": { + "version": "7.0.1", + "resolved": "git+ssh://git@github.com/actions/github-script.git#450193c5abd4cdb17ba9f3ffcfe8f635c4bb6c2a", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/github": "^6.0.0", + "@actions/glob": "^0.4.0", + "@actions/io": "^1.1.3", + "@octokit/core": "^5.0.1", + "@octokit/plugin-request-log": "^4.0.0", + "@octokit/plugin-retry": "^6.0.1", + "@types/node": "^24.1.0" + }, + "engines": { + "node": ">=24" + } + }, + "node_modules/@actions/github-script/node_modules/@types/node": { + "version": "24.13.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.2.tgz", + "integrity": "sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@actions/github-script/node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@actions/glob": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@actions/glob/-/glob-0.4.0.tgz", + "integrity": "sha512-+eKIGFhsFa4EBwaf/GMyzCdWrXWymGXfFmZU3FHQvYS8mPcHtTtZONbkcqqUMzw9mJ/pImEBFET1JNifhqGsAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@actions/core": "^1.9.1", + "minimatch": "^3.0.4" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.5.tgz", + "integrity": "sha512-orNOYXw3hYXxxisXMldjzjBzqqTLBPbwOtHg7ovBPvfBHDue1qM9YJENZ3W2BQuS+7z4ThogMbEzEsov57Itkg==", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/json-schema": "^7.0.15" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-array/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", + "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@js-temporal/polyfill": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@js-temporal/polyfill/-/polyfill-0.5.1.tgz", + "integrity": "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ==", + "license": "ISC", + "dependencies": { + "jsbi": "^4.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz", + "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/core/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", + "integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/endpoint/node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/graphql/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "27.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", + "integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-4.0.1.tgz", + "integrity": "sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.1.0.tgz", + "integrity": "sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^13.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/request-error/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request/node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/request/node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@octokit/rest": { + "version": "22.0.1", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-22.0.1.tgz", + "integrity": "sha512-Jzbhzl3CEexhnivb1iQ0KJ7s5vvjMWcmRtq5aUsKmKDrRW6z3r84ngmiFKFvpZjpiU/9/S6ITPFRpn5s/3uQJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^7.0.6", + "@octokit/plugin-paginate-rest": "^14.0.0", + "@octokit/plugin-request-log": "^6.0.0", + "@octokit/plugin-rest-endpoint-methods": "^17.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/core": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", + "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.3", + "@octokit/request": "^10.0.6", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/graphql": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", + "integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^10.0.6", + "@octokit/types": "^16.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-paginate-rest": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz", + "integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-request-log": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", + "integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "17.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz", + "integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request": { + "version": "10.0.7", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.7.tgz", + "integrity": "sha512-v93h0i1yu4idj8qFPZwjehoJx4j3Ntn+JhXsdJrG9pYaX6j/XRz2RmasMUHtNgQD39nrv/VwTWSqK0RNXR8upA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.2", + "@octokit/request-error": "^7.0.2", + "@octokit/types": "^16.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/@octokit/request-error": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", + "integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^16.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/rest/node_modules/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@octokit/rest/node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/@octokit/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", + "integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^27.0.0" + } + }, + "node_modules/@octokit/webhooks-types": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/@octokit/webhooks-types/-/webhooks-types-7.6.1.tgz", + "integrity": "sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@oxc-project/types": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz", + "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz", + "integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz", + "integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz", + "integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz", + "integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz", + "integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz", + "integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz", + "integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz", + "integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz", + "integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz", + "integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz", + "integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz", + "integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@simple-git/args-pathspec": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@simple-git/args-pathspec/-/args-pathspec-1.0.3.tgz", + "integrity": "sha512-ngJMaHlsWDTfjyq9F3VIQ8b7NXbBLq5j9i5bJ6XLYtD6qlDXT7fdKY2KscWWUF8t18xx052Y/PUO1K1TRc9yKA==", + "license": "MIT" + }, + "node_modules/@simple-git/argv-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@simple-git/argv-parser/-/argv-parser-1.1.1.tgz", + "integrity": "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==", + "license": "MIT", + "dependencies": { + "@simple-git/args-pathspec": "^1.0.3" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node20": { + "version": "20.1.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.9.tgz", + "integrity": "sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.43", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.43.tgz", + "integrity": "sha512-6oYBAi5ikg4Pl+kGsoYtawUMBT2zZMCvPNF7pVLnHZfd1zf38DRiWn/gT01RYCdUqkv7Fhr+C9ot4/tb+2sVvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.1.tgz", + "integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/type-utils": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.59.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", + "integrity": "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", + "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.59.1", + "@typescript-eslint/types": "^8.59.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", + "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", + "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.1.tgz", + "integrity": "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", + "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", + "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.59.1", + "@typescript-eslint/tsconfig-utils": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", + "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", + "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.5.tgz", + "integrity": "sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.5", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.5", + "vitest": "4.1.5" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz", + "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", + "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.5", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz", + "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz", + "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.5", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz", + "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.5", + "@vitest/utils": "4.1.5", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz", + "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz", + "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.5", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz", + "integrity": "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.5.5", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", + "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", + "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", + "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbi": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.2.tgz", + "integrity": "sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew==", + "license": "Apache-2.0" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/marked": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.2.tgz", + "integrity": "sha512-NsmlUYBS/Zg57rgDWMYdnre6OTj4e+qq/JS2ot3KrYLSoHLw+sDu0Nm1ZGpRgYAq6c+b1ekaY5NzVchMCQnzcg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz", + "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", + "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.17.tgz", + "integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.127.0", + "@rolldown/pluginutils": "1.0.0-rc.17" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.17", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", + "@rolldown/binding-darwin-x64": "1.0.0-rc.17", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-git": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.36.0.tgz", + "integrity": "sha512-cGQjLjK8bxJw4QuYT7gxHw3/IouVESbhahSsHrX97MzCL1gu2u7oy38W6L2ZIGECEfIBG4BabsWDPjBxJENv9Q==", + "license": "MIT", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "@simple-git/args-pathspec": "^1.0.3", + "@simple-git/argv-parser": "^1.1.0", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinybench": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.0.1.tgz", + "integrity": "sha512-cMdWsxmysdg8mNWf1pujiWl3TW0cU6m8QuNw55QlnP3I6N96Grb0wnu5N0syHIu3LbiVZCNqlfWzWDq84HZphA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.1.tgz", + "integrity": "sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.59.1", + "@typescript-eslint/parser": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/undici": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.26.0.tgz", + "integrity": "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz", + "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.10", + "rolldown": "1.0.0-rc.17", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", + "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.5", + "@vitest/browser-preview": "4.1.5", + "@vitest/browser-webdriverio": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/ui": "4.1.5", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.1.tgz", + "integrity": "sha512-a6ENMBBGZBsnlSebQ/eKCguSBeGKSf4O7BPnqVPmYGtpBYI7VSqoVqw+QcB7kPRjbqPwhYTpFbVj/RqNz/CT0Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/.github/package.json b/.github/package.json new file mode 100644 index 000000000000..f1ef6dbd66a8 --- /dev/null +++ b/.github/package.json @@ -0,0 +1,59 @@ +{ + "_copied_from": "https://github.com/Azure/azure-rest-api-specs/blob/main/.github/package.json", + "private": true, + "type": "module", + "_comments": { + "dependencies": "Runtime dependencies must be kept to an absolute minimum for performance, ideally with no transitive dependencies", + "dependencies2": "All runtime and dev dependencies in this file, must be a superset of shared/package.json" + }, + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.1.3", + "@js-temporal/polyfill": "0.5.1", + "debug": "^4.4.3", + "js-yaml": "^4.1.0", + "marked": "^18.0.0", + "markdown-table": "^3.0.4", + "simple-git": "^3.36.0", + "zod": "^4.3.5" + }, + "devDependencies": { + "@actions/github-script": "github:actions/github-script", + "@eslint/js": "^10.0.0", + "@octokit/endpoint": "^11.0.0", + "@octokit/rest": "^22.0.0", + "@octokit/types": "^16.0.0", + "@octokit/webhooks-types": "^7.5.1", + "@tsconfig/node20": "^20.1.4", + "@types/debug": "^4.1.12", + "@types/js-yaml": "^4.0.9", + "@types/node": "^20.0.0", + "@types/semver": "^7.7.1", + "@vitest/coverage-v8": "^4.1.0", + "cross-env": "^10.1.0", + "eslint": "^10.0.0", + "fflate": "0.8.2", + "globals": "^17.0.0", + "prettier": "3.8.3", + "prettier-plugin-organize-imports": "^4.2.0", + "semver": "^7.7.1", + "tinybench": "^6.0.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.58.0", + "vitest": "^4.1.0" + }, + "scripts": { + "check": "npm run test:ci && npm run lint && npm run format:check", + "lint": "npm run lint:eslint && npm run lint:tsc", + "lint:eslint": "cross-env DEBUG=eslint:eslint,eslint:linter eslint", + "lint:tsc": "tsc --build --verbose", + "format": "prettier . --write", + "format:check": "prettier . --check", + "format:check:ci": "prettier . --check --log-level debug", + "test": "vitest", + "test:ci": "vitest run --coverage --reporter=verbose", + "validate": "npm run lint && npm run format:check && npm run test:ci" + }, + "overrides": { + "undici@^5.0.0": "^6.0.0" + } +} diff --git a/.github/shared/cmd/spec-model.js b/.github/shared/cmd/spec-model.js new file mode 100644 index 000000000000..1bae18f753c0 --- /dev/null +++ b/.github/shared/cmd/spec-model.js @@ -0,0 +1,59 @@ +#!/usr/bin/env node + +import { debugLogger } from "../src/logger.js"; +import { SpecModel } from "../src/spec-model.js"; + +const USAGE = + "Usage: npx spec-model path/to/spec [--debug] [--include-operations] [--include-refs] [--relative-paths] [--no-embed-errors]\n" + + "Examples:\n" + + " npx spec-model specification/widget\n" + + " npx spec-model specification --include-operations --include-refs > out.txt; grep out.txt '\"error\":'"; + +// Exclude first two args (node, script file) +let args = process.argv.slice(2); + +const debug = args.includes("--debug"); +args = args.filter((a) => a != "--debug"); + +const includeOperations = args.includes("--include-operations"); +args = args.filter((a) => a != "--include-operations"); + +const includeRefs = args.includes("--include-refs"); +args = args.filter((a) => a != "--include-refs"); + +const relativePaths = args.includes("--relative-paths"); +args = args.filter((a) => a != "--relative-paths"); + +const noEmbedErrors = args.includes("--no-embed-errors"); +args = args.filter((a) => a != "--no-embed-errors"); + +if (args.length < 1) { + console.error(USAGE); + process.exit(1); +} + +if (args.length > 1) { + console.error("ERROR: Too many arguments\n"); + console.error(USAGE); + process.exit(1); +} + +const specPath = args[0]; + +// Default to 'undefined' instead of 'defaultLogger', so output is always a valid JSON object (no logging) +const logger = debug ? debugLogger : undefined; + +const specModel = new SpecModel(specPath, { logger }); + +console.log( + JSON.stringify( + await specModel.toJSONAsync({ + embedErrors: !noEmbedErrors, + includeOperations, + includeRefs, + relativePaths, + }), + null, + 2, + ), +); diff --git a/.github/shared/eslint.base.config.js b/.github/shared/eslint.base.config.js new file mode 100644 index 000000000000..74b1bef11689 --- /dev/null +++ b/.github/shared/eslint.base.config.js @@ -0,0 +1,39 @@ +import eslint from "@eslint/js"; +import { defineConfig } from "eslint/config"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +/** + * @param {object} options + * @param {boolean|object} [options.projectService] + * @param {string} options.tsconfigRootDir + * @returns {import('eslint').Linter.Config[]} + */ +export function defineBaseConfig(options) { + const { projectService = true, tsconfigRootDir } = options; + + return defineConfig( + eslint.configs.recommended, + tseslint.configs.recommendedTypeChecked, + { + languageOptions: { + // we only run in node, not browser + globals: globals.node, + // required to use tseslint.configs.recommendedTypeChecked + parserOptions: { + // Defaults to "true", which is the minimum required to use tseslint.configs.recommendedTypeChecked + // Can be overridden by caller, by setting to a config object + projectService, + // Must be set by caller, since this should point to the root directory of the project being analyzed + tsconfigRootDir, + }, + }, + }, + { + ignores: [ + // generated by `vitest --coverage` + "coverage/**", + ], + }, + ); +} diff --git a/.github/shared/eslint.config.js b/.github/shared/eslint.config.js new file mode 100644 index 000000000000..750ce3d8e808 --- /dev/null +++ b/.github/shared/eslint.config.js @@ -0,0 +1,7 @@ +import { defineBaseConfig } from "./eslint.base.config.js"; + +export default defineBaseConfig({ + // ensures the tsconfig path resolves relative to this file (so cannot be defined in base file) + // default is process.cwd() when running eslint, which may be incorrect + tsconfigRootDir: import.meta.dirname, +}); diff --git a/.github/shared/package-lock.json b/.github/shared/package-lock.json new file mode 100644 index 000000000000..1603b2a769e0 --- /dev/null +++ b/.github/shared/package-lock.json @@ -0,0 +1,2905 @@ +{ + "name": "@azure-tools/specs-shared", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@azure-tools/specs-shared", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.1.3", + "debug": "^4.4.3", + "js-yaml": "^4.1.0", + "marked": "^18.0.0", + "simple-git": "^3.36.0", + "zod": "^4.3.5" + }, + "bin": { + "spec-model": "cmd/spec-model.js" + }, + "devDependencies": { + "@eslint/js": "^10.0.0", + "@tsconfig/node20": "^20.1.4", + "@types/debug": "^4.1.12", + "@types/js-yaml": "^4.0.9", + "@types/node": "^20.0.0", + "@types/semver": "^7.7.1", + "@vitest/coverage-v8": "^4.1.0", + "cross-env": "^10.1.0", + "eslint": "^10.0.0", + "globals": "^17.0.0", + "prettier": "3.8.3", + "prettier-plugin-organize-imports": "^4.2.0", + "semver": "^7.7.1", + "tinybench": "^6.0.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.58.0", + "vitest": "^4.1.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "15.3.5", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-15.3.5.tgz", + "integrity": "sha512-orNOYXw3hYXxxisXMldjzjBzqqTLBPbwOtHg7ovBPvfBHDue1qM9YJENZ3W2BQuS+7z4ThogMbEzEsov57Itkg==", + "license": "MIT", + "dependencies": { + "js-yaml": "^4.1.1" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@types/json-schema": "^7.0.15" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", + "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.5.5.tgz", + "integrity": "sha512-eIJYKTCECbP/nsKaaruF6LW967mtbQbsw4JTtSVkUQc9MneSkbrgPJAbKl9nWr0ZeowV8BfsarBmPpBzGelA2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.1.tgz", + "integrity": "sha512-rZAP3aVgB9ds9KOeUSL+zZ21hPmo8dh6fnIFwRQj5EAZl9gzR7wxYbYXYysAM8CTqGmUGyp2S4kUdV17MnGuWQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kwsites/file-exists": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz", + "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1" + } + }, + "node_modules/@kwsites/promise-deferred": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz", + "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", + "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.127.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.127.0.tgz", + "integrity": "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.17.tgz", + "integrity": "sha512-s70pVGhw4zqGeFnXWvAzJDlvxhlRollagdCCKRgOsgUOH3N1l0LIxf83AtGzmb5SiVM4Hjl5HyarMRfdfj3DaQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.17.tgz", + "integrity": "sha512-4ksWc9n0mhlZpZ9PMZgTGjeOPRu8MB1Z3Tz0Mo02eWfWCHMW1zN82Qz/pL/rC+yQa+8ZnutMF0JjJe7PjwasYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.17.tgz", + "integrity": "sha512-SUSDOI6WwUVNcWxd02QEBjLdY1VPHvlEkw6T/8nYG322iYWCTxRb1vzk4E+mWWYehTp7ERibq54LSJGjmouOsw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.17.tgz", + "integrity": "sha512-hwnz3nw9dbJ05EDO/PvcjaaewqqDy7Y1rn1UO81l8iIK1GjenME75dl16ajbvSSMfv66WXSRCYKIqfgq2KCfxw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.17.tgz", + "integrity": "sha512-IS+W7epTcwANmFSQFrS1SivEXHtl1JtuQA9wlxrZTcNi6mx+FDOYrakGevvvTwgj2JvWiK8B29/qD9BELZPyXQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-e6usGaHKW5BMNZOymS1UcEYGowQMWcgZ71Z17Sl/h2+ZziNJ1a9n3Zvcz6LdRyIW5572wBCTH/Z+bKuZouGk9Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.17.tgz", + "integrity": "sha512-b/CgbwAJpmrRLp02RPfhbudf5tZnN9nsPWK82znefso832etkem8H7FSZwxrOI9djcdTP7U6YfNhbRnh7djErg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-4EII1iNGRUN5WwGbF/kOh/EIkoDN9HsupgLQoXfY+D1oyJm7/F4t5PYU5n8SWZgG0FEwakyM8pGgwcBYruGTlA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-AH8oq3XqQo4IibpVXvPeLDI5pzkpYn0WiZAfT05kFzoJ6tQNzwRdDYQ45M8I/gslbodRZwW8uxLhbSBbkv96rA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.17.tgz", + "integrity": "sha512-cLnjV3xfo7KslbU41Z7z8BH/E1y5mzUYzAqih1d1MDaIGZRCMqTijqLv76/P7fyHuvUcfGsIpqCdddbxLLK9rA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.17.tgz", + "integrity": "sha512-0phclDw1spsL7dUB37sIARuis2tAgomCJXAHZlpt8PXZ4Ba0dRP1e+66lsRqrfhISeN9bEGNjQs+T/Fbd7oYGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.17.tgz", + "integrity": "sha512-0ag/hEgXOwgw4t8QyQvUCxvEg+V0KBcA6YuOx9g0r02MprutRF5dyljgm3EmR02O292UX7UeS6HzWHAl6KgyhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.17.tgz", + "integrity": "sha512-LEXei6vo0E5wTGwpkJ4KoT3OZJRnglwldt5ziLzOlc6qqb55z4tWNq2A+PFqCJuvWWdP53CVhG1Z9NtToDPJrA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.17.tgz", + "integrity": "sha512-gUmyzBl3SPMa6hrqFUth9sVfcLBlYsbMzBx5PlexMroZStgzGqlZ26pYG89rBb45Mnia+oil6YAIFeEWGWhoZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.17.tgz", + "integrity": "sha512-3hkiolcUAvPB9FLb3UZdfjVVNWherN1f/skkGWJP/fgSQhYUZpSIRr0/I8ZK9TkF3F7kxvJAk0+IcKvPHk9qQg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.17.tgz", + "integrity": "sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@simple-git/args-pathspec": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@simple-git/args-pathspec/-/args-pathspec-1.0.3.tgz", + "integrity": "sha512-ngJMaHlsWDTfjyq9F3VIQ8b7NXbBLq5j9i5bJ6XLYtD6qlDXT7fdKY2KscWWUF8t18xx052Y/PUO1K1TRc9yKA==", + "license": "MIT" + }, + "node_modules/@simple-git/argv-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@simple-git/argv-parser/-/argv-parser-1.1.1.tgz", + "integrity": "sha512-Q9lBcfQ+VQCpQqGJFHe5yooOS5hGdLFFbJ5R+R5aDsnkPCahtn1hSkMcORX65J2Z5lxSkD0lQorMsncuBQxYUw==", + "license": "MIT", + "dependencies": { + "@simple-git/args-pathspec": "^1.0.3" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node20": { + "version": "20.1.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.9.tgz", + "integrity": "sha512-IjlTv1RsvnPtUcjTqtVsZExKVq+KQx4g5pCP5tI7rAs6Xesl2qFwSz/tPDBC4JajkL/MlezBu3gPUwqRHl+RIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.59.1.tgz", + "integrity": "sha512-BOziFIfE+6osHO9FoJG4zjoHUcvI7fTNBSpdAwrNH0/TLvzjsk2oo8XSSOT2HhqUyhZPfHv4UOffoJ9oEEQ7Ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/type-utils": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.59.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.59.1.tgz", + "integrity": "sha512-HDQH9O/47Dxi1ceDhBXdaldtf/WV9yRYMjbjCuNk3qnaTD564qwv61Y7+gTxwxRKzSrgO5uhtw584igXVuuZkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.59.1.tgz", + "integrity": "sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.59.1", + "@typescript-eslint/types": "^8.59.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.59.1.tgz", + "integrity": "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.59.1.tgz", + "integrity": "sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.59.1.tgz", + "integrity": "sha512-klWPBR2ciQHS3f++ug/mVnWKPjBUo7icEL3FAO1lhAR1Z1i5NQYZ1EannMSRYcq5qCv5wNALlXr6fksRHyYl7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.59.1.tgz", + "integrity": "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.59.1.tgz", + "integrity": "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.59.1", + "@typescript-eslint/tsconfig-utils": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/visitor-keys": "8.59.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.59.1.tgz", + "integrity": "sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.59.1", + "@typescript-eslint/types": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.59.1.tgz", + "integrity": "sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.59.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitest/coverage-v8": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.5.tgz", + "integrity": "sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^1.0.2", + "@vitest/utils": "4.1.5", + "ast-v8-to-istanbul": "^1.0.0", + "istanbul-lib-coverage": "^3.2.2", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.2.0", + "magicast": "^0.5.2", + "obug": "^2.1.1", + "std-env": "^4.0.0-rc.1", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@vitest/browser": "4.1.5", + "vitest": "4.1.5" + }, + "peerDependenciesMeta": { + "@vitest/browser": { + "optional": true + } + } + }, + "node_modules/@vitest/expect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz", + "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz", + "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "4.1.5", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz", + "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz", + "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.5", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz", + "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.5", + "@vitest/utils": "4.1.5", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz", + "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz", + "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.5", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-v8-to-istanbul": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.0.tgz", + "integrity": "sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.31", + "estree-walker": "^3.0.3", + "js-tokens": "^10.0.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.3.tgz", + "integrity": "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.5.tgz", + "integrity": "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/es-module-lexer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", + "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.2.1.tgz", + "integrity": "sha512-wiyGaKsDgqXvF40P8mDwiUp/KQjE1FdrIEJsM8PZ3XCiniTMXS3OHWWUe5FI5agoCnr8x4xPrTDZuxsBlNHl+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.5.5", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz", + "integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", + "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magicast": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.2.tgz", + "integrity": "sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "source-map-js": "^1.2.1" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "18.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.2.tgz", + "integrity": "sha512-NsmlUYBS/Zg57rgDWMYdnre6OTj4e+qq/JS2ot3KrYLSoHLw+sDu0Nm1ZGpRgYAq6c+b1ekaY5NzVchMCQnzcg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/minimatch": { + "version": "10.2.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz", + "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "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", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.12", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.12.tgz", + "integrity": "sha512-W62t/Se6rA0Az3DfCL0AqJwXuKwBeYg6nOaIgzP+xZ7N5BFCI7DYi1qs6ygUYT6rvfi6t9k65UMLJC+PHZpDAA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-organize-imports": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.3.0.tgz", + "integrity": "sha512-FxFz0qFhyBsGdIsb697f/EkvHzi5SZOhWAjxcx2dLt+Q532bAlhswcXGYB1yzjZ69kW8UoadFBw7TyNwlq96Iw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "prettier": ">=2.0", + "typescript": ">=2.9", + "vue-tsc": "^2.1.0 || 3" + }, + "peerDependenciesMeta": { + "vue-tsc": { + "optional": true + } + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/rolldown": { + "version": "1.0.0-rc.17", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.17.tgz", + "integrity": "sha512-ZrT53oAKrtA4+YtBWPQbtPOxIbVDbxT0orcYERKd63VJTF13zPcgXTvD4843L8pcsI7M6MErt8QtON6lrB9tyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.127.0", + "@rolldown/pluginutils": "1.0.0-rc.17" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.0.0-rc.17", + "@rolldown/binding-darwin-arm64": "1.0.0-rc.17", + "@rolldown/binding-darwin-x64": "1.0.0-rc.17", + "@rolldown/binding-freebsd-x64": "1.0.0-rc.17", + "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.17", + "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.17", + "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.17", + "@rolldown/binding-linux-x64-musl": "1.0.0-rc.17", + "@rolldown/binding-openharmony-arm64": "1.0.0-rc.17", + "@rolldown/binding-wasm32-wasi": "1.0.0-rc.17", + "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.17", + "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.17" + } + }, + "node_modules/semver": { + "version": "7.7.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", + "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-git": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.36.0.tgz", + "integrity": "sha512-cGQjLjK8bxJw4QuYT7gxHw3/IouVESbhahSsHrX97MzCL1gu2u7oy38W6L2ZIGECEfIBG4BabsWDPjBxJENv9Q==", + "license": "MIT", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "@simple-git/args-pathspec": "^1.0.3", + "@simple-git/argv-parser": "^1.1.0", + "debug": "^4.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.0.0.tgz", + "integrity": "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinybench": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.0.1.tgz", + "integrity": "sha512-cMdWsxmysdg8mNWf1pujiWl3TW0cU6m8QuNw55QlnP3I6N96Grb0wnu5N0syHIu3LbiVZCNqlfWzWDq84HZphA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/tinyexec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz", + "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyrainbow": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", + "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.59.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.59.1.tgz", + "integrity": "sha512-xqDcFVBmlrltH64lklOVp1wYxgJr6LVdg3NamBgH2OOQDLFdTKfIZXF5PfghrnXQKXZGTQs8tr1vL7fJvq8CTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.59.1", + "@typescript-eslint/parser": "8.59.1", + "@typescript-eslint/typescript-estree": "8.59.1", + "@typescript-eslint/utils": "8.59.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "8.0.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.10.tgz", + "integrity": "sha512-rZuUu9j6J5uotLDs+cAA4O5H4K1SfPliUlQwqa6YEwSrWDZzP4rhm00oJR5snMewjxF5V/K3D4kctsUTsIU9Mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.4", + "postcss": "^8.5.10", + "rolldown": "1.0.0-rc.17", + "tinyglobby": "^0.2.16" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.1.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitest": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz", + "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "4.1.5", + "@vitest/mocker": "4.1.5", + "@vitest/pretty-format": "4.1.5", + "@vitest/runner": "4.1.5", + "@vitest/snapshot": "4.1.5", + "@vitest/spy": "4.1.5", + "@vitest/utils": "4.1.5", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.5", + "@vitest/browser-preview": "4.1.5", + "@vitest/browser-webdriverio": "4.1.5", + "@vitest/coverage-istanbul": "4.1.5", + "@vitest/coverage-v8": "4.1.5", + "@vitest/ui": "4.1.5", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.1.tgz", + "integrity": "sha512-a6ENMBBGZBsnlSebQ/eKCguSBeGKSf4O7BPnqVPmYGtpBYI7VSqoVqw+QcB7kPRjbqPwhYTpFbVj/RqNz/CT0Q==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/.github/shared/package.json b/.github/shared/package.json new file mode 100644 index 000000000000..df75018baf14 --- /dev/null +++ b/.github/shared/package.json @@ -0,0 +1,76 @@ +{ + "name": "@azure-tools/specs-shared", + "private": true, + "type": "module", + "exports": { + "./array": "./src/array.js", + "./breaking-change": "./src/breaking-change.js", + "./changed-files": "./src/changed-files.js", + "./console": "./src/console.js", + "./eslint-base-config": "./eslint.base.config.js", + "./exec": "./src/exec.js", + "./git": "./src/git.js", + "./github": "./src/github.js", + "./logger": "./src/logger.js", + "./math": "./src/math.js", + "./path": "./src/path.js", + "./readme": "./src/readme.js", + "./sdk-types": "./src/sdk-types.js", + "./set": "./src/set.js", + "./simple-git": "./src/simple-git.js", + "./sleep": "./src/sleep.js", + "./sort": "./src/sort.js", + "./spec-model-error": "./src/spec-model-error.js", + "./spec-model": "./src/spec-model.js", + "./swagger": "./src/swagger.js", + "./tag": "./src/tag.js", + "./time": "./src/time.js", + "./test/examples": "./test/examples.js" + }, + "bin": { + "spec-model": "./cmd/spec-model.js" + }, + "_comments": { + "dependencies": "Runtime dependencies must be kept to an absolute minimum for performance, ideally with no transitive dependencies", + "dependencies2": "All runtime and dev dependencies in this file, must be a subset of ../package.json" + }, + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^15.1.3", + "debug": "^4.4.3", + "js-yaml": "^4.1.0", + "marked": "^18.0.0", + "simple-git": "^3.36.0", + "zod": "^4.3.5" + }, + "devDependencies": { + "@eslint/js": "^10.0.0", + "@tsconfig/node20": "^20.1.4", + "@types/debug": "^4.1.12", + "@types/js-yaml": "^4.0.9", + "@types/node": "^20.0.0", + "@types/semver": "^7.7.1", + "@vitest/coverage-v8": "^4.1.0", + "cross-env": "^10.1.0", + "eslint": "^10.0.0", + "globals": "^17.0.0", + "prettier": "3.8.3", + "prettier-plugin-organize-imports": "^4.2.0", + "semver": "^7.7.1", + "tinybench": "^6.0.0", + "typescript": "~6.0.2", + "typescript-eslint": "^8.58.0", + "vitest": "^4.1.0" + }, + "scripts": { + "check": "npm run test:ci && npm run lint && npm run format:check", + "lint": "npm run lint:eslint && npm run lint:tsc", + "lint:eslint": "cross-env DEBUG=eslint:eslint,eslint:linter eslint", + "lint:tsc": "tsc --build --verbose", + "format": "prettier . --ignore-path ../.prettierignore --write", + "format:check": "prettier . --ignore-path ../.prettierignore --check", + "format:check:ci": "prettier . --ignore-path ../.prettierignore --check --log-level debug", + "perf": "node perf/perf.js", + "test": "vitest", + "test:ci": "vitest run --coverage --reporter=verbose" + } +} diff --git a/.github/shared/perf/perf.js b/.github/shared/perf/perf.js new file mode 100644 index 000000000000..70d6254eb998 --- /dev/null +++ b/.github/shared/perf/perf.js @@ -0,0 +1,19 @@ +import { resolve } from "path"; +import { Bench } from "tinybench"; +import { resolveCached } from "../src/path.js"; + +const bench = new Bench({ name: "github shared", time: 100 }); + +// ┌─────────┬───────────────────┬──────────────────┬──────────────────┬────────────────────────┬────────────────────────┬─────────┐ +// │ (index) │ Task name │ Latency avg (ns) │ Latency med (ns) │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │ +// ├─────────┼───────────────────┼──────────────────┼──────────────────┼────────────────────────┼────────────────────────┼─────────┤ +// │ 0 │ 'resolve()' │ '592.71 ± 1.66%' │ '500.00 ± 0.00' │ '1836985 ± 0.06%' │ '2000000 ± 0' │ 168717 │ +// │ 1 │ 'resolveCached()' │ '51.48 ± 0.79%' │ '0.00 ± 0.00' │ '14810488 ± 0.04%' │ '19423802 ± 0' │ 1942381 │ +// └─────────┴───────────────────┴──────────────────┴──────────────────┴────────────────────────┴────────────────────────┴─────────┘ + +bench.add("resolve()", () => resolve("bar")).add("resolveCached()", () => resolveCached("bar")); + +await bench.run(); + +console.log(bench.name); +console.table(bench.table()); diff --git a/.github/shared/readme.md b/.github/shared/readme.md new file mode 100644 index 000000000000..c9c013e847f4 --- /dev/null +++ b/.github/shared/readme.md @@ -0,0 +1,228 @@ +# `.github/shared` + +Shared JavaScript helper library (`@azure-tools/specs-shared`) used by tooling and GitHub Actions +across the `Azure/azure-rest-api-specs` repository. The code is plain ESM JavaScript annotated with +JSDoc, so it can be consumed from both JavaScript and TypeScript without a build step. + +This document has two audiences: + +- **[API reference](#api-reference)** — for _users_ of the shared code, a catalog of the APIs + exported from `src` so you can reuse existing helpers instead of reinventing the wheel. +- **[Folder structure & contributing](#folder-structure--contributing)** — for _developers_ of the + shared code, how the folder is organized and how to make changes. + +## API reference + +Each module is published as a subpath export in [`../package.json`](../package.json) (for example +`@azure-tools/specs-shared/array`). Import directly from the subpath, e.g.: + +```js +import { mapAsync } from "@azure-tools/specs-shared/array"; +``` + +> The list below is generated from the `export` statements under [`src`](./src). When in doubt, read +> the JSDoc on the function/class itself — it is the source of truth for parameters and return types. + +### `array` — async array helpers + +- `filterAsync(array, asyncPredicate)` — `Array.prototype.filter` with an async predicate. +- `flatMapAsync(array, asyncMapper)` — `Array.prototype.flatMap` with an async mapper. +- `mapAsync(array, asyncMapper)` — `Array.prototype.map` with an async mapper. +- `includesEvery(array, values)` — true if `array` includes every value in `values`. +- `includesNone(array, values)` — true if `array` includes none of the values in `values`. + +### `breaking-change` — breaking-change / versioning approval labels + +Single source of truth for breaking-change and versioning approval label names and helpers. + +- `VERSIONING_APPROVALS`, `BREAKING_CHANGE_APPROVALS`, `REVIEW_REQUIRED_LABELS` — label-name maps. +- `versioningApprovalValues`, `breakingChangeApprovalValues`, `reviewRequiredLabelValues` — value + arrays for the maps above. +- `isValidVersioningApproval(value)`, `isValidBreakingChangeApproval(value)`, + `isReviewRequiredLabel(value)` — label classification helpers. +- `breakingChangesCheckType`, `BREAKING_CHANGES_CHECK_TYPES` — breaking-change check type constants. + +### `cache` — in-memory caches + +- `KeyedCache` — cache keyed by a single value; `getOrCreate(key, factory)`. +- `KeyedPairCache` — cache keyed by a pair of values; `getOrCreate(key1, key2, factory)`. + +### `changed-files` — git changed files & path predicates + +- `getChangedFiles(options)` — list changed files (posix paths relative to repo root) between two + commitishes via `git diff`. +- `getChangedFilesStatuses(options)` — same as above, but grouped by change status + (added/modified/deleted/renamed). +- Path predicate filters (each takes a file path and returns a boolean): `json`, `markdown`, + `readme`, `dataPlane`, `resourceManager`, `preview`, `stable`, `example`, `typespec`, + `quickstartTemplate`, `swagger`, `scenario`. + +### `console` — console output + +- `log(...args)` — async wrapper around `console.log`. + +### `exec` — child-process execution + +- `isExecError(error)` — type guard for errors thrown by the exec helpers. +- `execFile(file, args, options)` — promisified `child_process.execFile`. +- `execNpm(args, options)` — run an `npm` command. +- `execNpmExec(args, options)` — run an `npm exec` command. + +### `git` — git helpers + +- `isFullGitSha(string)` — true if the string is a full 40-character git SHA. + +### `github` — GitHub API constants + +- `PER_PAGE_MAX` — maximum page size (100) for GitHub REST list APIs. +- `CheckStatus`, `CheckConclusion`, `CommitStatusState` — frozen enums mirroring GitHub check/commit + status values. + +### `logger` — logging + +- `ILogger` (JSDoc typedef) — the logger interface (`debug`/`error`/`info`/`warning`/`isDebug`). +- `ConsoleLogger` — `ILogger` implementation backed by the console. +- `defaultLogger` — shared non-debug logger instance. +- `debugLogger` — shared debug-enabled logger instance. + +### `math` — math helpers + +- `toPercent(value, decimals)` — format a `0..1` ratio as a percentage string. + +### `path` — path helpers (with caching) + +- `includesSegment(path, segment)` — true if the path contains the given path segment. +- `resolveCached(path)` — cached `path.resolve` (hot path; much faster than uncached `resolve`). +- `resolvePairCached(from, to)` — cached `path.resolve(from, to)`. +- `untilLastSegment(path, segment)` — substring up to the last occurrence of `segment`. +- `untilLastSegmentWithParent(path, segment)` — like above, including the parent of the segment. + +### `readme` — autorest readme model + +- `TagMatchRegex` — regex matching `$(tag) == "..."` conditions in a readme. +- `Readme` — model of an autorest `readme.md`: `getGlobalConfig()`, `getTags()`, `path`, + `specModel`, `toJSONAsync(options)`, `toString()`. + +### `sdk-types` — SDK language types & schemas + +- `SdkName` — frozen enum of SDK language identifiers (Go/Java/Js/Net/Python/Rust). +- `SdkNameSchema`, `APIViewRequestDataSchema`, `SpecGenSdkArtifactInfoSchema` — zod schemas (plus + inferred typedefs) for SDK tooling payloads. +- `sdkLabels` — per-language SDK label configuration. + +### `set` — set helpers + +- `equals(set1, set2)` — true if the two sets contain the same elements. +- `intersect(a, b)` — the intersection of two sets. + +### `simple-git` — git repo helpers + +- `getRootFolder(inputPath)` — resolve the git repository root for a path. + +### `sleep` — timers + +- `sleep(ms)` — promise that resolves after `ms` milliseconds. + +### `sort` — comparators + +- `byDate(getDate)` — comparator sorting by a date extracted from each element. +- `invert(comparator)` — reverse an existing comparator. + +### `spec-model` — spec folder model + +- `SpecModel` — model of a specification folder: `folder`, `getAffectedReadmeTags(swaggerPath)`, + `getAffectedSwaggers(swaggerPath)`, `getReadmes()`, `getSwaggers()`, `toJSONAsync(options)`, + `toString()`. +- `embedError(fn, options)` — wrap an async function so thrown errors are embedded in the result. + +### `spec-model-error` — errors + +- `SpecModelError` — `Error` subclass carrying `source`, `readme`, and `tag` context. + +### `swagger` — swagger document model + +- `Swagger` — model of a swagger/OpenAPI document: `getRefs()`, `getExamples()`, `getOperations()`, + `getTypeSpecGenerated()`, `path`, `tag`, `versionKind`, `toJSONAsync(options)`, `toString()`. +- `API_VERSION_LIFECYCLE_STAGES` — frozen enum of API-version lifecycle stages. + +### `tag` — autorest tag model + +- `Tag` — model of an autorest tag: `inputFiles`, `name`, `readme`, `toJSONAsync(options)`, + `toString()`. + +### `time` — time/duration helpers + +- `Duration` — frozen map of common durations in milliseconds. +- `add(date, ms)` / `subtract(date, ms)` — date arithmetic. +- `formatDuration(ms)` — human-readable duration string. +- `getDuration(from, to)` — milliseconds between two dates. + +## Folder structure & contributing + +``` +.github/shared +├── cmd/ # Executable CLI entry points (exposed via package.json "bin") +├── perf/ # Performance benchmarks (tinybench) +├── src/ # The shared library source (one module per file) +├── test/ # Vitest unit tests + fixtures and test helpers +├── tsconfig.json # Type-checking config (lint:tsc) +├── eslint.config.js # ESLint config (also re-exported as eslint-base-config) +└── vitest.config.js # Test + coverage config +``` + +### `src` + +The shared library. Each file is a focused module (see the [API reference](#api-reference)) and is +exposed to consumers through a subpath in [`../package.json`](../package.json)'s `exports`. See +[`src/README.md`](./src/README.md) for notes on consuming the code from TypeScript. + +Conventions: + +- Plain ESM JavaScript annotated with JSDoc — no separate `.ts` sources or build step. Types are + inferred from JSDoc, so keep annotations accurate. +- Runtime dependencies are kept to an absolute minimum (ideally zero transitive dependencies) for + performance, and must be declared in [`../package.json`](../package.json). + +### `test` + +[Vitest](https://vitest.dev/) unit tests. Each `src/.js` has a matching +`test/.test.js`. Supporting assets live alongside the tests: + +- `test/fixtures/` — sample specs/swaggers/readmes used by the tests. +- `test/examples.js` — shared example data (also exported publicly as + `@azure-tools/specs-shared/test/examples`). +- `test/repo.js`, `test/sdk-types.js` — local test helpers. + +### `perf` + +[`perf/perf.js`](./perf/perf.js) contains [tinybench](https://github.com/tinylibs/tinybench) +micro-benchmarks (for example comparing `resolve()` vs `resolveCached()`). Run with `npm run perf`. + +### `cmd` + +CLI entry points exposed via `package.json` `"bin"`. [`cmd/spec-model.js`](./cmd/spec-model.js) +backs `npx spec-model` for dumping a `SpecModel` to JSON. + +### Contributing + +When adding or changing shared code: + +1. **Add the module** under `src` as a single-responsibility file with JSDoc-annotated exports. +2. **Export it** by adding a subpath entry to the `exports` map in [`../package.json`](../package.json). +3. **Test it** by adding/updating `test/.test.js`; add fixtures under `test/fixtures` if + needed. +4. **Keep dependencies minimal** — avoid new runtime dependencies; any you add must already exist in + [`../package.json`](../package.json). +5. **Document new APIs** by updating the [API reference](#api-reference) above. + +Useful scripts (run from `.github`): + +| Command | Description | +| ---------------------- | -------------------------------------------------- | +| `npm test` | Run tests in watch mode (vitest). | +| `npm run test:ci` | Run tests once with coverage. | +| `npm run lint` | Run ESLint and `tsc` type-checking. | +| `npm run format` | Auto-format with prettier. | +| `npm run format:check` | Check formatting without writing. | +| `npm run perf` | Run performance benchmarks. | +| `npm run check` | Run tests, lint, and format check (the full gate). | diff --git a/.github/shared/src/README.md b/.github/shared/src/README.md new file mode 100644 index 000000000000..a551394b509b --- /dev/null +++ b/.github/shared/src/README.md @@ -0,0 +1,23 @@ +# .github/src + +## Overview + +Helper functions intended for use by any JavaScript, TypeScript, or other code (using a wrapper +that shells to nodejs) in this repo. + +## Calling from TypeScript + +You may need to enable `allowJs` in `tsconfig.json`: + +``` +{ + "compilerOptions": { + "allowJs": true + } +} +``` + +https://www.typescriptlang.org/tsconfig/#allowJs + +Another issue may be missing type definitions, but all shared code should be annotated with JSDoc +comments, which TypeScript should use to infer types. diff --git a/.github/shared/src/array.js b/.github/shared/src/array.js new file mode 100644 index 000000000000..8f911e2c0d95 --- /dev/null +++ b/.github/shared/src/array.js @@ -0,0 +1,55 @@ +/** + * @template T + * @param {T[]} array + * @param {(item: T, index: number, array: T[]) => Promise} asyncPredicate + * @returns {Promise} + */ +export async function filterAsync(array, asyncPredicate) { + const results = await mapAsync(array, asyncPredicate); + return array.filter((_, i) => results[i]); +} + +/** + * @template T,U + * @param {T[]} array + * @param {(item: T, index: number, array: T[]) => Promise} asyncMapper + * @returns {Promise} + */ +export async function flatMapAsync(array, asyncMapper) { + const mapped = await mapAsync(array, asyncMapper); + return mapped.flat(); +} + +/** + * Returns true if `array` includes no elements from `values` + * + * @template T,U + * @param {T[]} array + * @param {(item: T, index: number, array: T[]) => Promise} asyncMapper + * @returns {Promise} + */ +export async function mapAsync(array, asyncMapper) { + return Promise.all(array.map(asyncMapper)); +} + +/** + * Returns true if `array` includes every element from `values` + * + * @template T + * @param {T[]} array + * @param {T[]} values + * @returns {boolean} + */ +export function includesEvery(array, values) { + return values.every((value) => array.includes(value)); +} + +/** + * @template T + * @param {T[]} array + * @param {T[]} values + * @returns {boolean} + */ +export function includesNone(array, values) { + return values.every((value) => !array.includes(value)); +} diff --git a/.github/shared/src/breaking-change.js b/.github/shared/src/breaking-change.js new file mode 100644 index 000000000000..a6adae4435d0 --- /dev/null +++ b/.github/shared/src/breaking-change.js @@ -0,0 +1,81 @@ +/* v8 ignore start */ + +/** + * Breaking change configuration and constants for Azure REST API specs + * This file contains the single source of truth for all breaking change and versioning approval labels. + * + * Used across multiple tools in the Azure/azure-rest-api-specs repository. + */ + +// All versioning approval labels in one place +export const VERSIONING_APPROVALS = { + BENIGN: "Versioning-Approved-Benign", + BUG_FIX: "Versioning-Approved-BugFix", + PRIVATE_PREVIEW: "Versioning-Approved-PrivatePreview", + BRANCH_POLICY_EXCEPTION: "Versioning-Approved-BranchPolicyException", + PREVIOUSLY: "Versioning-Approved-Previously", + RETIRED: "Versioning-Approved-Retired", +}; + +// All breaking change approval labels in one place +export const BREAKING_CHANGE_APPROVALS = { + BENIGN: "BreakingChange-Approved-Benign", + BUG_FIX: "BreakingChange-Approved-BugFix", + USER_IMPACT: "BreakingChange-Approved-UserImpact", + BRANCH_POLICY_EXCEPTION: "BreakingChange-Approved-BranchPolicyException", + PREVIOUSLY: "BreakingChange-Approved-Previously", + SECURITY: "BreakingChange-Approved-Security", +}; + +// Review required labels +export const REVIEW_REQUIRED_LABELS = { + BREAKING_CHANGE: "BreakingChangeReviewRequired", + VERSIONING: "VersioningReviewRequired", +}; + +// Extract values as arrays for validation and configuration +export const versioningApprovalValues = Object.values(VERSIONING_APPROVALS); +export const breakingChangeApprovalValues = Object.values(BREAKING_CHANGE_APPROVALS); +export const reviewRequiredLabelValues = Object.values(REVIEW_REQUIRED_LABELS); + +// Type guard functions for runtime validation +/** + * @param {string} value + */ +export function isValidVersioningApproval(value) { + return versioningApprovalValues.includes(value); +} + +/** + * @param {string} value + */ +export function isValidBreakingChangeApproval(value) { + return breakingChangeApprovalValues.includes(value); +} + +/** + * @param {string} value + */ +export function isReviewRequiredLabel(value) { + return reviewRequiredLabelValues.includes(value); +} + +// Configuration for different check types +export const breakingChangesCheckType = { + SameVersion: { + reviewRequiredLabel: REVIEW_REQUIRED_LABELS.VERSIONING, + approvalPrefixLabel: "Versioning-Approved-*", + approvalLabels: versioningApprovalValues, + }, + CrossVersion: { + reviewRequiredLabel: REVIEW_REQUIRED_LABELS.BREAKING_CHANGE, + approvalPrefixLabel: "BreakingChange-Approved-*", + approvalLabels: breakingChangeApprovalValues, + }, +}; + +// Check types +export const BREAKING_CHANGES_CHECK_TYPES = { + SAME_VERSION: "SameVersion", + CROSS_VERSION: "CrossVersion", +}; diff --git a/.github/shared/src/cache.js b/.github/shared/src/cache.js new file mode 100644 index 000000000000..ec54ede7b399 --- /dev/null +++ b/.github/shared/src/cache.js @@ -0,0 +1,61 @@ +/** + * Caches values in memory with a single key of any type. + * + * @template K, V + */ +export class KeyedCache { + /** @type {Map} */ + #map = new Map(); + + /** + * Returns cached value, initializing if necessary + * + * @param {K} key + * @param {() => V} factory + * @returns {V} cached value + * + * @example + * const result = cache.getOrCreate(42, async () => await doWork(42)); + */ + getOrCreate(key, factory) { + let value = this.#map.get(key); + + if (value === undefined) { + value = factory(); + this.#map.set(key, value); + } + + return value; + } +} + +/** + * Caches values in memory with an ordered pair of keys of any types. + * + * @template K1, K2, V + */ +export class KeyedPairCache { + // Two-layer nested cache + /** @type {KeyedCache>} */ + #cache1 = new KeyedCache(); + + /** + * Returns cached value, initializing if necessary. + * Keys are ordered, so (key1, key2) != (key2, key1). + * + * @param {K1} key1 + * @param {K2} key2 + * @param {() => V} factory + * @returns {V} cached value + * + * @example + * const result = cache.getOrCreate(42, 7 async () => await doWork(42, 7)); + */ + getOrCreate(key1, key2, factory) { + // key1 => cache for the next layer + const cache2 = this.#cache1.getOrCreate(key1, () => new KeyedCache()); + + // key2 => final value + return cache2.getOrCreate(key2, factory); + } +} diff --git a/.github/shared/src/changed-files.js b/.github/shared/src/changed-files.js new file mode 100644 index 000000000000..f167e7056680 --- /dev/null +++ b/.github/shared/src/changed-files.js @@ -0,0 +1,313 @@ +import debug from "debug"; +import { simpleGit } from "simple-git"; +import { KeyedCache } from "./cache.js"; +import { includesSegment } from "./path.js"; + +// Enable simple-git debug logging to improve console output +debug.enable("simple-git"); + +// Cache results of the `example` filter, using the un-resolved path for maximum perf +// The `example` filter is a hot path in spec-model for large specs like "network". +/** @type {KeyedCache} */ +const exampleCache = new KeyedCache(); + +/** + * Get a list of changed files in a git repository + * + * @param {Object} [options] + * @param {string} [options.baseCommitish] Default: "HEAD^". + * @param {string} [options.cwd] Current working directory. Default: process.cwd(). + * @param {string[]} [options.gitOptions] Additional git options to pass to git diff command. Example: ["--no-renames"]. Default: [] + * @param {string} [options.headCommitish] Default: "HEAD". + * @param {import('./logger.js').ILogger} [options.logger] + * @param {string[]} [options.paths] Limits the diff to the named paths. If not set, includes all paths in repo. Default: [] + * @returns {Promise} List of changed files, using posix paths, relative to repo root. Example: ["specification/foo/Microsoft.Foo/main.tsp"]. + */ +export async function getChangedFiles(options = {}) { + const { + baseCommitish = "HEAD^", + cwd, + gitOptions = [], + headCommitish = "HEAD", + logger, + paths = [], + } = options; + + if (paths.length > 0) { + // Use "--" to separate paths from revisions + paths.unshift("--"); + } + + // TODO: If we need to filter based on status, instead of passing an argument to `--diff-filter, + // consider using "--name-status" instead of "--name-only", and return an array of objects like + // { name: "/foo/baz.js", status: Status.Renamed, previousName: "/foo/bar.js"}. + // Then add filter functions to filter based on status. This is more flexible and lets consumers + // filter based on status with a single call to `git diff`. + const result = await simpleGit(cwd).diff([ + "--name-only", + ...gitOptions, + baseCommitish, + headCommitish, + ...paths, + ]); + + const files = result + .trim() + .split("\n") + // ignore empty lines (e.g. when no files are changed) + .filter((s) => s.length > 0); + logger?.info("Changed Files:"); + for (const file of files) { + logger?.info(` ${file}`); + } + logger?.info(""); + + return files; +} + +/** + * Get a list of changed files in a git repository with statuses for additions, + * modifications, deletions, and renames. Warning: rename behavior can vary + * based on the git client's configuration of diff.renames. + * + * @param {Object} [options] + * @param {string} [options.baseCommitish] Default: "HEAD^". + * @param {string} [options.cwd] Current working directory. Default: process.cwd(). + * @param {string[]} [options.gitOptions] Additional git options to pass to git diff command. Example: ["--no-renames"]. Default: [] + * @param {string} [options.headCommitish] Default: "HEAD". + * @param {import('./logger.js').ILogger} [options.logger] + * @param {string[]} [options.paths] Limits the diff to the named paths. If not set, includes all paths in repo. Default: [] + * @returns {Promise<{additions: string[], modifications: string[], deletions: string[], renames: {from: string, to: string}[], total: number}>} + */ +export async function getChangedFilesStatuses(options = {}) { + const { + baseCommitish = "HEAD^", + cwd, + gitOptions = [], + headCommitish = "HEAD", + logger, + paths = [], + } = options; + + if (paths.length > 0) { + // Use "--" to separate paths from revisions + paths.unshift("--"); + } + + const result = await simpleGit(cwd).diff([ + "--name-status", + ...gitOptions, + baseCommitish, + headCommitish, + ...paths, + ]); + + const categorizedFiles = { + additions: /** @type {string[]} */ ([]), + modifications: /** @type {string[]} */ ([]), + deletions: /** @type {string[]} */ ([]), + renames: /** @type {{from: string, to: string}[]} */ ([]), + total: 0, + }; + + if (result.trim()) { + const lines = result.trim().split("\n"); + + for (const line of lines) { + const parts = line.split("\t"); + const status = parts[0]; + + switch (status[0]) { + case "A": + categorizedFiles.additions.push(parts[1]); + break; + case "M": + categorizedFiles.modifications.push(parts[1]); + break; + case "D": + categorizedFiles.deletions.push(parts[1]); + break; + case "R": + categorizedFiles.renames.push({ + from: parts[1], + to: parts[2], + }); + break; + case "C": + categorizedFiles.additions.push(parts[2]); + break; + default: + categorizedFiles.modifications.push(parts[1]); + } + } + + categorizedFiles.total = + categorizedFiles.additions.length + + categorizedFiles.modifications.length + + categorizedFiles.deletions.length + + categorizedFiles.renames.length; + } + + // Log all changed files by categories + if (logger) { + logger.info("Categorized Changed Files:"); + + if (categorizedFiles.additions.length > 0) { + logger.info(` Additions (${categorizedFiles.additions.length}):`); + for (const file of categorizedFiles.additions) { + logger.info(` + ${file}`); + } + } + + if (categorizedFiles.modifications.length > 0) { + logger.info(` Modifications (${categorizedFiles.modifications.length}):`); + for (const file of categorizedFiles.modifications) { + logger.info(` M ${file}`); + } + } + + if (categorizedFiles.deletions.length > 0) { + logger.info(` Deletions (${categorizedFiles.deletions.length}):`); + for (const file of categorizedFiles.deletions) { + logger.info(` - ${file}`); + } + } + + if (categorizedFiles.renames.length > 0) { + logger.info(` Renames (${categorizedFiles.renames.length}):`); + for (const rename of categorizedFiles.renames) { + logger.info(` R ${rename.from} -> ${rename.to}`); + } + } + + logger.info(` Total: ${categorizedFiles.total} files`); + logger.info(""); + } + + return categorizedFiles; +} + +// Functions suitable for passing to string[].filter(), ordered roughly in order of increasing specificity +// Functions accept both relative and absolute paths, since paths are resolve()'d before searching (when needed) + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function json(file) { + // Extension "json" with any case is a valid JSON file + return typeof file === "string" && file.toLowerCase().endsWith(".json"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function markdown(file) { + // Extension ".md" with any case is a valid markdown file + return typeof file === "string" && file.toLowerCase().endsWith(".md"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function readme(file) { + // Filename "readme.md" with any case is a valid README file + return typeof file === "string" && file.toLowerCase().endsWith("readme.md"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function dataPlane(file) { + // Folder name "data-plane" should match case for consistency across specs + return typeof file === "string" && includesSegment(file, "data-plane"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function resourceManager(file) { + // Folder name "resource-manager" should match case for consistency across specs + return typeof file === "string" && includesSegment(file, "resource-manager"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function preview(file) { + // Folder name "preview" should match case for consistency across specs + return typeof file === "string" && includesSegment(file, "preview"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function stable(file) { + // Folder name "stable" should match case for consistency across specs + return typeof file === "string" && includesSegment(file, "stable"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function example(file) { + return ( + typeof file === "string" && + // Intentionally use un-resolved path as key for perf, since we are OK + // caching the same result for different representations of the same path. + exampleCache.getOrCreate( + file, + // Folder name "examples" should match case for consistency across specs + () => json(file) && includesSegment(file, "examples"), + ) + ); +} + +/** + * @param {string} file + * @returns {boolean} + */ +export function typespec(file) { + return ( + typeof file === "string" && + (file.toLowerCase().endsWith(".tsp") || file.toLowerCase().endsWith("tspconfig.yaml")) + ); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function quickstartTemplate(file) { + return typeof file === "string" && json(file) && file.includes("/quickstart-templates/"); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function swagger(file) { + return ( + typeof file === "string" && + json(file) && + (dataPlane(file) || resourceManager(file)) && + !example(file) && + !quickstartTemplate(file) && + !scenario(file) + ); +} + +/** + * @param {string} [file] + * @returns {boolean} + */ +export function scenario(file) { + return typeof file === "string" && json(file) && includesSegment(file, "scenarios"); +} diff --git a/.github/shared/src/console.js b/.github/shared/src/console.js new file mode 100644 index 000000000000..a1a72f33e4c4 --- /dev/null +++ b/.github/shared/src/console.js @@ -0,0 +1,48 @@ +import { once } from "node:events"; +import { format } from "node:util"; + +/** + * Async, backpressure-aware console.log() replacement. console.log() can silently drop messages under backpressure. + * + * Use when you need to log a lot of text, and the console reader may be applying backpressure. + * + * Examples: `node app.js | tee out.txt`, GitHub Actions console log reader + * + * @type {(...args: Parameters) => Promise} + */ +export async function log(...args) { + const line = format(...args) + "\n"; + + if (!process.stdout.write(line)) { + await once(process.stdout, "drain"); + } +} + +// ## Future Improvement +// +// The log() function currently handles backpressure per call, but concurrent callers +// can still invoke `process.stdout.write()` before a prior `drain` completes +// (eg callers using Promise.all()). If we ever need strict global backpressure control, +// add a shared write queue (promise chain/mutex) to serialize all writes across calls. +// +// /** @type {Promise} */ +// let writeQueue = Promise.resolve(); +// +// /** +// * Async, backpressure-aware console.log replacement. +// * +// * @type {(...args: Parameters) => Promise} +// */ +// export function log(...args) { +// const line = format(...args) + "\n"; +// +// const writeOnce = async () => { +// if (!process.stdout.write(line)) { +// await once(process.stdout, "drain"); +// } +// }; +// +// const next = writeQueue.then(writeOnce, writeOnce); +// writeQueue = next.catch(() => {}); +// return next; +// } diff --git a/.github/shared/src/exec.js b/.github/shared/src/exec.js new file mode 100644 index 000000000000..aba68ea0cf25 --- /dev/null +++ b/.github/shared/src/exec.js @@ -0,0 +1,134 @@ +import child_process from "child_process"; +import { dirname, join } from "path"; +import { promisify } from "util"; +const execFileImpl = promisify(child_process.execFile); + +/** + * @typedef {Object} ExecOptions + * @property {string} [cwd] Current working directory. Default: process.cwd(). + * @property {import('./logger.js').ILogger} [logger] + * @property {number} [maxBuffer] Max bytes allowed on stdout or stderr. Default: 16 * 1024 * 1024. + */ + +/** + * @typedef {Object} NpmPrefixOptions + * @property {string} [prefix] Prefix to pass to npm via "--prefix". + */ + +/** + * @typedef {ExecOptions & NpmPrefixOptions} ExecNpmOptions + */ + +/** + * @typedef {Object} ExecResult + * @property {string} stdout + * @property {string} stderr + */ + +/** + * @typedef {Error & { stdout?: string, stderr?: string, code?: number }} ExecError + */ + +/** + * Checks whether an unknown error object is an ExecError. + * @param {unknown} error + * @returns {error is ExecError} + */ +export function isExecError(error) { + if (!(error instanceof Error)) return false; + + const e = /** @type {ExecError} */ (error); + return typeof e.stdout === "string" || typeof e.stderr === "string"; +} + +/** + * Wraps `child_process.execFile()`, adding logging and a larger default maxBuffer. + * + * @param {string} file + * @param {string[]} [args] + * @param {ExecOptions} [options] + * @returns {Promise} + * @throws {ExecError} + */ +export async function execFile(file, args, options = {}) { + const { + cwd, + logger, + // Node default is 1024 * 1024, which is too small for some git commands returning many entities or large file content. + // To support "git show", should be larger than the largest swagger file in the repo (2.5 MB as of 2/28/2025). + maxBuffer = 16 * 1024 * 1024, + } = options; + + logger?.info(`execFile("${file}", ${JSON.stringify(args)})`); + + try { + // execFile(file, args) is more secure than exec(cmd), since the latter is vulnerable to shell injection + const result = await execFileImpl(file, args, { + cwd, + maxBuffer, + }); + + logger?.debug(`stdout: '${result.stdout}'`); + logger?.debug(`stderr: '${result.stderr}'`); + + return result; + } catch (error) { + /* v8 ignore next */ + logger?.debug(`error: '${JSON.stringify(error)}'`); + + throw error; + } +} + +/** + * Calls `execFile()` with appropriate arguments to run `npm` on all platforms + * + * @param {string[]} args + * @param {ExecNpmOptions} [options] + * @returns {Promise} + * @throws {ExecError} + */ +export async function execNpm(args, options = {}) { + const { prefix } = options; + + // Exclude platform-specific code from coverage + /* v8 ignore start */ + const { file, defaultArgs } = + process.platform === "win32" + ? { + // Only way I could find to run "npm" on Windows, without using the shell (e.g. "cmd /c npm ...") + // + // "node.exe", ["--", "npm-cli.js", ...args] + // + // The "--" MUST come BEFORE "npm-cli.js", to ensure args are sent to the script unchanged. + // If the "--" comes after "npm-cli.js", the args sent to the script will be ["--", ...args], + // which is NOT equivalent, and can break if args itself contains another "--". + + // example: "C:\Program Files\nodejs\node.exe" + file: process.execPath, + + // example: "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" + defaultArgs: [ + "--", + join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js"), + ], + } + : { file: "npm", defaultArgs: [] }; + /* v8 ignore stop */ + + const prefixArgs = prefix ? ["--prefix", prefix] : []; + + return await execFile(file, [...defaultArgs, ...prefixArgs, ...args], options); +} + +/** + * Calls `execNpm()` with arguments ["exec", "--no", "--"] prepended. + * + * @param {string[]} args + * @param {ExecNpmOptions} [options] + * @returns {Promise} + * @throws {ExecError} + */ +export async function execNpmExec(args, options = {}) { + return await execNpm(["exec", "--no", "--", ...args], options); +} diff --git a/.github/shared/src/git.js b/.github/shared/src/git.js new file mode 100644 index 000000000000..ad712085efa2 --- /dev/null +++ b/.github/shared/src/git.js @@ -0,0 +1,9 @@ +/** + * Returns true if a string is a possible full git SHA (40 hex chars, case insensitive) + * + * @param {string} string + * @returns {boolean} + */ +export function isFullGitSha(string) { + return /^[0-9a-f]{40}$/i.test(string); +} diff --git a/.github/shared/src/github.js b/.github/shared/src/github.js new file mode 100644 index 000000000000..501a512810da --- /dev/null +++ b/.github/shared/src/github.js @@ -0,0 +1,102 @@ +/* v8 ignore start */ + +export const PER_PAGE_MAX = 100; + +/** + * https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks#check-statuses-and-conclusions + * + * @readonly + * @enum {"completed" | "expected" | "failure" | "in_progress" | "pending" | "queued" | "requested" | "startup_failure" | "waiting" } + */ +export const CheckStatus = Object.freeze({ + /** + * @description The check run completed and has a conclusion. + */ + COMPLETED: "completed", + /** + * @description The check run is waiting for a status to be reported. + */ + EXPECTED: "expected", + /** + * @description The check run failed. + */ + FAILURE: "failure", + /** + * @description The check run is in progress. + */ + IN_PROGRESS: "in_progress", + /** + * @description The check run is at the front of the queue but the group-based concurrency limit has been reached. + */ + PENDING: "pending", + /** + * @description The check run has been queued. + */ + QUEUED: "queued", + /** + * @description The check run has been created but has not been queued. + */ + REQUESTED: "requested", + /** + * @description The check suite failed during startup. This status is not applicable to check runs. + */ + STARTUP_FAILURE: "startup_failure", + /** + * @description The check run is waiting for a deployment protection rule to be satisfied. + */ + WAITING: "waiting", +}); + +/** + * https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks#check-statuses-and-conclusions + * + * @readonly + * @enum {"action_required" | "cancelled" | "failure" | "neutral" | "skipped" | "stale" | "success" | "timed_out" } + */ +export const CheckConclusion = Object.freeze({ + /** + * @description The check run provided required actions upon its completion. For more information, see Using the REST API to interact with checks. + */ + ACTION_REQUIRED: "action_required", + /** + * @description The check run was cancelled before it completed. + */ + CANCELLED: "cancelled", + /** + * @description The check run failed. + */ + FAILURE: "failure", + /** + * @description The check run completed with a neutral result. This is treated as a success for dependent checks in GitHub Actions. + */ + NEUTRAL: "neutral", + /** + * @description The check run was skipped. This is treated as a success for dependent checks in GitHub Actions. + */ + SKIPPED: "skipped", + /** + * @description The check run was marked stale by GitHub because it took too long. + */ + STALE: "stale", + /** + * @description The check run completed successfully. + */ + SUCCESS: "success", + /** + * @description The check run timed out. + */ + TIMED_OUT: "timed_out", +}); + +/** + * https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#create-a-commit-status--parameters + * + * @readonly + * @enum {"error" | "failure" | "pending" | "success"} + */ +export const CommitStatusState = Object.freeze({ + ERROR: "error", + FAILURE: "failure", + PENDING: "pending", + SUCCESS: "success", +}); diff --git a/.github/shared/src/logger.js b/.github/shared/src/logger.js new file mode 100644 index 000000000000..dc43a06d9782 --- /dev/null +++ b/.github/shared/src/logger.js @@ -0,0 +1,64 @@ +/** + * @typedef {Object} ILogger + * @property {(message:string) => void} debug + * @property {(message:string) => void} error + * @property {(message:string) => void} info + * @property {(message:string) => void} warning + * @property {() => boolean} isDebug + */ + +/** + * @implements {ILogger} + */ +export class ConsoleLogger { + /** @type {boolean} */ + #isDebug; + + /** + * @param {boolean} [isDebug] - If true, debug logs will be printed. Default: false. + */ + constructor(isDebug = false) { + this.#isDebug = isDebug; + } + + /** + * @param {string} message + */ + debug(message) { + if (this.isDebug()) { + console.debug(message); + } + } + + /** + * @param {string} message + */ + error(message) { + console.error(message); + } + + /** + * @param {string} message + */ + info(message) { + console.log(message); + } + + /** + * @returns {boolean} + */ + isDebug() { + return this.#isDebug; + } + + /** + * @param {string} message + */ + warning(message) { + console.warn(message); + } +} + +// Singleton loggers +export const defaultLogger = new ConsoleLogger(); +export const debugLogger = new ConsoleLogger(/*isDebug*/ true); diff --git a/.github/shared/src/math.js b/.github/shared/src/math.js new file mode 100644 index 000000000000..69c2784130d3 --- /dev/null +++ b/.github/shared/src/math.js @@ -0,0 +1,10 @@ +/** + * Convert a float [0,1] to a percentage string. + * + * @param {number} value - A number between 0 and 1. + * @param {number} [decimals=0] - How many decimal places to include. Default: 0 + * @returns {string} + */ +export function toPercent(value, decimals = 0) { + return `${(value * 100).toFixed(decimals)}%`; +} diff --git a/.github/shared/src/path.js b/.github/shared/src/path.js new file mode 100644 index 000000000000..929116c931b6 --- /dev/null +++ b/.github/shared/src/path.js @@ -0,0 +1,104 @@ +import { basename, dirname, resolve } from "path"; + +import { KeyedCache, KeyedPairCache } from "./cache.js"; + +/** @type {KeyedCache} */ +const resolveCache = new KeyedCache(); + +/** @type {KeyedPairCache} */ +const resolvePairCache = new KeyedPairCache(); + +/** + * + * @param {string} path Absolute or relative path + * @param {string} segment File or folder + * @returns {boolean} True if resolved path contains segment + * + * @example + * includesSegment("stable/2025-01-01/examples/foo.json", "examples") + * // -> true + */ +export function includesSegment(path, segment) { + return untilLastSegment(path, segment) !== ""; +} + +/** + * Wraps `path.resolve(path)` with a cache to improve performance + * + * @param {string} path + * @returns {string} + */ +export function resolveCached(path) { + return resolveCache.getOrCreate(path, () => resolve(path)); +} + +/** + * Wraps `path.resolve(from, to)` with a cache to improve performance + +* @param {string} from + * @param {string} to + * @returns {string} + */ +export function resolvePairCached(from, to) { + return resolvePairCache.getOrCreate(from, to, () => resolve(from, to)); +} + +/** + * @param {string} path Absolute or relative path + * @param {string} segment File or folder + * @returns {string} Portion of resolved path up to (and including) the last occurrence of segment + * + * @example + * untilLastSegment("stable/2025-01-01/examples/foo.json", "examples") + * // -> "{cwd}/stable/2025-01-01/examples" + */ +export function untilLastSegment(path, segment) { + // Shares code with `untilLastSegmentWithParent()`, but not worth refactoring yet + + let current = resolveCached(path); + + while (true) { + const parent = dirname(current); + + if (basename(current) === segment) { + // Found the target folder. Return it. + return current; + } else if (parent === current) { + // Reached the filesystem root (folder not found). Return empty string. + return ""; + } else { + // Keep walking upward + current = parent; + } + } +} + +/** + * @param {string} path Absolute or relative path + * @param {string} segment File or folder + * @returns {string} Portion of resolved path up to (and including) the last segment with the specified parent + * + * @example + * untilLastSegmentWithParent("specification/foo/data-plane/stable/2025-01-01/foo.json", "specification") + * // -> "{cwd}/specification/foo" + */ +export function untilLastSegmentWithParent(path, segment) { + // Shares code with `untilLastSegment()`, but not worth refactoring yet + + let current = resolveCached(path); + + while (true) { + const parent = dirname(current); + + if (basename(parent) === segment) { + // Found the target parent. Return current; + return current; + } else if (parent === current) { + // Reached the filesystem root (folder not found). Return empty string. + return ""; + } else { + // Keep walking upward + current = parent; + } + } +} diff --git a/.github/shared/src/readme.js b/.github/shared/src/readme.js new file mode 100644 index 000000000000..01e4614e18ca --- /dev/null +++ b/.github/shared/src/readme.js @@ -0,0 +1,281 @@ +import { readFile } from "fs/promises"; +import yaml from "js-yaml"; +import { marked } from "marked"; +import { dirname, normalize, relative } from "path"; +import { inspect } from "util"; +import * as z from "zod"; +import { mapAsync } from "./array.js"; +import { resolvePairCached } from "./path.js"; +import { SpecModelError } from "./spec-model-error.js"; +import { embedError } from "./spec-model.js"; +import { Tag } from "./tag.js"; + +/** + * @typedef {import('./spec-model.js').ErrorJSON} ErrorJSON + * @typedef {import('./spec-model.js').SpecModel} SpecModel + * @typedef {import('./spec-model.js').ToJSONOptions} ToJSONOptions + * @typedef {import('./tag.js').TagJSON} TagJSON + */ + +/** + * @typedef {Object} ReadmeJSON + * @property {string} path + * @property {Object} globalConfig + * @property {(TagJSON|ErrorJSON)[]} tags + */ + +/** + * Regex to match tag names in readme.md yaml code blocks + */ +export const TagMatchRegex = /yaml.*\$\(tag\) ?== ?(["'])(.*?)\1/; + +// Example: "foo.json" +const jsonFileSchema = z.string().regex(/\.json$/i); + +// Examples: +// {} +// {"input-file": "foo.json"} +// {"input-file": ["foo.json", "bar.json"]} +const inputFileSchema = z.object({ + "input-file": z + // May be undefined, a single json filename, or an array of json filenames + .optional(z.union([jsonFileSchema, z.array(jsonFileSchema)])) + // Normalize single string to array of string. Don't change 'undefined'. + .transform((value) => (typeof value === "string" ? [value] : value)), +}); + +export class Readme { + /** + * Content of `readme.md`, either loaded from `#path` or passed in via `options`. + * + * Reset to `undefined` after `#data` is loaded to save memory. + * + * @type {string | undefined} + */ + #content; + + /** @type {{globalConfig: Record, tags: Map} | undefined} */ + #data; + + /** @type {import('./logger.js').ILogger | undefined} */ + #logger; + + /** + * absolute path + * @type {string} + * */ + #path; + + /** + * SpecModel that contains this Readme + * @type {SpecModel | undefined} + */ + #specModel; + + /** + * @param {string} path Used for content, unless options.content is specified + * @param {Object} [options] + * @param {string} [options.content] If specified, is used instead of reading path from disk + * @param {import('./logger.js').ILogger} [options.logger] + * @param {SpecModel} [options.specModel] + */ + constructor(path, options = {}) { + const { content, logger, specModel } = options; + + this.#path = resolvePairCached(specModel?.folder ?? "", path); + + this.#content = content; + this.#logger = logger; + this.#specModel = specModel; + } + + /** + * @param {string} swaggerPath + * @param {import('./logger.js').ILogger} [logger] + * @returns {string} + */ + static #normalizeSwaggerPath(swaggerPath, logger) { + let swaggerPathNormalized = swaggerPath; + // Ignore uses of "$(this-folder)" in the swagger path. It refers to the + // current folder anyway and can be substituted with "." + if (swaggerPath.includes("$(this-folder)")) { + swaggerPathNormalized = swaggerPath.replaceAll("$(this-folder)", "."); + } + + // Some swagger paths contain backslashes. These should be normalized when + // encountered though the expected format for input-files is forward slashes. + if (swaggerPathNormalized.includes("\\")) { + /* v8 ignore next */ + logger?.info( + `Found backslash (\\) in swagger path ${swaggerPath}. Replacing with forward slash (/)`, + ); + + swaggerPathNormalized = swaggerPathNormalized.replaceAll("\\", "/"); + } + + return normalize(swaggerPathNormalized); + } + + async #getData() { + if (!this.#data) { + // Only read file if #content is exactly undefined, to allow setting #content to empty string + // to simulate an empty file + if (this.#content === undefined) { + this.#content = await readFile(this.#path, { + encoding: "utf8", + }); + } + + const tokens = marked.lexer(this.#content); + + /** @type import("marked").Tokens.Code[] */ + const yamlBlocks = tokens + .filter((token) => token.type === "code") + .map((token) => /** @type import("marked").Tokens.Code */ (token)) + // Include default block and tagged blocks (```yaml $(tag) == 'package-2021-11-01') + .filter((token) => token.lang?.toLowerCase().startsWith("yaml")); + + const globalConfigYamlBlocks = yamlBlocks.filter((token) => token.lang === "yaml"); + + const globalConfig = globalConfigYamlBlocks.reduce( + (obj, token) => Object.assign(obj, yaml.load(token.text, { schema: yaml.FAILSAFE_SCHEMA })), + {}, + ); + + /** @type {Map} */ + const tags = new Map(); + for (const block of yamlBlocks) { + const tagName = block.lang?.match(TagMatchRegex)?.[2] || "default"; + + if (tagName === "default" || tagName === "all-api-versions") { + // Skip yaml blocks where this is no tag or tag is all-api-versions + continue; + } + + const obj = /** @type {any} */ (yaml.load(block.text, { schema: yaml.FAILSAFE_SCHEMA })); + + if (!obj) { + this.#logger?.debug(`No YAML object found for tag ${tagName} in ${this.#path}`); + continue; + } + + let parsedObj; + try { + parsedObj = inputFileSchema.parse(obj); + } catch (error) { + /* v8 ignore else -- defensive rethrow */ + if (error instanceof z.ZodError) { + throw new SpecModelError( + `Unable to parse input-file YAML for tag ${tagName} in ${this.#path}`, + { + source: this.#path, + readme: this.#path, + tag: tagName, + cause: error, + }, + ); + } else { + throw error; + } + } + + if (!parsedObj["input-file"]) { + // The yaml block does not contain an input-file key + continue; + } + + // This heuristic assumes that a previous definition of the tag with no + // swaggers means that the previous definition did not have an input-file + // key. It's possible that the previous defintion had an `input-file: []` + // or something like it. + const existingTag = tags.get(tagName); + if ((existingTag?.inputFiles?.size ?? 0) > 0) { + // The tag already exists and has a swagger file. This is an error as + // there should only be one definition of input-files per tag. + const message = `Multiple input-file definitions for tag ${tagName} in ${this.#path}`; + this.#logger?.error(message); + throw new Error(message); + } + + const inputFilePaths = parsedObj["input-file"]; + + const swaggerPathsResolved = inputFilePaths + .map((p) => Readme.#normalizeSwaggerPath(p)) + .map((p) => resolvePairCached(dirname(this.#path), p)); + + const tag = new Tag(tagName, swaggerPathsResolved, { + logger: this.#logger, + readme: this, + }); + + tags.set(tag.name, tag); + } + + this.#data = { globalConfig, tags }; + + // Clear #content to save memory, since it's no longer needed after #data is loaded + this.#content = undefined; + } + + return this.#data; + } + + /** + * @returns {Promise>} + */ + async getGlobalConfig() { + return (await this.#getData()).globalConfig; + } + + /** + * @returns {Promise>} + */ + async getTags() { + return (await this.#getData()).tags; + } + + /** + * @returns {string} absolute path + */ + get path() { + return this.#path; + } + + /** + * @returns {SpecModel | undefined} SpecModel that contains this Readme + */ + get specModel() { + return this.#specModel; + } + + /** + * @param {ToJSONOptions} [options] + * @returns {Promise} + */ + async toJSONAsync(options = {}) { + const { relativePaths } = options; + + return await embedError(async () => { + const tags = await mapAsync( + [...(await this.getTags()).values()].sort((a, b) => a.name.localeCompare(b.name)), + async (t) => await t.toJSONAsync(options), + ); + + return { + path: + relativePaths && this.#specModel + ? relative(this.#specModel.folder, this.#path) + : this.#path, + globalConfig: await this.getGlobalConfig(), + tags, + }; + }, options); + } + + /** + * @returns {string} + */ + toString() { + return `Readme(${this.#path}, {logger: ${inspect(this.#logger)}})`; + } +} diff --git a/.github/shared/src/sdk-types.js b/.github/shared/src/sdk-types.js new file mode 100644 index 000000000000..4ec5955b03cf --- /dev/null +++ b/.github/shared/src/sdk-types.js @@ -0,0 +1,98 @@ +import * as z from "zod"; + +/** + * Represents supported SDK language identifiers. + * + * @readonly + * @enum {"azure-sdk-for-go" | "azure-sdk-for-java" | "azure-sdk-for-js" | "azure-sdk-for-net" | "azure-sdk-for-python" | "azure-sdk-for-rust"} + */ +export const SdkName = Object.freeze({ + Go: "azure-sdk-for-go", + Java: "azure-sdk-for-java", + Js: "azure-sdk-for-js", + Net: "azure-sdk-for-net", + Python: "azure-sdk-for-python", + Rust: "azure-sdk-for-rust", +}); +/** @type {import("zod").ZodType} */ +export const SdkNameSchema = z.enum(Object.values(SdkName)); + +/* + * Data for the API view request. + */ +export const APIViewRequestDataSchema = z.object({ packageName: z.string(), filePath: z.string() }); +/** + * @typedef {import("zod").infer} APIViewRequestData + */ + +/** + * Represents the result of the spec-gen-sdk generation process. + */ +export const SpecGenSdkArtifactInfoSchema = z.object({ + language: SdkNameSchema, + result: z.string(), + headSha: z.string(), + prNumber: z.string().optional(), + labelAction: z.boolean().optional(), + isSpecGenSdkCheckRequired: z.boolean(), + apiViewRequestData: z.array(APIViewRequestDataSchema), +}); +/** + * @typedef {import("zod").infer} SpecGenSdkArtifactInfo + */ + +/** + * @typedef {{ + * breakingChange: string | undefined, + * breakingChangeApproved: string | undefined, + * breakingChangeSuppression: string | undefined, + * breakingChangeSuppressionApproved: string | undefined + * }} SdkLabelInfo + */ + +/** + * @typedef {Record} SdkLabels + */ + +/** + * SDK labels mapping for breaking change labels + * @type {SdkLabels} + * */ +export const sdkLabels = { + "azure-sdk-for-go": { + breakingChange: "BreakingChange-Go-Sdk", + breakingChangeApproved: "BreakingChange-Go-Sdk-Approved", + breakingChangeSuppression: "BreakingChange-Go-Sdk-Suppression", + breakingChangeSuppressionApproved: "BreakingChange-Go-Sdk-Suppression-Approved", + }, + "azure-sdk-for-java": { + breakingChange: undefined, + breakingChangeApproved: undefined, + breakingChangeSuppression: undefined, + breakingChangeSuppressionApproved: undefined, + }, + "azure-sdk-for-js": { + breakingChange: "BreakingChange-JavaScript-Sdk", + breakingChangeApproved: "BreakingChange-JavaScript-Sdk-Approved", + breakingChangeSuppression: "BreakingChange-JavaScript-Sdk-Suppression", + breakingChangeSuppressionApproved: "BreakingChange-JavaScript-Sdk-Suppression-Approved", + }, + "azure-sdk-for-net": { + breakingChange: undefined, + breakingChangeApproved: undefined, + breakingChangeSuppression: undefined, + breakingChangeSuppressionApproved: undefined, + }, + "azure-sdk-for-python": { + breakingChange: "BreakingChange-Python-Sdk", + breakingChangeApproved: "BreakingChange-Python-Sdk-Approved", + breakingChangeSuppression: "BreakingChange-Python-Sdk-Suppression", + breakingChangeSuppressionApproved: "BreakingChange-Python-Sdk-Suppression-Approved", + }, + "azure-sdk-for-rust": { + breakingChange: undefined, + breakingChangeApproved: undefined, + breakingChangeSuppression: undefined, + breakingChangeSuppressionApproved: undefined, + }, +}; diff --git a/.github/shared/src/set.js b/.github/shared/src/set.js new file mode 100644 index 000000000000..9595693c1f50 --- /dev/null +++ b/.github/shared/src/set.js @@ -0,0 +1,36 @@ +/** + * @param {Set} set1 + * @param {Set} set2 + * @returns {boolean} True if sets are the same size and have the same elements + */ +export function equals(set1, set2) { + if (!(set1 instanceof Set) || !(set2 instanceof Set)) { + return false; + } + + if (set1.size !== set2.size) { + return false; + } + + // Should be O(N), since set lookup should be O(1) + // Sets are same size, so iterating over either set has the same perf + for (const item of set1) { + if (!set2.has(item)) { + return false; + } + } + + return true; +} + +/** + * @template T + * @param {Set} a + * @param {Set} b + * @returns {Set} + */ +export function intersect(a, b) { + // Since set lookup is O(1), iterate over the smaller set for better perf: O(small) vs O(large) + const [small, large] = a.size < b.size ? [a, b] : [b, a]; + return new Set([...small].filter((value) => large.has(value))); +} diff --git a/.github/shared/src/simple-git.js b/.github/shared/src/simple-git.js new file mode 100644 index 000000000000..c8241c839e35 --- /dev/null +++ b/.github/shared/src/simple-git.js @@ -0,0 +1,13 @@ +import { resolve } from "path"; +import { simpleGit } from "simple-git"; + +/** + * + * @param {string} inputPath + * @returns {Promise} + */ +export async function getRootFolder(inputPath) { + // expecting users to handle the case where inputPath is not a git repo + const gitRoot = await simpleGit(inputPath).revparse("--show-toplevel"); + return resolve(gitRoot.trim()); +} diff --git a/.github/shared/src/sleep.js b/.github/shared/src/sleep.js new file mode 100644 index 000000000000..3c7626bf036c --- /dev/null +++ b/.github/shared/src/sleep.js @@ -0,0 +1,7 @@ +/** + * @param {number} ms Number of milliseconds to sleep + * @returns {Promise} + */ +export async function sleep(ms) { + await new Promise((resolve) => setTimeout(resolve, ms)); +} diff --git a/.github/shared/src/sort.js b/.github/shared/src/sort.js new file mode 100644 index 000000000000..59012776d475 --- /dev/null +++ b/.github/shared/src/sort.js @@ -0,0 +1,43 @@ +/** + * Returns a comparator that compares values by a date string in ascending order. + * Throws if the value returned by getDate() is null, undefined, or cannot be + * parsed as a date. + * + * @template T + * @param {(item: T) => string} getDate + * @returns {(a: T, b: T) => number} + */ +export function byDate(getDate) { + return (a, b) => { + // Sort ascending to match JS default + return parseDate(getDate(a)) - parseDate(getDate(b)); + }; +} + +/** + * Parses a string to a date, throwing if null, undefined, or cannot be parsed. + * + * @param {string} s + * @returns {number} + */ +function parseDate(s) { + // Date.parse() returns NaN for null, undefined, or strings that cannot be parsed. + const parsed = Date.parse(s); + + if (Number.isNaN(parsed)) { + throw new Error(`Unable to parse '${s}' to a valid date`); + } + + return parsed; +} + +/** + * Inverts a comparator function. + * + * @template T + * @param {(a: T, b: T) => number} comparator + * @returns {(a: T, b: T) => number} + */ +export function invert(comparator) { + return (a, b) => -comparator(a, b); +} diff --git a/.github/shared/src/spec-model-error.js b/.github/shared/src/spec-model-error.js new file mode 100644 index 000000000000..f81cdce22289 --- /dev/null +++ b/.github/shared/src/spec-model-error.js @@ -0,0 +1,59 @@ +export class SpecModelError extends Error { + /** + * Path to file that caused the error + * + * @type {string|undefined} + */ + #source; + + /** + * Path to readme that caused the error (if known) + * @type {string|undefined} + */ + #readme; + + /** + * Name of tag that caused the error (if known) + * @type {string|undefined} + */ + #tag; + + /** + * @param {string} message + * @param {Object} [options] + * @param {Error} [options.cause] + * @param {string} [options.source] Path to file that caused the error + * @param {string} [options.readme] Path to readme that caused the error (if known) + * @param {string} [options.tag] Name of tag that caused the error (if known) + */ + constructor(message, options = {}) { + const { cause, source, readme, tag } = options; + + const fullMessage = + message + + (source ? `\n Problem File: ${source}` : "") + + (readme ? `\n Readme: ${readme}` : "") + + (tag ? `\n Tag: ${tag}` : "") + + (cause ? `\n Cause: ${cause}` : ""); + + super(fullMessage, { cause }); + + this.name = this.constructor.name; + + this.#source = source; + this.#readme = readme; + this.#tag = tag; + } + + get source() { + return this.#source; + } + + get readme() { + return this.#readme; + } + + get tag() { + return this.#tag; + } +} diff --git a/.github/shared/src/spec-model.js b/.github/shared/src/spec-model.js new file mode 100644 index 000000000000..5bf5de8c3eeb --- /dev/null +++ b/.github/shared/src/spec-model.js @@ -0,0 +1,275 @@ +import { readdir } from "fs/promises"; +import { inspect } from "util"; +import { flatMapAsync, mapAsync } from "./array.js"; +import { readme } from "./changed-files.js"; +import { resolveCached, resolvePairCached } from "./path.js"; +import { Readme } from "./readme.js"; +import { SpecModelError } from "./spec-model-error.js"; + +/** + * @typedef {import('./readme.js').ReadmeJSON} ReadmeJSON + * @typedef {import('./swagger.js').Swagger} Swagger + * @typedef {import('./tag.js').Tag} Tag + */ + +/** + * @typedef {Object} ErrorJSON + * @prop {string} error + */ + +/** + * @typedef {Object} SpecModelJSON + * @property {string} folder + * @property {(ReadmeJSON|ErrorJSON)[]} readmes + */ + +/** + * @typedef {Object} ToJSONOptions + * @prop {boolean} [embedErrors] + * @prop {boolean} [includeOperations] Whether to include the operations in each swagger. Increases runtime about 20x, from 6s to 120s for whole specs repo. + * @prop {boolean} [includeRefs] + * @prop {boolean} [relativePaths] + */ + +/** @type {Map} */ +const specModelCache = new Map(); + +export class SpecModel { + /** @type {string} absolute path */ + // @ts-expect-error Ignore error that value may not be set in ctor (since we may returned cached value) + #folder; + + /** @type {import('./logger.js').ILogger | undefined} */ + #logger; + + /** @type {Map | undefined} */ + #readmes; + + /** + * @param {string} folder + * @param {Object} [options] + * @param {import('./logger.js').ILogger} [options.logger] + */ + constructor(folder, options = {}) { + const { logger } = options; + + const resolvedFolder = resolveCached(folder); + + const cachedSpecModel = specModelCache.get(resolvedFolder); + if (cachedSpecModel !== undefined) { + return cachedSpecModel; + } + + this.#folder = resolvedFolder; + this.#logger = logger; + + specModelCache.set(resolvedFolder, this); + } + + /** + * @returns {string} absolute path + */ + get folder() { + return this.#folder; + } + + /** + * Given a swagger file, return all the tags inside readme files that reference the file (directly or indirectly). + * @param {string} swaggerPath + * @returns {Promise>>} map of readme paths to (map of tag names to Tag objects) + */ + async getAffectedReadmeTags(swaggerPath) { + const swaggerPathResolved = resolveCached(swaggerPath); + + /** @type {Map>} */ + const affectedReadmeTags = new Map(); + + for (const readme of (await this.getReadmes()).values()) { + for (const tag of (await readme.getTags()).values()) { + for (const inputFile of tag.inputFiles.values()) { + if (inputFile.path === swaggerPathResolved) { + /** @type {Map} */ + const tags = affectedReadmeTags.get(readme.path) ?? new Map(); + tags.set(tag.name, tag); + affectedReadmeTags.set(readme.path, tags); + + // No need to check refs if the swagger file is directly referenced + continue; + } + + const refs = await inputFile.getRefs(); + if (refs.get(swaggerPathResolved)) { + /** @type {Map} */ + const tags = affectedReadmeTags.get(readme.path) ?? new Map(); + tags.set(tag.name, tag); + affectedReadmeTags.set(readme.path, tags); + } + } + } + } + + return affectedReadmeTags; + } + + /** + * Given a swagger file, return the swagger files that are affected by the + * changes in the given swagger file. + * @param {string} swaggerPath + * @returns {Promise>} map of swagger paths to Swagger objects + */ + async getAffectedSwaggers(swaggerPath) { + const swaggerPathResolved = resolveCached(swaggerPath); + + /** @type {Map} */ + const affectedSwaggers = new Map(); + + for (const readme of (await this.getReadmes()).values()) { + for (const tag of (await readme.getTags()).values()) { + for (const swagger of tag.inputFiles.values()) { + // readme.md includes swaggerPath + if (swagger.path === swaggerPathResolved) { + affectedSwaggers.set(swagger.path, swagger); + } + + const refs = await swagger.getRefs(); + + // readme.md includes a.json + // a.json references swaggerPath + const refToSwaggerPath = refs.get(swaggerPathResolved); + if (refToSwaggerPath) { + // Add the Swagger object for swaggerPath + affectedSwaggers.set(refToSwaggerPath.path, refToSwaggerPath); + + // Add the Swagger object that references swaggerPath + // + // Example: a.json + affectedSwaggers.set(swagger.path, swagger); + } + + // readme.md includes a.json + // a.json references b.json + // b.json references swaggerPath + for (const ref of refs.values()) { + const refRefs = await ref.getRefs(); + const refRefToSwaggerPath = refRefs.get(swaggerPathResolved); + if (refRefToSwaggerPath) { + // Add the Swagger object for swaggerPath + affectedSwaggers.set(refRefToSwaggerPath.path, refRefToSwaggerPath); + + // Add the Swagger object that references swaggerPath + // + // Example: b.json + affectedSwaggers.set(ref.path, ref); + + // Add the Swagger object that references the Swagger object + // that references swaggerPath + // + // Example: a.json + // + // Note: This may not be strictly necessary, since getRefs() includes + // transitive references, so "a.json" should have already been added + // above. However, it's safer to add it, in case somehow it wasn't added + // earlier, since we know it's in the dependency chain. + affectedSwaggers.set(swagger.path, swagger); + } + } + } + } + } + + // The swagger file supplied does not exist in the given specModel + if (affectedSwaggers.size === 0) { + throw new SpecModelError( + `Swagger file ${swaggerPath} not found in specModel.\n` + + `It must be referenced in the "input-file" section of a tag in a readme.md file ` + + `or in a swagger JSON file using $ref.`, + { source: swaggerPath }, + ); + } + + return affectedSwaggers; + } + + /** + * @returns {Promise>} map of readme paths to readme Objects + */ + async getReadmes() { + if (!this.#readmes) { + const files = await readdir(this.#folder, { + recursive: true, + }); + + const readmePaths = files + // filter before resolve to (slightly) improve perf, since filter only needs filename + .filter(readme) + .map((p) => resolvePairCached(this.#folder, p)); + + this.#logger?.debug(`Found ${readmePaths.length} readme files`); + + this.#readmes = new Map( + readmePaths.map((p) => { + const readme = new Readme(p, { + logger: this.#logger, + specModel: this, + }); + return [readme.path, readme]; + }), + ); + } + + return this.#readmes; + } + + async getSwaggers() { + const readmes = [...(await this.getReadmes()).values()]; + const tags = await flatMapAsync(readmes, async (r) => [...(await r.getTags()).values()]); + const swaggers = tags.flatMap((t) => [...t.inputFiles.values()]); + const refs = await flatMapAsync(swaggers, async (s) => [...(await s.getRefs()).values()]); + return [...swaggers, ...refs]; + } + + /** + * @param {ToJSONOptions} [options] + * @returns {Promise} + */ + async toJSONAsync(options = {}) { + return await embedError(async () => { + const readmes = await mapAsync( + [...(await this.getReadmes()).values()].sort((a, b) => a.path.localeCompare(b.path)), + async (r) => await r.toJSONAsync(options), + ); + return { + folder: this.#folder, + readmes, + }; + }, options); + } + + /** + * @returns {string} + */ + toString() { + return `SpecModel(${this.#folder}, {logger: ${inspect(this.#logger)}}})`; + } +} + +/** + * @template T + * @param {() => Promise} fn + * @param {Object} [options] + * @param {boolean} [options.embedErrors] + * @returns {Promise} + */ +export async function embedError(fn, options = {}) { + const { embedErrors } = options; + + try { + return await fn(); + } catch (error) { + if (embedErrors && error instanceof Error) { + return { error: error.message }; + } else { + throw error; + } + } +} diff --git a/.github/shared/src/swagger.js b/.github/shared/src/swagger.js new file mode 100644 index 000000000000..6db79acf14ae --- /dev/null +++ b/.github/shared/src/swagger.js @@ -0,0 +1,458 @@ +import $RefParser from "@apidevtools/json-schema-ref-parser"; +import { readFile } from "fs/promises"; +import { dirname, relative } from "path"; +import { inspect } from "util"; +import { z } from "zod"; +import { mapAsync } from "./array.js"; +import { KeyedCache } from "./cache.js"; +import { example, preview } from "./changed-files.js"; +import { resolveCached, resolvePairCached } from "./path.js"; +import { SpecModelError } from "./spec-model-error.js"; +import { embedError } from "./spec-model.js"; + +/** + * @typedef {import('./spec-model.js').ErrorJSON} ErrorJSON + * @typedef {import('./spec-model.js').Tag} Tag + * @typedef {import('./spec-model.js').ToJSONOptions} ToJSONOptions + */ + +/** + * @typedef {Object} Operation + * @property {string} id - The operation ID + * @property {string} path - API path + * @property {string} httpMethod - HTTP method (GET, POST, etc.) + */ + +/** + * @typedef {Object} SwaggerJSON + * @property {string} path + * @property {Operation[]} [operations] + * @property {Object[]} [refs] + */ + +const infoSchema = z.object({ + "x-typespec-generated": z.array(z.object({ emitter: z.string().optional() })).optional(), +}); +/** + * @typedef {import("zod").infer} InfoObject + */ + +// https://swagger.io/specification/v2/#operation-object +const operationSchema = z.object({ operationId: z.string().optional() }); +/** + * @typedef {import("zod").infer} OperationObject + */ + +// TODO: Consider narrowing to only the field names in the spec ("get", "put", etc) +// https://swagger.io/specification/v2/#path-item-object +const pathSchema = z + .object({ + parameters: z.array(z.unknown()).optional(), + }) + .catchall(operationSchema); +/** + * @typedef {import("zod").infer} PathObject + */ + +// https://swagger.io/specification/v2/#paths-object +const pathsSchema = z.record(z.string(), pathSchema); +/** + * @typedef {import("zod").infer} PathsObject + */ + +// https://swagger.io/specification/v2/#swagger-object +const swaggerSchema = z.object({ + info: infoSchema.optional(), + paths: pathsSchema.optional(), + "x-ms-paths": pathsSchema.optional(), +}); +/** + * @typedef {import("zod").infer} SwaggerObject + * + * @example + * const swagger = { + * "paths": { + * "/foo": { + * "parameters": [ ... ], + * "get": { + * "operationId": "Foo_Get" + * }, + * "put": { + * "operationId": "Foo_CreateOrUpdate" + * } + * }, + * "/bar": { ... } + * }, + * "x-ms-paths": { + * "/baz": { ... } + * } + * }; + */ + +/** + * @type {import('@apidevtools/json-schema-ref-parser').ResolverOptions} + */ +const excludeExamples = { + order: 1, + canRead: true, + read: async ( + /** @type import('@apidevtools/json-schema-ref-parser').FileInfo */ + file, + ) => { + if (example(file.url)) { + return ""; + } + return await readFile(file.url, { encoding: "utf8" }); + }, +}; + +export class Swagger { + /** + * Caches the contents of files on disk, using the resolved path as the key. + * + * @type {KeyedCache>} + */ + static #contentCache = new KeyedCache(); + + /** + * Caches JSON objects parsed from text, using the resolved path (or content string itself) as the key. + * + * @type {KeyedCache>} + * */ + static #contentJsonCache = new KeyedCache(); + + /** + * Caches SwaggerObject objects parsed from JSON objects, using the resolved path (or content string itself) as the key. + * + * @type {KeyedCache>} + */ + static #contentObjectCache = new KeyedCache(); + + /** + * Caches operations extracted from a SwaggerObject, using the resolved path (or content string itself) as the key. + * + * @type {KeyedCache>>} + */ + static #operationsCache = new KeyedCache(); + + /** + * Caches reference paths extracted from a JSON object, using the resolved path (or content string itself) as the key. + * + * Swagger objects should not be cached statically, because they may belong to different Tags, Readmes, or SpecModels. + * + * @type {KeyedCache>} + */ + static #refPathCache = new KeyedCache(); + + /** + * Optional content of swagger file, passed in via `options`. If undefined, content is loaded from `#path`. + * + * @type {string | undefined} + */ + #content; + + /** @type {import('./logger.js').ILogger | undefined} */ + #logger; + + /** @type {string} absolute path */ + #path; + + /** @type {Tag | undefined} Tag that contains this Swagger */ + #tag; + + /** @type {Map | undefined} all references, safe to cache in instance (but not statically) */ + #allRefs; + + /** @type {Map | undefined} referenced swaggers (excluding examples), safe to cache in instance (but not statically) */ + #refs; + + /** @type {Map | undefined} referenced examples (excluding swaggers), safe to cache in instance (but not statically) */ + #examples; + + /** + * @param {string} path + * @param {Object} [options] + * @param {string} [options.content] If specified, is used instead of reading path from disk + * @param {import('./logger.js').ILogger} [options.logger] + * @param {Tag} [options.tag] + */ + constructor(path, options = {}) { + const { content, logger, tag } = options; + + const rootDir = dirname(tag?.readme?.path ?? ""); + this.#path = resolvePairCached(rootDir, path); + + this.#content = content; + this.#logger = logger; + this.#tag = tag; + } + + /** + * @returns {Promise} Content of swagger file, represented as a string, either loaded from `#path` or passed in via `options` + * @throws {SpecModelError} + */ + async #getContent() { + return ( + this.#content ?? + (await Swagger.#contentCache.getOrCreate( + this.#path, + async () => + await this.#wrapError( + async () => await readFile(this.#path, { encoding: "utf8" }), + "Failed to read file for swagger", + ), + )) + ); + } + + /** + * @returns {Promise} Content of swagger file, represented as an untyped JSON object + * @throws {SpecModelError} + */ + async #getContentJSON() { + return await Swagger.#contentJsonCache.getOrCreate( + this.#content ?? this.#path, + async () => + await this.#wrapError( + async () => /** @type {unknown} */ (JSON.parse(await this.#getContent())), + "Failed to parse JSON for swagger", + ), + ); + } + + /** + * @returns {Promise} Content of swagger file, represented as a typed object + * @throws {SpecModelError} + */ + async #getContentObject() { + return await Swagger.#contentObjectCache.getOrCreate( + this.#content ?? this.#path, + async () => + await this.#wrapError( + async () => swaggerSchema.parse(await this.#getContentJSON()), + "Failed to parse schema for swagger", + ), + ); + } + + /** + * @returns {Promise>} Map of swaggers referenced from this swagger, using `path` as key + */ + async getRefs() { + if (this.#refs === undefined) { + const allRefs = await this.#getRefs(); + + // filter out any paths that are examples + const filtered = new Map([...allRefs].filter(([path]) => !example(path))); + + this.#refs = filtered; + } + return this.#refs; + } + + async #getRefs() { + if (this.#allRefs === undefined) { + // Safe to cache refPaths statically, since it's just an array of string paths + const refPaths = await Swagger.#refPathCache.getOrCreate( + this.#content ?? this.#path, + async () => { + const contentJSON = await this.#getContentJSON(); + + const schema = await this.#wrapError( + async () => + await $RefParser.resolve(this.#path, contentJSON, { + resolve: { file: excludeExamples, http: false }, + }), + "Failed to resolve file for swagger", + ); + + return ( + schema + .paths("file") + // Exclude ourself + .filter((p) => resolveCached(p) !== resolveCached(this.#path)) + ); + }, + ); + + // Swagger objects should not be cached statically, because they may belong to different Tags, Readmes, or SpecModels. + // But, they are safe to cache in this instance. + this.#allRefs = new Map( + refPaths.map((p) => { + const swagger = new Swagger(p, { + logger: this.#logger, + tag: this.#tag, + }); + return [swagger.path, swagger]; + }), + ); + } + + return this.#allRefs; + } + + /** + * @returns {Promise>} Map of examples referenced from this swagger, using `path` as key + */ + async getExamples() { + if (this.#examples === undefined) { + const allRefs = await this.#getRefs(); + + // filter out any paths that are examples + const filtered = new Map([...allRefs].filter(([path]) => example(path))); + + this.#examples = filtered; + } + return this.#examples; + } + + /** + * @returns {Promise>} Map of the operations in this swagger, using `operationId` as key + */ + async getOperations() { + return await Swagger.#operationsCache.getOrCreate(this.#content ?? this.#path, async () => { + const contentObject = await this.#getContentObject(); + + /** @type {Map} */ + const operations = new Map(); + + // Process regular paths + if (contentObject.paths) { + for (const [path, pathObject] of Object.entries(contentObject.paths)) { + this.#addOperations(operations, path, pathObject); + } + } + + // Process x-ms-paths (Azure extension) + if (contentObject["x-ms-paths"]) { + for (const [path, pathObject] of Object.entries(contentObject["x-ms-paths"])) { + this.#addOperations(operations, path, pathObject); + } + } + + return operations; + }); + } + + /** + * @returns {Promise} True if the spec was generated from TypeSpec + */ + async getTypeSpecGenerated() { + const contentObject = await this.#getContentObject(); + return contentObject.info?.["x-typespec-generated"] !== undefined; + } + + /** + * + * @param {Map} operations + * @param {string} path + * @param {PathObject} pathObject + * @returns {void} + */ + #addOperations(operations, path, pathObject) { + for (const [method, operation] of Object.entries( + /** @type {Omit} */ (pathObject), + )) { + if (method !== "parameters" && operation.operationId !== undefined) { + const operationObj = { + id: operation.operationId, + httpMethod: method.toUpperCase(), + path: path, + }; + operations.set(operation.operationId, operationObj); + } + } + } + + /** + * @returns {string} absolute path + */ + get path() { + return this.#path; + } + + /** + * @returns {Tag | undefined} Tag that contains this Swagger + */ + get tag() { + return this.#tag; + } + + /** + * @returns {string} version kind (stable or preview) + */ + get versionKind() { + return preview(this.#path) + ? API_VERSION_LIFECYCLE_STAGES.PREVIEW + : API_VERSION_LIFECYCLE_STAGES.STABLE; + } + + /** + * @param {ToJSONOptions} [options] + * @returns {Promise} + */ + async toJSONAsync(options = {}) { + const { includeOperations, includeRefs, relativePaths } = options; + + return await embedError( + async () => ({ + path: + relativePaths && this.#tag?.readme?.specModel + ? relative(this.#tag?.readme?.specModel.folder, this.#path) + : this.#path, + operations: includeOperations + ? [...(await this.getOperations()).values()].map((o) => { + // Create new object with properties in preferred output order + return { path: o.path, httpMethod: o.httpMethod, id: o.id }; + }) + : undefined, + refs: includeRefs + ? await mapAsync( + [...(await this.getRefs()).values()].sort((a, b) => a.path.localeCompare(b.path)), + async (s) => + // Do not include swagger refs transitively, otherwise we could get in infinite loop + await s.toJSONAsync({ ...options, includeRefs: false }), + ) + : undefined, + }), + options, + ); + } + + toString() { + return `Swagger(${this.#path}, {logger: ${inspect(this.#logger)}})`; + } + + /** + * Returns value of `func()`, wrapping any `Error` in `SpecModelError` + * + * @template T + * @param {() => T | Promise} func + * @param {string} message + * @returns {Promise} + * @throws {SpecModelError} + */ + async #wrapError(func, message) { + try { + return await func(); + } catch (error) { + /* v8 ignore else -- defensive rethrow */ + if (error instanceof Error) { + throw new SpecModelError(`${message}: ${this.#path}`, { + cause: error, + source: this.#path, + tag: this.#tag?.name, + readme: this.#tag?.readme?.path, + }); + } else { + throw error; + } + } + } +} + +// API version lifecycle stages +export const API_VERSION_LIFECYCLE_STAGES = Object.freeze({ + PREVIEW: "preview", + STABLE: "stable", +}); diff --git a/.github/shared/src/tag.js b/.github/shared/src/tag.js new file mode 100644 index 000000000000..0502db908546 --- /dev/null +++ b/.github/shared/src/tag.js @@ -0,0 +1,98 @@ +import { inspect } from "util"; +import { mapAsync } from "./array.js"; +import { embedError } from "./spec-model.js"; +import { Swagger } from "./swagger.js"; + +/** + * @typedef {import('./spec-model.js').ErrorJSON} ErrorJSON + * @typedef {import('./readme.js').Readme} Readme + * @typedef {import('./swagger.js').SwaggerJSON} SwaggerJSON + * @typedef {import('./spec-model.js').ToJSONOptions} ToJSONOptions + */ + +/** + * @typedef {Object} TagJSON + * @property {string} name + * @property {(SwaggerJSON|ErrorJSON)[]} inputFiles + */ + +export class Tag { + /** @type {Map} */ + #inputFiles; + + /** @type {import('./logger.js').ILogger | undefined} */ + #logger; + + /** @type {string} */ + #name; + + /** + * Readme that contains this Tag + * @type {Readme | undefined} + */ + #readme; + + /** + * @param {string} name + * @param {string[]} inputFilePaths + * @param {Object} [options] + * @param {import('./logger.js').ILogger} [options.logger] + * @param {Readme} [options.readme] + */ + constructor(name, inputFilePaths, options = {}) { + const { logger, readme } = options; + + this.#name = name; + this.#logger = logger; + this.#readme = readme; + + this.#inputFiles = new Map( + inputFilePaths.map((p) => { + let swagger = new Swagger(p, { logger: this.#logger, tag: this }); + return [swagger.path, swagger]; + }), + ); + } + + /** + * @returns {Map} + */ + get inputFiles() { + return this.#inputFiles; + } + + /** + * @returns {string} + */ + get name() { + return this.#name; + } + + /** + * @returns {Readme | undefined} Readme that contains this Tag + */ + get readme() { + return this.#readme; + } + + /** + * @param {ToJSONOptions} [options] + * @returns {Promise} + */ + async toJSONAsync(options = {}) { + return await embedError( + async () => ({ + name: this.#name, + inputFiles: await mapAsync( + [...this.#inputFiles.values()].sort((a, b) => a.path.localeCompare(b.path)), + async (s) => await s.toJSONAsync(options), + ), + }), + options, + ); + } + + toString() { + return `Tag(${this.#name}, {logger: ${inspect(this.#logger)}})`; + } +} diff --git a/.github/shared/src/time.js b/.github/shared/src/time.js new file mode 100644 index 000000000000..accbf5961daa --- /dev/null +++ b/.github/shared/src/time.js @@ -0,0 +1,75 @@ +/** + * @typedef {Object} DurationType + * @property {number} Millisecond - 1 millisecond + * @property {number} Second - 1 second in milliseconds + * @property {number} Minute - 1 minute in milliseconds + * @property {number} Hour - 1 hour in milliseconds + * @property {number} Day - 1 day in milliseconds + * @property {number} Week - 1 week in milliseconds + */ + +/** + * Common time duration constants in milliseconds. + * + * @readonly + * @type {DurationType} + */ +export const Duration = Object.freeze({ + Millisecond: 1, + Second: 1000, + Minute: 60 * 1000, + Hour: 60 * 60 * 1000, + Day: 24 * 60 * 60 * 1000, + Week: 7 * 24 * 60 * 60 * 1000, +}); + +/** + * Add milliseconds to a date. + * @param {Date} date + * @param {number} ms + * @returns {Date} + */ +export function add(date, ms) { + return new Date(date.getTime() + ms); +} + +/** + * Formats a duration of milliseconds as hh:mm:ss (always zero-padded). + * + * @param {number} ms + * @returns {string} + */ +export function formatDuration(ms) { + let totalSeconds = Math.floor(ms / Duration.Second); + + const hours = Math.floor(totalSeconds / 3600); + totalSeconds %= 3600; + + const minutes = Math.floor(totalSeconds / 60); + const seconds = totalSeconds % 60; + + const pad = (/** @type {number} */ n) => String(n).padStart(2, "0"); + + return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`; +} + +/** + * Returns the number of milliseconds between two dates (always non-negative) + * + * @param {Date} from + * @param {Date} to + * @returns {number} + */ +export function getDuration(from, to) { + return Math.abs(from.getTime() - to.getTime()); +} + +/** + * Subtract milliseconds from a date. + * @param {Date} date + * @param {number} ms + * @returns {Date} + */ +export function subtract(date, ms) { + return new Date(date.getTime() - ms); +} diff --git a/.github/shared/test/array.test.js b/.github/shared/test/array.test.js new file mode 100644 index 000000000000..591331465401 --- /dev/null +++ b/.github/shared/test/array.test.js @@ -0,0 +1,56 @@ +import { describe, expect, it } from "vitest"; +import { filterAsync, flatMapAsync, includesEvery, includesNone, mapAsync } from "../src/array.js"; +import { sleep } from "../src/sleep.js"; + +describe("array", () => { + it("filterAsync", async () => { + const input = [1, 2, 3]; + + const result = await filterAsync(input, async (item, index) => { + await sleep(index); + return item === 1 || index === 1; + }); + + expect(result).toEqual([1, 2]); + }); + + it("flatMapAsync", async () => { + const input = [1, 2, 3]; + + const result = await flatMapAsync(input, async (item, index) => { + await sleep(index); + return [index, item * index]; + }); + + expect(result).toEqual([0, 0, 1, 2, 2, 6]); + }); + + it("mapAsync", async () => { + const input = [1, 2, 3]; + + const result = await mapAsync(input, async (item, index) => { + await sleep(index); + return item * index; + }); + + expect(result).toEqual([0, 2, 6]); + }); + + it("includesEvery", () => { + const input = [1, 2, 3]; + const values = [1, 2]; + + expect(includesEvery(input, values)).toBe(true); + expect(includesEvery(input, [4])).toBe(false); + expect(includesEvery(input, [])).toBe(true); + }); + + it("includesNone", () => { + const input = [1, 2, 3]; + const values = [4, 5]; + + expect(includesNone(input, values)).toBe(true); + expect(includesNone(input, [2])).toBe(false); + expect(includesNone(input, [])).toBe(true); + }); +}); diff --git a/.github/shared/test/cache.test.js b/.github/shared/test/cache.test.js new file mode 100644 index 000000000000..4f9400749d44 --- /dev/null +++ b/.github/shared/test/cache.test.js @@ -0,0 +1,89 @@ +import { describe, expect, it } from "vitest"; +import { KeyedCache, KeyedPairCache } from "../src/cache.js"; + +describe("KeyedCache", () => { + it("createAndGetSync", () => { + /** @type {KeyedCache} */ + const cache = new KeyedCache(); + + let createdCount = 0; + const getOrCreate = () => + cache.getOrCreate(42, () => { + createdCount++; + return "foo"; + }); + + for (let i = 0; i < 3; i++) { + expect(getOrCreate()).toEqual("foo"); + } + expect(createdCount).toEqual(1); + }); + + it("createAndGetAsync", async () => { + /** @type {KeyedCache>} */ + const cache = new KeyedCache(); + + let createdCount = 0; + const getOrCreate = () => + cache.getOrCreate(42, async () => { + await Promise.resolve(); + createdCount++; + return "foo"; + }); + + for (let i = 0; i < 3; i++) { + await expect(getOrCreate()).resolves.toEqual("foo"); + } + expect(createdCount).toEqual(1); + }); +}); + +describe("KeyedPairCache", () => { + it("createAndGetSync", () => { + /** @type {KeyedPairCache} */ + const cache = new KeyedPairCache(); + + let createdCount = 0; + const getOrCreate = () => + cache.getOrCreate(42, 7, () => { + createdCount++; + return "foo"; + }); + + for (let i = 0; i < 3; i++) { + expect(getOrCreate()).toEqual("foo"); + } + expect(createdCount).toEqual(1); + }); + + it("createAndGetAsync", async () => { + /** @type {KeyedPairCache>} */ + const cache = new KeyedPairCache(); + + let createdCount = 0; + const getOrCreate = () => + cache.getOrCreate(42, 7, async () => { + await Promise.resolve(); + createdCount++; + return "foo"; + }); + + for (let i = 0; i < 3; i++) { + await expect(getOrCreate()).resolves.toEqual("foo"); + } + expect(createdCount).toEqual(1); + }); + + it("keys are ordered", () => { + /** @type {KeyedPairCache} */ + const cache = new KeyedPairCache(); + + const getOrCreateFooBar = () => cache.getOrCreate(42, 7, () => "42-7"); + const getOrCreateBarFoo = () => cache.getOrCreate(7, 42, () => "7-42"); + + for (let i = 0; i < 3; i++) { + expect(getOrCreateFooBar()).toEqual("42-7"); + expect(getOrCreateBarFoo()).toEqual("7-42"); + } + }); +}); diff --git a/.github/shared/test/changed-files.test.js b/.github/shared/test/changed-files.test.js new file mode 100644 index 000000000000..d9d97c954604 --- /dev/null +++ b/.github/shared/test/changed-files.test.js @@ -0,0 +1,474 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; + +const mockDiff = vi.hoisted(() => vi.fn().mockResolvedValue("")); + +vi.mock("simple-git", () => ({ + simpleGit: vi.fn().mockReturnValue({ + diff: mockDiff, + }), +})); + +import { resolve } from "path"; +import * as simpleGit from "simple-git"; +import { + dataPlane, + example, + getChangedFiles, + getChangedFilesStatuses, + json, + markdown, + preview, + quickstartTemplate, + readme, + resourceManager, + scenario, + stable, + swagger, + typespec, +} from "../src/changed-files.js"; +import { debugLogger } from "../src/logger.js"; + +describe("changedFiles", () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + it.each([{}, { logger: debugLogger }])(`getChangedFiles(%o)`, async (options) => { + const files = [ + ".github/src/changed-files.js", + "specification/contosowidgetmanager/Contoso.Management/main.tsp", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json", + ]; + + mockDiff.mockResolvedValue(files.join("\n")); + + await expect(getChangedFiles(options)).resolves.toEqual(files); + expect(mockDiff).toHaveBeenCalledWith(["--name-only", "HEAD^", "HEAD"]); + + const specFiles = files.filter((f) => f.startsWith("specification")); + mockDiff.mockResolvedValue(specFiles.join("\n")); + await expect(getChangedFiles({ ...options, paths: ["specification"] })).resolves.toEqual( + specFiles, + ); + expect(mockDiff).toHaveBeenCalledWith(["--name-only", "HEAD^", "HEAD", "--", "specification"]); + }); + + it("getChangedFiles returns empty array when no files are changed", async () => { + mockDiff.mockResolvedValue(""); + await expect(getChangedFiles()).resolves.toEqual([]); + expect(mockDiff).toHaveBeenCalledWith(["--name-only", "HEAD^", "HEAD"]); + }); + + it("getChangedFiles accepts gitOptions parameter", async () => { + const files = ["file1.json", "file2.json"]; + mockDiff.mockResolvedValue(files.join("\n")); + + await expect(getChangedFiles({ gitOptions: ["--no-renames"] })).resolves.toEqual(files); + expect(mockDiff).toHaveBeenCalledWith(["--name-only", "--no-renames", "HEAD^", "HEAD"]); + }); + + it("getChangedFiles accepts multiple gitOptions", async () => { + const files = ["file1.json"]; + mockDiff.mockResolvedValue(files.join("\n")); + + await expect( + getChangedFiles({ gitOptions: ["--no-renames", "--find-copies"] }), + ).resolves.toEqual(files); + expect(mockDiff).toHaveBeenCalledWith([ + "--name-only", + "--no-renames", + "--find-copies", + "HEAD^", + "HEAD", + ]); + }); + + const files = [ + "CONTRIBUTING.MD", + "cspell.json", + "cspell.yaml", + "MixedCase.jSoN", + "MixedCase.mD", + "README.MD", + "not-spec/contosowidgetmanager/data-plane/readme.md", + "not-spec/contosowidgetmanager/resource-manager/readme.md", + "not-spec/contosowidgetmanager/Contoso.Management/main.tsp", + "not-spec/contosowidgetmanager/Contoso.Management/tspconfig.yaml", + "not-spec/contosowidgetmanager/Contoso.Management/examples/2021-11-01/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/examples/2021-12-01-preview/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/scenarios/2021-11-01/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/scenarios/2021-12-01-preview/Employees_Get.json", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/data-plane/readme.md", + "specification/contosowidgetmanager/Contoso.Management/main.tsp", + "specification/contosowidgetmanager/Contoso.Management/tspconfig.yaml", + "specification/contosowidgetmanager/Contoso.Management/examples/2021-11-01/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/examples/2021-12-01-preview/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/readme.md", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/examples/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/scenarios/2021-11-01/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/scenarios/2021-12-01-preview/Employees_Get.json", + "specification/compute/quickstart-templates/swagger.json", + ]; + + const filesResolved = files.map((f) => resolve(f)); + + it("filter:json", () => { + const expected = [ + "cspell.json", + "MixedCase.jSoN", + "not-spec/contosowidgetmanager/Contoso.Management/examples/2021-11-01/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/examples/2021-12-01-preview/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/scenarios/2021-11-01/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/scenarios/2021-12-01-preview/Employees_Get.json", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/Contoso.Management/examples/2021-11-01/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/examples/2021-12-01-preview/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/examples/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/scenarios/2021-11-01/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/scenarios/2021-12-01-preview/Employees_Get.json", + "specification/compute/quickstart-templates/swagger.json", + ]; + + expect(files.filter(json)).toEqual(expected); + expect(filesResolved.filter(json)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:markdown", () => { + const expected = [ + "CONTRIBUTING.MD", + "MixedCase.mD", + "README.MD", + "not-spec/contosowidgetmanager/data-plane/readme.md", + "not-spec/contosowidgetmanager/resource-manager/readme.md", + "specification/contosowidgetmanager/data-plane/readme.md", + "specification/contosowidgetmanager/resource-manager/readme.md", + ]; + + expect(files.filter(markdown)).toEqual(expected); + expect(filesResolved.filter(markdown)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:readme", () => { + const expected = [ + "README.MD", + "not-spec/contosowidgetmanager/data-plane/readme.md", + "not-spec/contosowidgetmanager/resource-manager/readme.md", + "specification/contosowidgetmanager/data-plane/readme.md", + "specification/contosowidgetmanager/resource-manager/readme.md", + ]; + + expect(files.filter(readme)).toEqual(expected); + expect(filesResolved.filter(readme)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:typespec", () => { + const expected = [ + "not-spec/contosowidgetmanager/Contoso.Management/main.tsp", + "not-spec/contosowidgetmanager/Contoso.Management/tspconfig.yaml", + "specification/contosowidgetmanager/Contoso.Management/main.tsp", + "specification/contosowidgetmanager/Contoso.Management/tspconfig.yaml", + ]; + expect(files.filter(typespec)).toEqual(expected); + }); + + it("filter:data-plane", () => { + const expected = [ + "not-spec/contosowidgetmanager/data-plane/readme.md", + "specification/contosowidgetmanager/data-plane/readme.md", + ]; + + expect(files.filter(dataPlane)).toEqual(expected); + expect(filesResolved.filter(dataPlane)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:resource-manager", () => { + const expected = [ + "not-spec/contosowidgetmanager/resource-manager/readme.md", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/readme.md", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/examples/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json", + ]; + + expect(files.filter(resourceManager)).toEqual(expected); + expect(filesResolved.filter(resourceManager)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:preview", () => { + const expected = [ + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/examples/Employees_Get.json", + ]; + + expect(files.filter(preview)).toEqual(expected); + expect(filesResolved.filter(preview)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:stable", () => { + const expected = [ + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json", + ]; + + expect(files.filter(stable)).toEqual(expected); + expect(filesResolved.filter(stable)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:example", () => { + const expected = [ + "not-spec/contosowidgetmanager/Contoso.Management/examples/2021-11-01/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/examples/2021-12-01-preview/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/examples/2021-11-01/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/examples/2021-12-01-preview/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/examples/Employees_Get.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json", + ]; + + expect(files.filter(example)).toEqual(expected); + expect(filesResolved.filter(example)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:quickstartTemplate", () => { + const expected = ["specification/compute/quickstart-templates/swagger.json"]; + + expect(files.filter(quickstartTemplate)).toEqual(expected); + }); + + it("filter:scenarios", () => { + const expected = [ + "not-spec/contosowidgetmanager/Contoso.Management/scenarios/2021-11-01/Employees_Get.json", + "not-spec/contosowidgetmanager/Contoso.Management/scenarios/2021-12-01-preview/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/scenarios/2021-11-01/Employees_Get.json", + "specification/contosowidgetmanager/Contoso.Management/scenarios/2021-12-01-preview/Employees_Get.json", + ]; + + expect(files.filter(scenario)).toEqual(expected); + expect(filesResolved.filter(scenario)).toEqual(expected.map((f) => resolve(f))); + }); + + it("filter:swagger", () => { + const expected = [ + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "not-spec/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-12-01-preview/contoso.json", + "specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + ]; + + expect(files.filter(swagger)).toEqual(expected); + expect(filesResolved.filter(swagger)).toEqual(expected.map((f) => resolve(f))); + }); + + describe("getChangedFilesStatuses", () => { + it.each([{}, { logger: debugLogger }])( + "should categorize files correctly with all types of changes (%o)", + async (options) => { + const gitOutput = [ + "M\t.github/src/changed-files.js", + "A\tspecification/new-service/readme.md", + "M\tspecification/existing-service/main.tsp", + "D\tspecification/old-service/contoso.json", + "R100\tspecification/service/old-name.json\tspecification/service/new-name.json", + "C90\tspecification/template/base.json\tspecification/service/derived.json", + "T\tspecification/service/type-changed.json", + ].join("\n"); + + mockDiff.mockResolvedValue(gitOutput); + let result = await getChangedFilesStatuses(options); + expect(result).toEqual({ + additions: ["specification/new-service/readme.md", "specification/service/derived.json"], + modifications: [ + ".github/src/changed-files.js", + "specification/existing-service/main.tsp", + "specification/service/type-changed.json", + ], + deletions: ["specification/old-service/contoso.json"], + renames: [ + { + from: "specification/service/old-name.json", + to: "specification/service/new-name.json", + }, + ], + total: 7, + }); + expect(mockDiff).toHaveBeenCalledWith(["--name-status", "HEAD^", "HEAD"]); + + const specGitOutput = gitOutput + .split("\n") + .filter((f) => f.includes("specification/")) + .join("\n"); + mockDiff.mockResolvedValue(specGitOutput); + result = await getChangedFilesStatuses({ ...options, paths: ["specification"] }); + expect(result).toEqual({ + additions: ["specification/new-service/readme.md", "specification/service/derived.json"], + modifications: [ + "specification/existing-service/main.tsp", + "specification/service/type-changed.json", + ], + deletions: ["specification/old-service/contoso.json"], + renames: [ + { + from: "specification/service/old-name.json", + to: "specification/service/new-name.json", + }, + ], + total: 6, + }); + expect(mockDiff).toHaveBeenCalledWith([ + "--name-status", + "HEAD^", + "HEAD", + "--", + "specification", + ]); + }, + ); + + it("should handle empty git output", async () => { + mockDiff.mockResolvedValue(""); + const result = await getChangedFilesStatuses(); + expect(result).toEqual({ + additions: [], + modifications: [], + deletions: [], + renames: [], + total: 0, + }); + }); + + it("should handle only additions", async () => { + const gitOutput = [ + "A\tspecification/service1/readme.md", + "A\tspecification/service2/main.tsp", + ].join("\n"); + + mockDiff.mockResolvedValue(gitOutput); + const result = await getChangedFilesStatuses(); + expect(result).toEqual({ + additions: ["specification/service1/readme.md", "specification/service2/main.tsp"], + modifications: [], + deletions: [], + renames: [], + total: 2, + }); + }); + + it("should handle only renames", async () => { + const gitOutput = [ + "R95\told/path/file1.json\tnew/path/file1.json", + "R100\tservice/old.tsp\tservice/new.tsp", + ].join("\n"); + + mockDiff.mockResolvedValue(gitOutput); + const result = await getChangedFilesStatuses(); + expect(result).toEqual({ + additions: [], + modifications: [], + deletions: [], + renames: [ + { + from: "old/path/file1.json", + to: "new/path/file1.json", + }, + { + from: "service/old.tsp", + to: "service/new.tsp", + }, + ], + total: 2, + }); + }); + + it("should pass git options correctly", async () => { + const options = { + baseCommitish: "origin/main", + headCommitish: "feature-branch", + cwd: "/custom/path", + }; + + mockDiff.mockResolvedValue("A\ttest.json"); + await getChangedFilesStatuses(options); + expect(simpleGit.simpleGit).toHaveBeenCalledWith("/custom/path"); + expect(mockDiff).toHaveBeenCalledWith(["--name-status", "origin/main", "feature-branch"]); + }); + + it("should accept gitOptions parameter", async () => { + mockDiff.mockResolvedValue("A\tfile1.json\nM\tfile2.json"); + const result = await getChangedFilesStatuses({ gitOptions: ["--no-renames"] }); + expect(result).toEqual({ + additions: ["file1.json"], + modifications: ["file2.json"], + deletions: [], + renames: [], + total: 2, + }); + expect(mockDiff).toHaveBeenCalledWith(["--name-status", "--no-renames", "HEAD^", "HEAD"]); + }); + + it("should accept multiple gitOptions", async () => { + mockDiff.mockResolvedValue("A\tfile1.json"); + const result = await getChangedFilesStatuses({ + gitOptions: ["--no-renames", "--find-copies"], + }); + expect(result).toEqual({ + additions: ["file1.json"], + modifications: [], + deletions: [], + renames: [], + total: 1, + }); + expect(mockDiff).toHaveBeenCalledWith([ + "--name-status", + "--no-renames", + "--find-copies", + "HEAD^", + "HEAD", + ]); + }); + + it("should log categories selectively with a logger", async () => { + // When only some categories are populated and a logger is provided, the per-category + // if-blocks whose category is empty should take their false branch. + const gitOutput = [ + "A\tspecification/service1/readme.md", + "A\tspecification/service2/main.tsp", + ].join("\n"); + + mockDiff.mockResolvedValue(gitOutput); + const result = await getChangedFilesStatuses({ logger: debugLogger }); + expect(result).toEqual({ + additions: ["specification/service1/readme.md", "specification/service2/main.tsp"], + modifications: [], + deletions: [], + renames: [], + total: 2, + }); + + // Also test with no additions so the additions log block's false branch is covered + const gitOutputNoAdditions = "M\tspecification/service1/readme.md"; + mockDiff.mockResolvedValue(gitOutputNoAdditions); + const result2 = await getChangedFilesStatuses({ logger: debugLogger }); + expect(result2).toEqual({ + additions: [], + modifications: ["specification/service1/readme.md"], + deletions: [], + renames: [], + total: 1, + }); + }); + }); +}); diff --git a/.github/shared/test/console.test.js b/.github/shared/test/console.test.js new file mode 100644 index 000000000000..db6c97d836fe --- /dev/null +++ b/.github/shared/test/console.test.js @@ -0,0 +1,51 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { log } from "../src/console.js"; + +describe("console", () => { + describe("log", () => { + /** @type {import("vitest").MockInstance} */ + let writeSpy; + + beforeEach(() => { + writeSpy = vi.spyOn(process.stdout, "write").mockReturnValue(true); + }); + + afterEach(() => { + writeSpy.mockRestore(); + }); + + it("writes a formatted line to stdout", async () => { + await log("hello %s", "world"); + expect(writeSpy).toBeCalledWith("hello world\n"); + }); + + it("formats multiple arguments like console.log", async () => { + await log("a", "b", "c"); + expect(writeSpy).toBeCalledWith("a b c\n"); + }); + + it("works with no arguments", async () => { + await log(); + expect(writeSpy).toBeCalledWith("\n"); + }); + + it("awaits drain when stdout has backpressure", async () => { + writeSpy.mockReturnValueOnce(false); + + let resolved = false; + const promise = log("backpressure test").then(() => { + resolved = true; + }); + + // Should still be pending before drain + expect(resolved).toBe(false); + expect(writeSpy).toBeCalledWith("backpressure test\n"); + + // Unblock backpressure + process.stdout.emit("drain"); + await promise; + + expect(resolved).toBe(true); + }); + }); +}); diff --git a/.github/shared/test/examples.js b/.github/shared/test/examples.js new file mode 100644 index 000000000000..a094b3712834 --- /dev/null +++ b/.github/shared/test/examples.js @@ -0,0 +1,112 @@ +export const fullGitSha = "abc123abc123abc123abc123abc123abc123abc1"; + +export const swaggerHandWritten = JSON.stringify({}); + +export const swaggerTypeSpecGenerated = JSON.stringify({ + info: { + "x-typespec-generated": [{ emitter: "@azure-tools/typespec-autorest" }], + }, +}); + +export const contosoTspConfig = ` +parameters: + "service-dir": + default: "sdk/contosowidgetmanager" + "dependencies": + default: "" +emit: + - "@azure-tools/typespec-autorest" +linter: + extends: + - "@azure-tools/typespec-azure-rulesets/data-plane" +options: + "@azure-tools/typespec-autorest": + azure-resource-provider-folder: "data-plane" + emit-lro-options: "none" + emitter-output-dir: "{project-root}/.." + output-file: "{azure-resource-provider-folder}/{service-name}/{version-status}/{version}/widgets.json" + "@azure-tools/typespec-python": + package-dir: "azure-contoso-widgetmanager" + namespace: "azure.contoso.widgetmanager" + generate-test: true + generate-sample: true + flavor: azure + "@azure-tools/typespec-csharp": + package-dir: "Azure.Template.Contoso" + clear-output-folder: true + model-namespace: false + namespace: "{package-dir}" + flavor: azure + "@azure-tools/typespec-ts": + package-dir: "contosowidgetmanager-rest" + package-details: + name: "@azure-rest/contoso-widgetmanager-rest" + flavor: azure + "@azure-tools/typespec-java": + package-dir: "azure-contoso-widgetmanager" + namespace: com.azure.contoso.widgetmanager + flavor: azure + "@azure-tools/typespec-go": + module: "github.com/Azure/azure-sdk-for-go/{service-dir}/{package-dir}" + service-dir: "sdk/contosowidget" + package-dir: "azmanager" + module-version: "0.0.1" + generate-fakes: true + inject-spans: true + single-client: true + slice-elements-byval: true + "@azure-tools/typespec-client-generator-cli": + additionalDirectories: + - "specification/contosowidgetmanager/Contoso.WidgetManager.Shared/" +`; + +export const contosoReadme = ` +# contosowidgetmanager + +> see https://aka.ms/autorest +This is the AutoRest configuration file for Contoso. + +## Getting Started + +To build the SDKs for My API, simply install AutoRest via \`npm\` (\`npm install -g autorest\`) and then run: + +> \`autorest readme.md\` +To see additional help and options, run: + +> \`autorest --help\` +For other options on installation see [Installing AutoRest](https://aka.ms/autorest/install) on the AutoRest github page. + +--- + +## Configuration + +### Basic Information + +These are the global settings for the containerstorage. + +\`\`\`yaml +openapi-type: arm +openapi-subtype: rpaas +tag: package-2021-11-01 +\`\`\` + +### Tag: package-2021-11-01 + +These settings apply only when \`--tag=package-2021-11-01\` is specified on the command line. + +\`\`\`yaml $(tag) == 'package-2021-11-01' +input-file: + - Microsoft.Contoso/stable/2021-11-01/contoso.json +\`\`\` + +### Tag: package-2021-10-01-preview + +These settings apply only when \`--tag=package-2021-10-01-preview\` is specified on the command line. + +\`\`\`yaml $(tag) == 'package-2021-10-01-preview' +input-file: + - Microsoft.Contoso/preview/2021-10-01-preview/contoso.json +\`\`\` + +--- +`; diff --git a/.github/shared/test/exec.test.js b/.github/shared/test/exec.test.js new file mode 100644 index 000000000000..4c49a99d0f5a --- /dev/null +++ b/.github/shared/test/exec.test.js @@ -0,0 +1,99 @@ +import { dirname, resolve } from "path"; +import semver from "semver"; +import { fileURLToPath } from "url"; +import { describe, expect, it } from "vitest"; +import { execFile, execNpm, execNpmExec, isExecError } from "../src/exec.js"; +import { debugLogger } from "../src/logger.js"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +const options = { logger: debugLogger }; + +describe("execFile", () => { + const file = "node"; + const args = ["-e", `console.log("test")`]; + const expected = "test\n"; + + it.each([{}, options])("exec succeeds with default buffer (options: %o)", async (options) => { + await expect(execFile(file, args, options)).resolves.toEqual({ + stdout: expected, + stderr: "", + }); + }); + + it("exec succeeds with exact-sized buffer", async () => { + await expect(execFile(file, args, { ...options, maxBuffer: expected.length })).resolves.toEqual( + { stdout: expected, stderr: "" }, + ); + }); + + it("exec fails with too-small buffer", async () => { + await expect( + execFile(file, args, { ...options, maxBuffer: expected.length - 1 }), + ).rejects.toMatchObject({ + stdout: "test", + stderr: "", + code: "ERR_CHILD_PROCESS_STDIO_MAXBUFFER", + }); + }); +}); + +describe("execNpm", () => { + it("succeeds with --version", async () => { + await expect(execNpm(["--version"], options)).resolves.toMatchObject({ + stdout: /** @type {unknown} */ (expect.toSatisfy((v) => semver.valid(String(v)) !== null)), + stderr: "", + }); + }); + + it("succeeds with --prefix", async () => { + // "npm prefix" in this dir, without the "--prefix" option, returns the parent dir + let result = await execNpm(["prefix"], { ...options, cwd: __dirname }); + expect(result.stdout.trim()).toEqual(resolve(__dirname, "..")); + + // with the "--prefix" option set to this dir, returns this dir + result = await execNpm(["prefix"], { ...options, cwd: __dirname, prefix: __dirname }); + expect(result.stdout.trim()).toEqual(__dirname); + }); + + it("fails with --help", async () => { + await expect(execNpm(["--help"], options)).rejects.toMatchObject({ + stdout: /** @type {unknown} */ (expect.stringMatching(/usage/i)), + stderr: "", + code: 1, + }); + }); +}); + +describe("execNpmExec", () => { + // A command run in the context of "npm exec --no -- ___" needs to call + // something referenced in package.json. In this case, prettier is present + // so it is used. + it("runs prettier", async () => { + await expect(execNpmExec(["prettier", "--version"], options)).resolves.toEqual({ + stdout: /** @type {unknown} */ (expect.toSatisfy((v) => semver.valid(String(v)) !== null)), + stderr: "", + error: undefined, + }); + }); +}); + +describe("isExecError", () => { + it("isExecError", () => { + expect(isExecError("test")).toBe(false); + + const error = new Error(); + expect(isExecError(error)).toBe(false); + + const execError = /** @type {import("../src/exec.js").ExecError} */ (error); + + execError.stdout = "test"; + expect(isExecError(execError)).toBe(true); + + delete execError.stdout; + expect(isExecError(execError)).toBe(false); + + execError.stderr = "test"; + expect(isExecError(execError)).toBe(true); + }); +}); diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/common-types/resource-management/v5/types.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/common-types/resource-management/v5/types.json new file mode 100644 index 000000000000..600190811bf8 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/common-types/resource-management/v5/types.json @@ -0,0 +1,722 @@ +{ + "swagger": "2.0", + "info": { + "title": "Common types", + "version": "5.0" + }, + "paths": {}, + "definitions": { + "AzureEntityResource": { + "type": "object", + "title": "Entity Resource", + "description": "The resource model definition for an Azure Resource Manager resource with an etag.", + "properties": { + "etag": { + "type": "string", + "description": "Resource Etag.", + "readOnly": true + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "x-ms-client-name": "AzureEntityResource" + }, + "CheckNameAvailabilityRequest": { + "type": "object", + "description": "The check availability request body.", + "properties": { + "name": { + "type": "string", + "description": "The name of the resource for which availability needs to be checked." + }, + "type": { + "type": "string", + "description": "The resource type." + } + } + }, + "CheckNameAvailabilityResponse": { + "type": "object", + "description": "The check availability result.", + "properties": { + "nameAvailable": { + "type": "boolean", + "description": "Indicates if the resource name is available." + }, + "reason": { + "type": "string", + "description": "The reason why the given name is not available.", + "enum": [ + "Invalid", + "AlreadyExists" + ], + "x-ms-enum": { + "name": "CheckNameAvailabilityReason", + "modelAsString": true + } + }, + "message": { + "type": "string", + "description": "Detailed reason why the given name is available." + } + } + }, + "ErrorAdditionalInfo": { + "type": "object", + "description": "The resource management error additional info.", + "properties": { + "type": { + "type": "string", + "description": "The additional info type.", + "readOnly": true + }, + "info": { + "type": "object", + "description": "The additional info.", + "readOnly": true + } + } + }, + "ErrorDetail": { + "type": "object", + "description": "The error detail.", + "properties": { + "code": { + "type": "string", + "description": "The error code.", + "readOnly": true + }, + "message": { + "type": "string", + "description": "The error message.", + "readOnly": true + }, + "target": { + "type": "string", + "description": "The error target.", + "readOnly": true + }, + "details": { + "type": "array", + "description": "The error details.", + "items": { + "$ref": "#/definitions/ErrorDetail" + }, + "readOnly": true, + "x-ms-identifiers": [ + "message", + "target" + ] + }, + "additionalInfo": { + "type": "array", + "description": "The error additional info.", + "items": { + "$ref": "#/definitions/ErrorAdditionalInfo" + }, + "readOnly": true, + "x-ms-identifiers": [] + } + } + }, + "ErrorResponse": { + "type": "object", + "title": "Error response", + "description": "Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.).", + "properties": { + "error": { + "$ref": "#/definitions/ErrorDetail", + "description": "The error object." + } + } + }, + "Identity": { + "type": "object", + "description": "Identity for the resource.", + "properties": { + "principalId": { + "type": "string", + "format": "uuid", + "description": "The principal ID of resource identity. The value must be an UUID.", + "readOnly": true + }, + "tenantId": { + "type": "string", + "format": "uuid", + "description": "The tenant ID of resource. The value must be an UUID.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The identity type.", + "enum": [ + "SystemAssigned" + ], + "x-ms-enum": { + "name": "ResourceIdentityType", + "modelAsString": false + } + } + } + }, + "KeyVaultProperties": { + "type": "object", + "properties": { + "keyIdentifier": { + "type": "string", + "description": "Key vault uri to access the encryption key." + }, + "identity": { + "type": "string", + "description": "The client ID of the identity which will be used to access key vault." + } + } + }, + "Operation": { + "type": "object", + "title": "REST API Operation", + "description": "Details of a REST API operation, returned from the Resource Provider Operations API", + "properties": { + "name": { + "type": "string", + "description": "The name of the operation, as per Resource-Based Access Control (RBAC). Examples: \"Microsoft.Compute/virtualMachines/write\", \"Microsoft.Compute/virtualMachines/capture/action\"", + "readOnly": true + }, + "isDataAction": { + "type": "boolean", + "description": "Whether the operation applies to data-plane. This is \"true\" for data-plane operations and \"false\" for ARM/control-plane operations.", + "readOnly": true + }, + "display": { + "type": "object", + "description": "Localized display information for this particular operation.", + "properties": { + "provider": { + "type": "string", + "description": "The localized friendly form of the resource provider name, e.g. \"Microsoft Monitoring Insights\" or \"Microsoft Compute\".", + "readOnly": true + }, + "resource": { + "type": "string", + "description": "The localized friendly name of the resource type related to this operation. E.g. \"Virtual Machines\" or \"Job Schedule Collections\".", + "readOnly": true + }, + "operation": { + "type": "string", + "description": "The concise, localized friendly name for the operation; suitable for dropdowns. E.g. \"Create or Update Virtual Machine\", \"Restart Virtual Machine\".", + "readOnly": true + }, + "description": { + "type": "string", + "description": "The short, localized friendly description of the operation; suitable for tool tips and detailed views.", + "readOnly": true + } + } + }, + "origin": { + "type": "string", + "description": "The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is \"user,system\"", + "enum": [ + "user", + "system", + "user,system" + ], + "x-ms-enum": { + "name": "Origin", + "modelAsString": true + }, + "readOnly": true + }, + "actionType": { + "type": "string", + "description": "Enum. Indicates the action type. \"Internal\" refers to actions that are for internal only APIs.", + "enum": [ + "Internal" + ], + "x-ms-enum": { + "name": "ActionType", + "modelAsString": true + }, + "readOnly": true + } + } + }, + "OperationListResult": { + "type": "object", + "description": "A list of REST API operations supported by an Azure Resource Provider. It contains an URL link to get the next set of results.", + "properties": { + "value": { + "type": "array", + "description": "List of operations supported by the resource provider", + "items": { + "$ref": "#/definitions/Operation" + }, + "readOnly": true, + "x-ms-identifiers": [ + "name" + ] + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "URL to get the next set of operation list results (if there are any).", + "readOnly": true + } + } + }, + "OperationStatusResult": { + "type": "object", + "description": "The current status of an async operation.", + "properties": { + "id": { + "type": "string", + "format": "arm-id", + "description": "Fully qualified ID for the async operation." + }, + "resourceId": { + "type": "string", + "format": "arm-id", + "description": "Fully qualified ID of the resource against which the original async operation was started.", + "readOnly": true + }, + "name": { + "type": "string", + "description": "Name of the async operation." + }, + "status": { + "type": "string", + "description": "Operation status." + }, + "percentComplete": { + "type": "number", + "description": "Percent of the operation that is complete.", + "minimum": 0, + "maximum": 100 + }, + "startTime": { + "type": "string", + "format": "date-time", + "description": "The start time of the operation." + }, + "endTime": { + "type": "string", + "format": "date-time", + "description": "The end time of the operation." + }, + "operations": { + "type": "array", + "description": "The operations list.", + "items": { + "$ref": "#/definitions/OperationStatusResult" + } + }, + "error": { + "$ref": "#/definitions/ErrorDetail", + "description": "If present, details of the operation error." + } + }, + "required": [ + "status" + ] + }, + "Plan": { + "type": "object", + "description": "Plan for the resource.", + "properties": { + "name": { + "type": "string", + "description": "A user defined name of the 3rd Party Artifact that is being procured." + }, + "publisher": { + "type": "string", + "description": "The publisher of the 3rd Party Artifact that is being bought. E.g. NewRelic" + }, + "product": { + "type": "string", + "description": "The 3rd Party artifact that is being procured. E.g. NewRelic. Product maps to the OfferID specified for the artifact at the time of Data Market onboarding. " + }, + "promotionCode": { + "type": "string", + "description": "A publisher provided promotion code as provisioned in Data Market for the said product/artifact." + }, + "version": { + "type": "string", + "description": "The version of the desired product/artifact." + } + }, + "required": [ + "name", + "publisher", + "product" + ] + }, + "ProxyResource": { + "type": "object", + "title": "Proxy Resource", + "description": "The resource model definition for a Azure Resource Manager proxy resource. It will not have tags and a location", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "Resource": { + "type": "object", + "title": "Resource", + "description": "Common fields that are returned in the response for all Azure Resource Manager resources", + "properties": { + "id": { + "type": "string", + "format": "arm-id", + "description": "Fully qualified resource ID for the resource. E.g. \"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}\"", + "readOnly": true + }, + "name": { + "type": "string", + "description": "The name of the resource", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The type of the resource. E.g. \"Microsoft.Compute/virtualMachines\" or \"Microsoft.Storage/storageAccounts\"", + "readOnly": true + }, + "systemData": { + "$ref": "#/definitions/systemData", + "description": "Azure Resource Manager metadata containing createdBy and modifiedBy information.", + "readOnly": true + } + }, + "x-ms-azure-resource": true + }, + "ResourceModelWithAllowedPropertySet": { + "type": "object", + "description": "The resource model definition containing the full set of allowed properties for a resource. Except properties bag, there cannot be a top level property outside of this set.", + "properties": { + "managedBy": { + "type": "string", + "description": "The fully qualified resource ID of the resource that manages this resource. Indicates if this resource is managed by another Azure resource. If this is present, complete mode deployment will not delete the resource if it is removed from the template since it is managed by another resource.", + "x-ms-mutability": [ + "read", + "create", + "update" + ] + }, + "kind": { + "type": "string", + "description": "Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type. E.g. ApiApps are a kind of Microsoft.Web/sites type. If supported, the resource provider must validate and persist this value.", + "pattern": "^[-\\w\\._,\\(\\)]+$", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "etag": { + "type": "string", + "description": "The etag field is *not* required. If it is provided in the response body, it must also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields. ", + "readOnly": true + }, + "identity": { + "allOf": [ + { + "$ref": "#/definitions/Identity" + } + ] + }, + "sku": { + "allOf": [ + { + "$ref": "#/definitions/Sku" + } + ] + }, + "plan": { + "allOf": [ + { + "$ref": "#/definitions/Plan" + } + ] + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "x-ms-azure-resource": true + }, + "Sku": { + "type": "object", + "description": "The resource model definition representing SKU", + "properties": { + "name": { + "type": "string", + "description": "The name of the SKU. E.g. P3. It is typically a letter+number code" + }, + "tier": { + "$ref": "#/definitions/SkuTier" + }, + "size": { + "type": "string", + "description": "The SKU size. When the name field is the combination of tier and some other value, this would be the standalone code. " + }, + "family": { + "type": "string", + "description": "If the service has different generations of hardware, for the same SKU, then that can be captured here." + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "If the SKU supports scale out/in then the capacity integer should be included. If scale out/in is not possible for the resource this may be omitted." + } + }, + "required": [ + "name" + ] + }, + "SkuTier": { + "type": "string", + "description": "This field is required to be implemented by the Resource Provider if the service has more than one tier, but is not required on a PUT.", + "enum": [ + "Free", + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuTier", + "modelAsString": false + } + }, + "TrackedResource": { + "type": "object", + "title": "Tracked Resource", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ] + }, + "location": { + "type": "string", + "description": "The geo-location where the resource lives", + "x-ms-mutability": [ + "read", + "create" + ] + } + }, + "required": [ + "location" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "encryptionProperties": { + "type": "object", + "description": "Configuration of key for data encryption", + "properties": { + "status": { + "type": "string", + "description": "Indicates whether or not the encryption is enabled for container registry.", + "enum": [ + "enabled", + "disabled" + ], + "x-ms-enum": { + "name": "EncryptionStatus", + "modelAsString": true + } + }, + "keyVaultProperties": { + "$ref": "#/definitions/KeyVaultProperties", + "description": "Key vault properties." + } + } + }, + "locationData": { + "type": "object", + "description": "Metadata pertaining to the geographic location of the resource.", + "properties": { + "name": { + "type": "string", + "description": "A canonical name for the geographic or physical location.", + "maxLength": 256 + }, + "city": { + "type": "string", + "description": "The city or locality where the resource is located." + }, + "district": { + "type": "string", + "description": "The district, state, or province where the resource is located." + }, + "countryOrRegion": { + "type": "string", + "description": "The country or region where the resource is located" + } + }, + "required": [ + "name" + ] + }, + "systemData": { + "type": "object", + "description": "Metadata pertaining to creation and last modification of the resource.", + "properties": { + "createdBy": { + "type": "string", + "description": "The identity that created the resource." + }, + "createdByType": { + "type": "string", + "description": "The type of identity that created the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp of resource creation (UTC)." + }, + "lastModifiedBy": { + "type": "string", + "description": "The identity that last modified the resource." + }, + "lastModifiedByType": { + "type": "string", + "description": "The type of identity that last modified the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "lastModifiedAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp of resource last modification (UTC)" + } + }, + "readOnly": true + } + }, + "parameters": { + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "description": "The API version to use for this operation.", + "required": true, + "type": "string", + "minLength": 1 + }, + "If-Match": { + "name": "ifMatch", + "in": "header", + "description": "The If-Match header that makes a request conditional.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + }, + "If-None-Match": { + "name": "ifNoneMatch", + "in": "header", + "description": "The If-None-Match header that makes a request conditional.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + }, + "LocationParameter": { + "name": "location", + "in": "path", + "description": "The name of the Azure region.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method" + }, + "ManagementGroupNameParameter": { + "name": "managementGroupName", + "in": "path", + "description": "The name of the management group. The name is case insensitive.", + "required": true, + "type": "string", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "OperationIdParameter": { + "name": "operationId", + "in": "path", + "description": "The ID of an ongoing async operation.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method" + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "description": "The name of the resource group. The name is case insensitive.", + "required": true, + "type": "string", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "ScopeParameter": { + "name": "scope", + "in": "path", + "description": "The scope at which the operation is performed.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method", + "x-ms-skip-url-encoding": true + }, + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "description": "The ID of the target subscription. The value must be an UUID.", + "required": true, + "type": "string", + "format": "uuid" + }, + "TenantIdParameter": { + "name": "tenantId", + "in": "path", + "description": "The Azure tenant ID. This is a GUID-formatted string (e.g. 00000000-0000-0000-0000-000000000000)", + "required": true, + "type": "string", + "format": "uuid", + "x-ms-parameter-location": "method" + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/contoso.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/contoso.json new file mode 100644 index 000000000000..c51e0e74c52f --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/contoso.json @@ -0,0 +1,556 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.Contoso management service", + "version": "2021-10-01-preview", + "description": "Microsoft.Contoso Resource Provider management API.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Employees" + } + ], + "paths": { + "/providers/Microsoft.Contoso/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Operations_List": { + "$ref": "./examples/Operations_List.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListBySubscription", + "tags": [ + "Employees" + ], + "description": "List Employee resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListBySubscription": { + "$ref": "./examples/Employees_ListBySubscription.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListByResourceGroup", + "tags": [ + "Employees" + ], + "description": "List Employee resources by resource group", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListByResourceGroup": { + "$ref": "./examples/Employees_ListByResourceGroup.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}": { + "get": { + "operationId": "Employees_Get", + "tags": [ + "Employees" + ], + "description": "Get a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Get": { + "$ref": "./examples/Employees_Get.json" + } + } + }, + "put": { + "operationId": "Employees_CreateOrUpdate", + "tags": [ + "Employees" + ], + "description": "Create a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/Employee" + } + } + ], + "responses": { + "200": { + "description": "Resource 'Employee' update operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "201": { + "description": "Resource 'Employee' create operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_CreateOrUpdate": { + "$ref": "./examples/Employees_CreateOrUpdate.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Employees_Update", + "tags": [ + "Employees" + ], + "description": "Update a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/EmployeeUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Update": { + "$ref": "./examples/Employees_Update.json" + } + } + }, + "delete": { + "operationId": "Employees_Delete", + "tags": [ + "Employees" + ], + "description": "Delete a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Delete": { + "$ref": "./examples/Employees_Delete.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.CommonTypes.TrackedResourceUpdate": { + "type": "object", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/Resource" + } + ] + }, + "Employee": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/TrackedResource" + } + ] + }, + "EmployeeListResult": { + "type": "object", + "description": "The response of a Employee list operation.", + "properties": { + "value": { + "type": "array", + "description": "The Employee items on this page", + "items": { + "$ref": "#/definitions/Employee" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "EmployeeProperties": { + "type": "object", + "description": "Employee properties", + "properties": { + "age": { + "type": "integer", + "format": "int32", + "description": "Age of employee" + }, + "city": { + "type": "string", + "description": "City of employee" + }, + "profile": { + "type": "string", + "format": "base64url", + "description": "Profile of employee" + }, + "provisioningState": { + "$ref": "#/definitions/ProvisioningState", + "description": "The status of the last operation.", + "readOnly": true + } + } + }, + "EmployeeUpdate": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.TrackedResourceUpdate" + } + ] + }, + "ProvisioningState": { + "type": "string", + "description": "The resource provisioning state.", + "enum": [ + "Succeeded", + "Failed", + "Canceled", + "Provisioning", + "Updating", + "Deleting", + "Accepted" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + }, + { + "name": "Provisioning", + "value": "Provisioning", + "description": "The resource is being provisioned" + }, + { + "name": "Updating", + "value": "Updating", + "description": "The resource is updating" + }, + { + "name": "Deleting", + "value": "Deleting", + "description": "The resource is being deleted" + }, + { + "name": "Accepted", + "value": "Accepted", + "description": "The resource create request has been accepted" + } + ] + }, + "readOnly": true + } + }, + "parameters": {} +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_CreateOrUpdate.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_CreateOrUpdate.json new file mode 100644 index 000000000000..9b34209dcd17 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_CreateOrUpdate.json @@ -0,0 +1,76 @@ +{ + "title": "Employees_CreateOrUpdate", + "operationId": "Employees_CreateOrUpdate", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "9KF-f-8b", + "resource": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl" + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + }, + "201": { + "headers": { + "Azure-AsyncOperation": "https://contoso.com/operationstatus" + }, + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/9KF-f-8b", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Delete.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Delete.json new file mode 100644 index 000000000000..9ac7910eb3f7 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Delete.json @@ -0,0 +1,19 @@ +{ + "title": "Employees_Delete", + "operationId": "Employees_Delete", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "5vX--BxSu3ux48rI4O9OQ569" + }, + "responses": { + "202": { + "headers": { + "Retry-After": 30, + "location": "https://contoso.com/operationstatus" + } + }, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Get.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Get.json new file mode 100644 index 000000000000..3ee7ff5b9c4f --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Get.json @@ -0,0 +1,37 @@ +{ + "title": "Employees_Get", + "operationId": "Employees_Get", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "le-8MU--J3W6q8D386p3-iT3" + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListByResourceGroup.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListByResourceGroup.json new file mode 100644 index 000000000000..f6512d2ba7c2 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListByResourceGroup.json @@ -0,0 +1,41 @@ +{ + "title": "Employees_ListByResourceGroup", + "operationId": "Employees_ListByResourceGroup", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListBySubscription.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListBySubscription.json new file mode 100644 index 000000000000..ffa095dd1d66 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListBySubscription.json @@ -0,0 +1,40 @@ +{ + "title": "Employees_ListBySubscription", + "operationId": "Employees_ListBySubscription", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Update.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Update.json new file mode 100644 index 000000000000..f3f85a465653 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Update.json @@ -0,0 +1,47 @@ +{ + "title": "Employees_Update", + "operationId": "Employees_Update", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "-XhyNJ--", + "properties": { + "tags": { + "key7952": "no" + }, + "properties": { + "age": 24, + "city": "uyfg", + "profile": "oapgijcswfkruiuuzbwco" + } + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/contoso/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Operations_List.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Operations_List.json new file mode 100644 index 000000000000..6185e205aa43 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Operations_List.json @@ -0,0 +1,28 @@ +{ + "title": "Operations_List", + "operationId": "Operations_List", + "parameters": { + "api-version": "2021-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "ymeow", + "isDataAction": true, + "display": { + "provider": "qxyznq", + "resource": "bqfwkox", + "operation": "td", + "description": "yvgkhsuwartgxb" + }, + "origin": "user", + "actionType": "Internal" + } + ], + "nextLink": "https://sample.com/nextLink" + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json new file mode 100644 index 000000000000..10ffa6631f16 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json @@ -0,0 +1,556 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.Contoso management service", + "version": "2021-11-01", + "description": "Microsoft.Contoso Resource Provider management API.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Employees" + } + ], + "paths": { + "/providers/Microsoft.Contoso/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Operations_List": { + "$ref": "./examples/Operations_List.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListBySubscription", + "tags": [ + "Employees" + ], + "description": "List Employee resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListBySubscription": { + "$ref": "./examples/Employees_ListBySubscription.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListByResourceGroup", + "tags": [ + "Employees" + ], + "description": "List Employee resources by resource group", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListByResourceGroup": { + "$ref": "./examples/Employees_ListByResourceGroup.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}": { + "get": { + "operationId": "Employees_Get", + "tags": [ + "Employees" + ], + "description": "Get a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Get": { + "$ref": "./examples/Employees_Get.json" + } + } + }, + "put": { + "operationId": "Employees_CreateOrUpdate", + "tags": [ + "Employees" + ], + "description": "Create a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/Employee" + } + } + ], + "responses": { + "200": { + "description": "Resource 'Employee' update operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "201": { + "description": "Resource 'Employee' create operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_CreateOrUpdate": { + "$ref": "./examples/Employees_CreateOrUpdate.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Employees_Update", + "tags": [ + "Employees" + ], + "description": "Update a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/EmployeeUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Update": { + "$ref": "./examples/Employees_Update.json" + } + } + }, + "delete": { + "operationId": "Employees_Delete", + "tags": [ + "Employees" + ], + "description": "Delete a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Delete": { + "$ref": "./examples/Employees_Delete.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.CommonTypes.TrackedResourceUpdate": { + "type": "object", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/Resource" + } + ] + }, + "Employee": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/TrackedResource" + } + ] + }, + "EmployeeListResult": { + "type": "object", + "description": "The response of a Employee list operation.", + "properties": { + "value": { + "type": "array", + "description": "The Employee items on this page", + "items": { + "$ref": "#/definitions/Employee" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "EmployeeProperties": { + "type": "object", + "description": "Employee properties", + "properties": { + "age": { + "type": "integer", + "format": "int32", + "description": "Age of employee" + }, + "city": { + "type": "string", + "description": "City of employee" + }, + "profile": { + "type": "string", + "format": "base64url", + "description": "Profile of employee" + }, + "provisioningState": { + "$ref": "#/definitions/ProvisioningState", + "description": "The status of the last operation.", + "readOnly": true + } + } + }, + "EmployeeUpdate": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.TrackedResourceUpdate" + } + ] + }, + "ProvisioningState": { + "type": "string", + "description": "The resource provisioning state.", + "enum": [ + "Succeeded", + "Failed", + "Canceled", + "Provisioning", + "Updating", + "Deleting", + "Accepted" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + }, + { + "name": "Provisioning", + "value": "Provisioning", + "description": "The resource is being provisioned" + }, + { + "name": "Updating", + "value": "Updating", + "description": "The resource is updating" + }, + { + "name": "Deleting", + "value": "Deleting", + "description": "The resource is being deleted" + }, + { + "name": "Accepted", + "value": "Accepted", + "description": "The resource create request has been accepted" + } + ] + }, + "readOnly": true + } + }, + "parameters": {} +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_CreateOrUpdate.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_CreateOrUpdate.json new file mode 100644 index 000000000000..4a13a329e3b8 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_CreateOrUpdate.json @@ -0,0 +1,76 @@ +{ + "title": "Employees_CreateOrUpdate", + "operationId": "Employees_CreateOrUpdate", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "9KF-f-8b", + "resource": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl" + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + }, + "201": { + "headers": { + "Azure-AsyncOperation": "https://contoso.com/operationstatus" + }, + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/9KF-f-8b", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Delete.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Delete.json new file mode 100644 index 000000000000..15176d86b029 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Delete.json @@ -0,0 +1,19 @@ +{ + "title": "Employees_Delete", + "operationId": "Employees_Delete", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "5vX--BxSu3ux48rI4O9OQ569" + }, + "responses": { + "202": { + "headers": { + "Retry-After": 30, + "location": "https://contoso.com/operationstatus" + } + }, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json new file mode 100644 index 000000000000..eb1917859e24 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json @@ -0,0 +1,37 @@ +{ + "title": "Employees_Get", + "operationId": "Employees_Get", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "le-8MU--J3W6q8D386p3-iT3" + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListByResourceGroup.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListByResourceGroup.json new file mode 100644 index 000000000000..860fab85a9b8 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListByResourceGroup.json @@ -0,0 +1,41 @@ +{ + "title": "Employees_ListByResourceGroup", + "operationId": "Employees_ListByResourceGroup", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListBySubscription.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListBySubscription.json new file mode 100644 index 000000000000..18432d58de37 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListBySubscription.json @@ -0,0 +1,40 @@ +{ + "title": "Employees_ListBySubscription", + "operationId": "Employees_ListBySubscription", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Update.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Update.json new file mode 100644 index 000000000000..de46fc8ef2e8 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Update.json @@ -0,0 +1,47 @@ +{ + "title": "Employees_Update", + "operationId": "Employees_Update", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "-XhyNJ--", + "properties": { + "tags": { + "key7952": "no" + }, + "properties": { + "age": 24, + "city": "uyfg", + "profile": "oapgijcswfkruiuuzbwco" + } + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/contoso/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Operations_List.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Operations_List.json new file mode 100644 index 000000000000..4d74e755c020 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Operations_List.json @@ -0,0 +1,28 @@ +{ + "title": "Operations_List", + "operationId": "Operations_List", + "parameters": { + "api-version": "2021-11-01" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "ymeow", + "isDataAction": true, + "display": { + "provider": "qxyznq", + "resource": "bqfwkox", + "operation": "td", + "description": "yvgkhsuwartgxb" + }, + "origin": "user", + "actionType": "Internal" + } + ], + "nextLink": "https://sample.com/nextLink" + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/readme.md b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/readme.md new file mode 100644 index 000000000000..ae912e6ab9b0 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/contosowidgetmanager/resource-manager/readme.md @@ -0,0 +1,48 @@ +# containerstorage + +> see https://aka.ms/autorest +This is the AutoRest configuration file for Contoso. + +## Getting Started + +To build the SDKs for My API, simply install AutoRest via `npm` (`npm install -g autorest`) and then run: + +> `autorest readme.md` +To see additional help and options, run: + +> `autorest --help` +For other options on installation see [Installing AutoRest](https://aka.ms/autorest/install) on the AutoRest github page. + +--- + +## Configuration + +### Basic Information + +These are the global settings for the containerstorage. + +```yaml +openapi-type: arm +openapi-subtype: rpaas +tag: package-2021-11-01 +``` + +### Tag: package-2021-11-01 + +These settings apply only when `--tag=package-2021-11-01` is specified on the command line. + +```yaml $(tag) == 'package-2021-11-01' +input-file: + - Microsoft.Contoso/stable/2021-11-01/contoso.json +``` + +### Tag: package-2021-10-01-preview + +These settings apply only when `--tag=package-2021-10-01-preview` is specified on the command line. + +```yaml $(tag) == 'package-2021-10-01-preview' +input-file: + - Microsoft.Contoso/preview/2021-10-01-preview/contoso.json +``` + +--- diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-invalid-json/invalid-json.json b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-invalid-json/invalid-json.json new file mode 100644 index 000000000000..6b7f8497d846 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-invalid-json/invalid-json.json @@ -0,0 +1 @@ +invalid json \ No newline at end of file diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-invalid-json/readme.md b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-invalid-json/readme.md new file mode 100644 index 000000000000..0a719f6d8418 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-invalid-json/readme.md @@ -0,0 +1,19 @@ +# resolve-error + +Test how resolve errors are handled when a tag points to an input-file that does +not contian valid JSON. + +```yaml +openapi-type: arm +openapi-subtype: rpaas +tag: package-2021-11-01 +``` + +### Tag: package-2021-11-01 + +These settings apply only when `--tag=package-2021-11-01` is specified on the command line. + +```yaml $(tag) == 'package-2021-11-01' +input-file: + - invalid-json.json +``` diff --git a/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-not-found/readme.md b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-not-found/readme.md new file mode 100644 index 000000000000..e95ed9add13f --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedReadmeTags/specification/input-file-not-found/readme.md @@ -0,0 +1,19 @@ +# resolve-error + +Test how resolve errors are handled when a tag points to an input-file that +does not exist. + +```yaml +openapi-type: arm +openapi-subtype: rpaas +tag: package-2021-11-01 +``` + +### Tag: package-2021-11-01 + +These settings apply only when `--tag=package-2021-11-01` is specified on the command line. + +```yaml $(tag) == 'package-2021-11-01' +input-file: + - does-not-exist.json +``` diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/a.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/a.json new file mode 100644 index 000000000000..0d9a7af77520 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/a.json @@ -0,0 +1,41 @@ +{ + "swagger": "2.0", + "info": { + "title": "Service A", + "version": "1.0.0" + }, + "paths": { + "/a": { + "get": { + "summary": "Get A (refs B)", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/B" + } + } + } + }, + "put": { + "summary": "Update A (refs C)", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/C" + } + } + } + } + } + }, + "definitions": { + "B": { + "$ref": "./nesting/b.json#/definitions/B" + }, + "C": { + "$ref": "c.json#/definitions/C" + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/c.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/c.json new file mode 100644 index 000000000000..8bec3cc3498e --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/c.json @@ -0,0 +1,51 @@ +{ + "swagger": "2.0", + "info": { + "title": "Service C", + "version": "1.0.0" + }, + "paths": { + "/c": { + "get": { + "summary": "Get C", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/C" + } + } + } + } + }, + "/d": { + "get": { + "summary": "Get D", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/D" + } + } + } + } + } + }, + "definitions": { + "C": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "D": { + "$ref": "d.json#/definitions/D" + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/d.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/d.json new file mode 100644 index 000000000000..ad2cee57453b --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/d.json @@ -0,0 +1,51 @@ +{ + "swagger": "2.0", + "info": { + "title": "Service D", + "version": "1.0.0" + }, + "paths": { + "/d": { + "get": { + "summary": "Get D", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/D" + } + } + } + } + }, + "/shared-thing": { + "get": { + "summary": "Get SharedThing", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/SharedThing" + } + } + } + } + } + }, + "definitions": { + "D": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "description": { + "type": "string" + } + } + }, + "SharedThing": { + "$ref": "./shared/shared.json#/definitions/SharedThing" + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/e.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/e.json new file mode 100644 index 000000000000..ff2304866ec0 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/e.json @@ -0,0 +1,38 @@ +{ + "swagger": "2.0", + "info": { + "title": "Service E", + "version": "1.0.0" + }, + "paths": { + "/e": { + "get": { + "summary": "Get E", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/E" + } + } + } + } + } + }, + "definitions": { + "E": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "description": { + "type": "string" + } + } + }, + "SharedThing": { + "$ref": "./shared/shared.json#/definitions/SharedThing" + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/nesting/b.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/nesting/b.json new file mode 100644 index 000000000000..d71cadf5d9d4 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/nesting/b.json @@ -0,0 +1,49 @@ +{ + "swagger": "2.0", + "info": { + "title": "Service B", + "version": "1.0.0" + }, + "paths": { + "/b": { + "get": { + "summary": "Get B (refs C)", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/C" + } + } + } + }, + "put": { + "summary": "Update B (refs D)", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "#/definitions/D" + } + } + } + } + } + }, + "definitions": { + "B": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "description": { + "type": "string" + } + } + }, + "C": { + "$ref": "../c.json#/definitions/C" + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/readme.md b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/readme.md new file mode 100644 index 000000000000..68bb802fe44f --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/readme.md @@ -0,0 +1,40 @@ +# Contoso.WidgetManager + +## Configuration + +Testing buildState + +### Basic Information + +```yaml +openapi-type: data-plane +tag: tag-1 +``` + +### Tag: tag-1 + +These settings apply only when `--tag=tag-1` is specified on the command line. + +```yaml $(tag) == 'tag-1' +input-file: + - a.json +``` + +### Tag: tag-2 + +These settings apply only when `--tag=tag-2` is specified on the command line. + +```yaml $(tag) == 'tag-2' +input-file: + - e.json +``` + +### Tag: tag-3 + +These settings apply only when `--tag=tag-3` is specified on the command line. + +This tag has no yaml entities defined. + +```yaml $(tag) == 'tag-3' + +``` diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/shared/shared.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/shared/shared.json new file mode 100644 index 000000000000..4772308443c2 --- /dev/null +++ b/.github/shared/test/fixtures/getAffectedSwaggers/specification/1/data-plane/shared/shared.json @@ -0,0 +1,20 @@ +{ + "swagger": "2.0", + "info": { + "title": "Shared", + "version": "1.0.0" + }, + "definitions": { + "SharedThing": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "description": { + "type": "string" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/2/e.json b/.github/shared/test/fixtures/getAffectedSwaggers/specification/2/e.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/.github/shared/test/fixtures/getAffectedSwaggers/specification/empty/keep.txt b/.github/shared/test/fixtures/getAffectedSwaggers/specification/empty/keep.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/.github/shared/test/fixtures/getSpecModel/specification/common-types/resource-management/v5/types.json b/.github/shared/test/fixtures/getSpecModel/specification/common-types/resource-management/v5/types.json new file mode 100644 index 000000000000..600190811bf8 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/common-types/resource-management/v5/types.json @@ -0,0 +1,722 @@ +{ + "swagger": "2.0", + "info": { + "title": "Common types", + "version": "5.0" + }, + "paths": {}, + "definitions": { + "AzureEntityResource": { + "type": "object", + "title": "Entity Resource", + "description": "The resource model definition for an Azure Resource Manager resource with an etag.", + "properties": { + "etag": { + "type": "string", + "description": "Resource Etag.", + "readOnly": true + } + }, + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "x-ms-client-name": "AzureEntityResource" + }, + "CheckNameAvailabilityRequest": { + "type": "object", + "description": "The check availability request body.", + "properties": { + "name": { + "type": "string", + "description": "The name of the resource for which availability needs to be checked." + }, + "type": { + "type": "string", + "description": "The resource type." + } + } + }, + "CheckNameAvailabilityResponse": { + "type": "object", + "description": "The check availability result.", + "properties": { + "nameAvailable": { + "type": "boolean", + "description": "Indicates if the resource name is available." + }, + "reason": { + "type": "string", + "description": "The reason why the given name is not available.", + "enum": [ + "Invalid", + "AlreadyExists" + ], + "x-ms-enum": { + "name": "CheckNameAvailabilityReason", + "modelAsString": true + } + }, + "message": { + "type": "string", + "description": "Detailed reason why the given name is available." + } + } + }, + "ErrorAdditionalInfo": { + "type": "object", + "description": "The resource management error additional info.", + "properties": { + "type": { + "type": "string", + "description": "The additional info type.", + "readOnly": true + }, + "info": { + "type": "object", + "description": "The additional info.", + "readOnly": true + } + } + }, + "ErrorDetail": { + "type": "object", + "description": "The error detail.", + "properties": { + "code": { + "type": "string", + "description": "The error code.", + "readOnly": true + }, + "message": { + "type": "string", + "description": "The error message.", + "readOnly": true + }, + "target": { + "type": "string", + "description": "The error target.", + "readOnly": true + }, + "details": { + "type": "array", + "description": "The error details.", + "items": { + "$ref": "#/definitions/ErrorDetail" + }, + "readOnly": true, + "x-ms-identifiers": [ + "message", + "target" + ] + }, + "additionalInfo": { + "type": "array", + "description": "The error additional info.", + "items": { + "$ref": "#/definitions/ErrorAdditionalInfo" + }, + "readOnly": true, + "x-ms-identifiers": [] + } + } + }, + "ErrorResponse": { + "type": "object", + "title": "Error response", + "description": "Common error response for all Azure Resource Manager APIs to return error details for failed operations. (This also follows the OData error response format.).", + "properties": { + "error": { + "$ref": "#/definitions/ErrorDetail", + "description": "The error object." + } + } + }, + "Identity": { + "type": "object", + "description": "Identity for the resource.", + "properties": { + "principalId": { + "type": "string", + "format": "uuid", + "description": "The principal ID of resource identity. The value must be an UUID.", + "readOnly": true + }, + "tenantId": { + "type": "string", + "format": "uuid", + "description": "The tenant ID of resource. The value must be an UUID.", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The identity type.", + "enum": [ + "SystemAssigned" + ], + "x-ms-enum": { + "name": "ResourceIdentityType", + "modelAsString": false + } + } + } + }, + "KeyVaultProperties": { + "type": "object", + "properties": { + "keyIdentifier": { + "type": "string", + "description": "Key vault uri to access the encryption key." + }, + "identity": { + "type": "string", + "description": "The client ID of the identity which will be used to access key vault." + } + } + }, + "Operation": { + "type": "object", + "title": "REST API Operation", + "description": "Details of a REST API operation, returned from the Resource Provider Operations API", + "properties": { + "name": { + "type": "string", + "description": "The name of the operation, as per Resource-Based Access Control (RBAC). Examples: \"Microsoft.Compute/virtualMachines/write\", \"Microsoft.Compute/virtualMachines/capture/action\"", + "readOnly": true + }, + "isDataAction": { + "type": "boolean", + "description": "Whether the operation applies to data-plane. This is \"true\" for data-plane operations and \"false\" for ARM/control-plane operations.", + "readOnly": true + }, + "display": { + "type": "object", + "description": "Localized display information for this particular operation.", + "properties": { + "provider": { + "type": "string", + "description": "The localized friendly form of the resource provider name, e.g. \"Microsoft Monitoring Insights\" or \"Microsoft Compute\".", + "readOnly": true + }, + "resource": { + "type": "string", + "description": "The localized friendly name of the resource type related to this operation. E.g. \"Virtual Machines\" or \"Job Schedule Collections\".", + "readOnly": true + }, + "operation": { + "type": "string", + "description": "The concise, localized friendly name for the operation; suitable for dropdowns. E.g. \"Create or Update Virtual Machine\", \"Restart Virtual Machine\".", + "readOnly": true + }, + "description": { + "type": "string", + "description": "The short, localized friendly description of the operation; suitable for tool tips and detailed views.", + "readOnly": true + } + } + }, + "origin": { + "type": "string", + "description": "The intended executor of the operation; as in Resource Based Access Control (RBAC) and audit logs UX. Default value is \"user,system\"", + "enum": [ + "user", + "system", + "user,system" + ], + "x-ms-enum": { + "name": "Origin", + "modelAsString": true + }, + "readOnly": true + }, + "actionType": { + "type": "string", + "description": "Enum. Indicates the action type. \"Internal\" refers to actions that are for internal only APIs.", + "enum": [ + "Internal" + ], + "x-ms-enum": { + "name": "ActionType", + "modelAsString": true + }, + "readOnly": true + } + } + }, + "OperationListResult": { + "type": "object", + "description": "A list of REST API operations supported by an Azure Resource Provider. It contains an URL link to get the next set of results.", + "properties": { + "value": { + "type": "array", + "description": "List of operations supported by the resource provider", + "items": { + "$ref": "#/definitions/Operation" + }, + "readOnly": true, + "x-ms-identifiers": [ + "name" + ] + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "URL to get the next set of operation list results (if there are any).", + "readOnly": true + } + } + }, + "OperationStatusResult": { + "type": "object", + "description": "The current status of an async operation.", + "properties": { + "id": { + "type": "string", + "format": "arm-id", + "description": "Fully qualified ID for the async operation." + }, + "resourceId": { + "type": "string", + "format": "arm-id", + "description": "Fully qualified ID of the resource against which the original async operation was started.", + "readOnly": true + }, + "name": { + "type": "string", + "description": "Name of the async operation." + }, + "status": { + "type": "string", + "description": "Operation status." + }, + "percentComplete": { + "type": "number", + "description": "Percent of the operation that is complete.", + "minimum": 0, + "maximum": 100 + }, + "startTime": { + "type": "string", + "format": "date-time", + "description": "The start time of the operation." + }, + "endTime": { + "type": "string", + "format": "date-time", + "description": "The end time of the operation." + }, + "operations": { + "type": "array", + "description": "The operations list.", + "items": { + "$ref": "#/definitions/OperationStatusResult" + } + }, + "error": { + "$ref": "#/definitions/ErrorDetail", + "description": "If present, details of the operation error." + } + }, + "required": [ + "status" + ] + }, + "Plan": { + "type": "object", + "description": "Plan for the resource.", + "properties": { + "name": { + "type": "string", + "description": "A user defined name of the 3rd Party Artifact that is being procured." + }, + "publisher": { + "type": "string", + "description": "The publisher of the 3rd Party Artifact that is being bought. E.g. NewRelic" + }, + "product": { + "type": "string", + "description": "The 3rd Party artifact that is being procured. E.g. NewRelic. Product maps to the OfferID specified for the artifact at the time of Data Market onboarding. " + }, + "promotionCode": { + "type": "string", + "description": "A publisher provided promotion code as provisioned in Data Market for the said product/artifact." + }, + "version": { + "type": "string", + "description": "The version of the desired product/artifact." + } + }, + "required": [ + "name", + "publisher", + "product" + ] + }, + "ProxyResource": { + "type": "object", + "title": "Proxy Resource", + "description": "The resource model definition for a Azure Resource Manager proxy resource. It will not have tags and a location", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "Resource": { + "type": "object", + "title": "Resource", + "description": "Common fields that are returned in the response for all Azure Resource Manager resources", + "properties": { + "id": { + "type": "string", + "format": "arm-id", + "description": "Fully qualified resource ID for the resource. E.g. \"/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}\"", + "readOnly": true + }, + "name": { + "type": "string", + "description": "The name of the resource", + "readOnly": true + }, + "type": { + "type": "string", + "description": "The type of the resource. E.g. \"Microsoft.Compute/virtualMachines\" or \"Microsoft.Storage/storageAccounts\"", + "readOnly": true + }, + "systemData": { + "$ref": "#/definitions/systemData", + "description": "Azure Resource Manager metadata containing createdBy and modifiedBy information.", + "readOnly": true + } + }, + "x-ms-azure-resource": true + }, + "ResourceModelWithAllowedPropertySet": { + "type": "object", + "description": "The resource model definition containing the full set of allowed properties for a resource. Except properties bag, there cannot be a top level property outside of this set.", + "properties": { + "managedBy": { + "type": "string", + "description": "The fully qualified resource ID of the resource that manages this resource. Indicates if this resource is managed by another Azure resource. If this is present, complete mode deployment will not delete the resource if it is removed from the template since it is managed by another resource.", + "x-ms-mutability": [ + "read", + "create", + "update" + ] + }, + "kind": { + "type": "string", + "description": "Metadata used by portal/tooling/etc to render different UX experiences for resources of the same type. E.g. ApiApps are a kind of Microsoft.Web/sites type. If supported, the resource provider must validate and persist this value.", + "pattern": "^[-\\w\\._,\\(\\)]+$", + "x-ms-mutability": [ + "read", + "create" + ] + }, + "etag": { + "type": "string", + "description": "The etag field is *not* required. If it is provided in the response body, it must also be provided as a header per the normal etag convention. Entity tags are used for comparing two or more entities from the same requested resource. HTTP/1.1 uses entity tags in the etag (section 14.19), If-Match (section 14.24), If-None-Match (section 14.26), and If-Range (section 14.27) header fields. ", + "readOnly": true + }, + "identity": { + "allOf": [ + { + "$ref": "#/definitions/Identity" + } + ] + }, + "sku": { + "allOf": [ + { + "$ref": "#/definitions/Sku" + } + ] + }, + "plan": { + "allOf": [ + { + "$ref": "#/definitions/Plan" + } + ] + } + }, + "allOf": [ + { + "$ref": "#/definitions/TrackedResource" + } + ], + "x-ms-azure-resource": true + }, + "Sku": { + "type": "object", + "description": "The resource model definition representing SKU", + "properties": { + "name": { + "type": "string", + "description": "The name of the SKU. E.g. P3. It is typically a letter+number code" + }, + "tier": { + "$ref": "#/definitions/SkuTier" + }, + "size": { + "type": "string", + "description": "The SKU size. When the name field is the combination of tier and some other value, this would be the standalone code. " + }, + "family": { + "type": "string", + "description": "If the service has different generations of hardware, for the same SKU, then that can be captured here." + }, + "capacity": { + "type": "integer", + "format": "int32", + "description": "If the SKU supports scale out/in then the capacity integer should be included. If scale out/in is not possible for the resource this may be omitted." + } + }, + "required": [ + "name" + ] + }, + "SkuTier": { + "type": "string", + "description": "This field is required to be implemented by the Resource Provider if the service has more than one tier, but is not required on a PUT.", + "enum": [ + "Free", + "Basic", + "Standard", + "Premium" + ], + "x-ms-enum": { + "name": "SkuTier", + "modelAsString": false + } + }, + "TrackedResource": { + "type": "object", + "title": "Tracked Resource", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + }, + "x-ms-mutability": [ + "read", + "create", + "update" + ] + }, + "location": { + "type": "string", + "description": "The geo-location where the resource lives", + "x-ms-mutability": [ + "read", + "create" + ] + } + }, + "required": [ + "location" + ], + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "encryptionProperties": { + "type": "object", + "description": "Configuration of key for data encryption", + "properties": { + "status": { + "type": "string", + "description": "Indicates whether or not the encryption is enabled for container registry.", + "enum": [ + "enabled", + "disabled" + ], + "x-ms-enum": { + "name": "EncryptionStatus", + "modelAsString": true + } + }, + "keyVaultProperties": { + "$ref": "#/definitions/KeyVaultProperties", + "description": "Key vault properties." + } + } + }, + "locationData": { + "type": "object", + "description": "Metadata pertaining to the geographic location of the resource.", + "properties": { + "name": { + "type": "string", + "description": "A canonical name for the geographic or physical location.", + "maxLength": 256 + }, + "city": { + "type": "string", + "description": "The city or locality where the resource is located." + }, + "district": { + "type": "string", + "description": "The district, state, or province where the resource is located." + }, + "countryOrRegion": { + "type": "string", + "description": "The country or region where the resource is located" + } + }, + "required": [ + "name" + ] + }, + "systemData": { + "type": "object", + "description": "Metadata pertaining to creation and last modification of the resource.", + "properties": { + "createdBy": { + "type": "string", + "description": "The identity that created the resource." + }, + "createdByType": { + "type": "string", + "description": "The type of identity that created the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "createdAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp of resource creation (UTC)." + }, + "lastModifiedBy": { + "type": "string", + "description": "The identity that last modified the resource." + }, + "lastModifiedByType": { + "type": "string", + "description": "The type of identity that last modified the resource.", + "enum": [ + "User", + "Application", + "ManagedIdentity", + "Key" + ], + "x-ms-enum": { + "name": "createdByType", + "modelAsString": true + } + }, + "lastModifiedAt": { + "type": "string", + "format": "date-time", + "description": "The timestamp of resource last modification (UTC)" + } + }, + "readOnly": true + } + }, + "parameters": { + "ApiVersionParameter": { + "name": "api-version", + "in": "query", + "description": "The API version to use for this operation.", + "required": true, + "type": "string", + "minLength": 1 + }, + "If-Match": { + "name": "ifMatch", + "in": "header", + "description": "The If-Match header that makes a request conditional.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + }, + "If-None-Match": { + "name": "ifNoneMatch", + "in": "header", + "description": "The If-None-Match header that makes a request conditional.", + "required": true, + "type": "string", + "x-ms-parameter-location": "method" + }, + "LocationParameter": { + "name": "location", + "in": "path", + "description": "The name of the Azure region.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method" + }, + "ManagementGroupNameParameter": { + "name": "managementGroupName", + "in": "path", + "description": "The name of the management group. The name is case insensitive.", + "required": true, + "type": "string", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "OperationIdParameter": { + "name": "operationId", + "in": "path", + "description": "The ID of an ongoing async operation.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method" + }, + "ResourceGroupNameParameter": { + "name": "resourceGroupName", + "in": "path", + "description": "The name of the resource group. The name is case insensitive.", + "required": true, + "type": "string", + "minLength": 1, + "maxLength": 90, + "x-ms-parameter-location": "method" + }, + "ScopeParameter": { + "name": "scope", + "in": "path", + "description": "The scope at which the operation is performed.", + "required": true, + "type": "string", + "minLength": 1, + "x-ms-parameter-location": "method", + "x-ms-skip-url-encoding": true + }, + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "description": "The ID of the target subscription. The value must be an UUID.", + "required": true, + "type": "string", + "format": "uuid" + }, + "TenantIdParameter": { + "name": "tenantId", + "in": "path", + "description": "The Azure tenant ID. This is a GUID-formatted string (e.g. 00000000-0000-0000-0000-000000000000)", + "required": true, + "type": "string", + "format": "uuid", + "x-ms-parameter-location": "method" + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/data-plane/Azure.Contoso.WidgetManager/stable/2022-12-01/widgets.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/data-plane/Azure.Contoso.WidgetManager/stable/2022-12-01/widgets.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/data-plane/readme.md b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/data-plane/readme.md new file mode 100644 index 000000000000..9e353686c29f --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/data-plane/readme.md @@ -0,0 +1,85 @@ +# Contoso.WidgetManager + +> see https://aka.ms/autorest + +This is the AutoRest configuration file for Contoso.WidgetManager. + +## Configuration + +### Basic Information + +This is a TypeSpec project so we only want to readme to default the default tag and point to the outputted swagger file. +This is used for some tools such as doc generation and swagger apiview generation it isn't used for SDK code gen as we +use the native TypeSpec code generation configured in the tspconfig.yaml file. + +```yaml +openapi-type: data-plane +tag: package-2022-12-01 +``` + +### Tag: package-2022-12-01 + +These settings apply only when `--tag=package-2022-12-01` is specified on the command line. + +```yaml $(tag) == 'package-2022-12-01' +input-file: + - Azure.Contoso.WidgetManager/stable/2022-12-01/widgets.json +``` + +Define the tag twice to test code that handles duplicate tag definitions. + +```yaml $(tag) == 'package-2022-12-01' +input-file: + - Azure.Contoso.WidgetManager/stable/2022-12-01/widgets.json +``` + +### Suppress non-TypeSpec SDK related linting rules + +These set of linting rules aren't applicable to the new TypeSpec SDK code generators so suppressing them here. Eventually we will +opt-out these rules from running in the linting tools for TypeSpec generated swagger files. + +```yaml +suppressions: + - code: AvoidAnonymousTypes + - code: PatchInOperationName + - code: OperationIdNounVerb + - code: RequiredReadOnlyProperties + - code: SchemaNamesConvention + - code: SchemaDescriptionOrTitle +``` + +### Tag: package-2022-11-01-preview + +These settings apply only when `--tag=package-2022-11-01-preview` is specified on the command line. + +```yaml $(tag) == 'package-2022-11-01-preview' +input-file: + - Azure.Contoso.WidgetManager/preview/2022-11-01-preview/widgets.json +``` + +### Suppress non-TypeSpec SDK related linting rules + +These set of linting rules aren't applicable to the new TypeSpec SDK code generators so suppressing them here. Eventually we will +opt-out these rules from running in the linting tools for TypeSpec generated swagger files. + +```yaml +suppressions: + - code: AvoidAnonymousTypes + - code: PatchInOperationName + - code: OperationIdNounVerb + - code: RequiredReadOnlyProperties + - code: SchemaNamesConvention + - code: SchemaDescriptionOrTitle +``` + +### Suppress rules that might be fixed + +These set of linting rules we expect to fixed in typespec-autorest emitter but for now suppressing. +Github issue filed at https://github.com/Azure/typespec-azure/issues/2762 + +```yaml +suppressions: + - code: LroExtension + - code: SchemaTypeAndFormat + - code: PathParameterSchema +``` diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/contoso.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/contoso.json new file mode 100644 index 000000000000..c51e0e74c52f --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/contoso.json @@ -0,0 +1,556 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.Contoso management service", + "version": "2021-10-01-preview", + "description": "Microsoft.Contoso Resource Provider management API.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Employees" + } + ], + "paths": { + "/providers/Microsoft.Contoso/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Operations_List": { + "$ref": "./examples/Operations_List.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListBySubscription", + "tags": [ + "Employees" + ], + "description": "List Employee resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListBySubscription": { + "$ref": "./examples/Employees_ListBySubscription.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListByResourceGroup", + "tags": [ + "Employees" + ], + "description": "List Employee resources by resource group", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListByResourceGroup": { + "$ref": "./examples/Employees_ListByResourceGroup.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}": { + "get": { + "operationId": "Employees_Get", + "tags": [ + "Employees" + ], + "description": "Get a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Get": { + "$ref": "./examples/Employees_Get.json" + } + } + }, + "put": { + "operationId": "Employees_CreateOrUpdate", + "tags": [ + "Employees" + ], + "description": "Create a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/Employee" + } + } + ], + "responses": { + "200": { + "description": "Resource 'Employee' update operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "201": { + "description": "Resource 'Employee' create operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_CreateOrUpdate": { + "$ref": "./examples/Employees_CreateOrUpdate.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Employees_Update", + "tags": [ + "Employees" + ], + "description": "Update a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/EmployeeUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Update": { + "$ref": "./examples/Employees_Update.json" + } + } + }, + "delete": { + "operationId": "Employees_Delete", + "tags": [ + "Employees" + ], + "description": "Delete a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Delete": { + "$ref": "./examples/Employees_Delete.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.CommonTypes.TrackedResourceUpdate": { + "type": "object", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/Resource" + } + ] + }, + "Employee": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/TrackedResource" + } + ] + }, + "EmployeeListResult": { + "type": "object", + "description": "The response of a Employee list operation.", + "properties": { + "value": { + "type": "array", + "description": "The Employee items on this page", + "items": { + "$ref": "#/definitions/Employee" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "EmployeeProperties": { + "type": "object", + "description": "Employee properties", + "properties": { + "age": { + "type": "integer", + "format": "int32", + "description": "Age of employee" + }, + "city": { + "type": "string", + "description": "City of employee" + }, + "profile": { + "type": "string", + "format": "base64url", + "description": "Profile of employee" + }, + "provisioningState": { + "$ref": "#/definitions/ProvisioningState", + "description": "The status of the last operation.", + "readOnly": true + } + } + }, + "EmployeeUpdate": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.TrackedResourceUpdate" + } + ] + }, + "ProvisioningState": { + "type": "string", + "description": "The resource provisioning state.", + "enum": [ + "Succeeded", + "Failed", + "Canceled", + "Provisioning", + "Updating", + "Deleting", + "Accepted" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + }, + { + "name": "Provisioning", + "value": "Provisioning", + "description": "The resource is being provisioned" + }, + { + "name": "Updating", + "value": "Updating", + "description": "The resource is updating" + }, + { + "name": "Deleting", + "value": "Deleting", + "description": "The resource is being deleted" + }, + { + "name": "Accepted", + "value": "Accepted", + "description": "The resource create request has been accepted" + } + ] + }, + "readOnly": true + } + }, + "parameters": {} +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_CreateOrUpdate.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_CreateOrUpdate.json new file mode 100644 index 000000000000..9b34209dcd17 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_CreateOrUpdate.json @@ -0,0 +1,76 @@ +{ + "title": "Employees_CreateOrUpdate", + "operationId": "Employees_CreateOrUpdate", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "9KF-f-8b", + "resource": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl" + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + }, + "201": { + "headers": { + "Azure-AsyncOperation": "https://contoso.com/operationstatus" + }, + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/9KF-f-8b", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Delete.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Delete.json new file mode 100644 index 000000000000..9ac7910eb3f7 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Delete.json @@ -0,0 +1,19 @@ +{ + "title": "Employees_Delete", + "operationId": "Employees_Delete", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "5vX--BxSu3ux48rI4O9OQ569" + }, + "responses": { + "202": { + "headers": { + "Retry-After": 30, + "location": "https://contoso.com/operationstatus" + } + }, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Get.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Get.json new file mode 100644 index 000000000000..3ee7ff5b9c4f --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Get.json @@ -0,0 +1,37 @@ +{ + "title": "Employees_Get", + "operationId": "Employees_Get", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "le-8MU--J3W6q8D386p3-iT3" + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListByResourceGroup.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListByResourceGroup.json new file mode 100644 index 000000000000..f6512d2ba7c2 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListByResourceGroup.json @@ -0,0 +1,41 @@ +{ + "title": "Employees_ListByResourceGroup", + "operationId": "Employees_ListByResourceGroup", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListBySubscription.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListBySubscription.json new file mode 100644 index 000000000000..ffa095dd1d66 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_ListBySubscription.json @@ -0,0 +1,40 @@ +{ + "title": "Employees_ListBySubscription", + "operationId": "Employees_ListBySubscription", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Update.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Update.json new file mode 100644 index 000000000000..f3f85a465653 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Employees_Update.json @@ -0,0 +1,47 @@ +{ + "title": "Employees_Update", + "operationId": "Employees_Update", + "parameters": { + "api-version": "2021-10-01-preview", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "-XhyNJ--", + "properties": { + "tags": { + "key7952": "no" + }, + "properties": { + "age": 24, + "city": "uyfg", + "profile": "oapgijcswfkruiuuzbwco" + } + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/contoso/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Operations_List.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Operations_List.json new file mode 100644 index 000000000000..6185e205aa43 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/preview/2021-10-01-preview/examples/Operations_List.json @@ -0,0 +1,28 @@ +{ + "title": "Operations_List", + "operationId": "Operations_List", + "parameters": { + "api-version": "2021-10-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "ymeow", + "isDataAction": true, + "display": { + "provider": "qxyznq", + "resource": "bqfwkox", + "operation": "td", + "description": "yvgkhsuwartgxb" + }, + "origin": "user", + "actionType": "Internal" + } + ], + "nextLink": "https://sample.com/nextLink" + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json new file mode 100644 index 000000000000..10ffa6631f16 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json @@ -0,0 +1,556 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.Contoso management service", + "version": "2021-11-01", + "description": "Microsoft.Contoso Resource Provider management API.", + "x-typespec-generated": [ + { + "emitter": "@azure-tools/typespec-autorest" + } + ] + }, + "schemes": [ + "https" + ], + "host": "management.azure.com", + "produces": [ + "application/json" + ], + "consumes": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "description": "Azure Active Directory OAuth2 Flow.", + "flow": "implicit", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "tags": [ + { + "name": "Operations" + }, + { + "name": "Employees" + } + ], + "paths": { + "/providers/Microsoft.Contoso/operations": { + "get": { + "operationId": "Operations_List", + "tags": [ + "Operations" + ], + "description": "List the operations for the provider", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Operations_List": { + "$ref": "./examples/Operations_List.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListBySubscription", + "tags": [ + "Employees" + ], + "description": "List Employee resources by subscription ID", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListBySubscription": { + "$ref": "./examples/Employees_ListBySubscription.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees": { + "get": { + "operationId": "Employees_ListByResourceGroup", + "tags": [ + "Employees" + ], + "description": "List Employee resources by resource group", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/EmployeeListResult" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_ListByResourceGroup": { + "$ref": "./examples/Employees_ListByResourceGroup.json" + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Contoso/employees/{employeeName}": { + "get": { + "operationId": "Employees_Get", + "tags": [ + "Employees" + ], + "description": "Get a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Get": { + "$ref": "./examples/Employees_Get.json" + } + } + }, + "put": { + "operationId": "Employees_CreateOrUpdate", + "tags": [ + "Employees" + ], + "description": "Create a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "resource", + "in": "body", + "description": "Resource create parameters.", + "required": true, + "schema": { + "$ref": "#/definitions/Employee" + } + } + ], + "responses": { + "200": { + "description": "Resource 'Employee' update operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "201": { + "description": "Resource 'Employee' create operation succeeded", + "schema": { + "$ref": "#/definitions/Employee" + }, + "headers": { + "Azure-AsyncOperation": { + "type": "string", + "description": "A link to the status monitor" + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_CreateOrUpdate": { + "$ref": "./examples/Employees_CreateOrUpdate.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-long-running-operation": true + }, + "patch": { + "operationId": "Employees_Update", + "tags": [ + "Employees" + ], + "description": "Update a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + }, + { + "name": "properties", + "in": "body", + "description": "The resource properties to be updated.", + "required": true, + "schema": { + "$ref": "#/definitions/EmployeeUpdate" + } + } + ], + "responses": { + "200": { + "description": "Azure operation completed successfully.", + "schema": { + "$ref": "#/definitions/Employee" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Update": { + "$ref": "./examples/Employees_Update.json" + } + } + }, + "delete": { + "operationId": "Employees_Delete", + "tags": [ + "Employees" + ], + "description": "Delete a Employee", + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "name": "employeeName", + "in": "path", + "description": "The name of the Employee", + "required": true, + "type": "string", + "pattern": "^[a-zA-Z0-9-]{3,24}$" + } + ], + "responses": { + "202": { + "description": "Resource deletion accepted.", + "headers": { + "Location": { + "type": "string", + "description": "The Location header contains the URL where the status of the long running operation can be checked." + }, + "Retry-After": { + "type": "integer", + "format": "int32", + "description": "The Retry-After header can indicate how long the client should wait before polling the operation status." + } + } + }, + "204": { + "description": "Resource does not exist." + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-examples": { + "Employees_Delete": { + "$ref": "./examples/Employees_Delete.json" + } + }, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-long-running-operation": true + } + } + }, + "definitions": { + "Azure.ResourceManager.CommonTypes.TrackedResourceUpdate": { + "type": "object", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'", + "properties": { + "tags": { + "type": "object", + "description": "Resource tags.", + "additionalProperties": { + "type": "string" + } + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/Resource" + } + ] + }, + "Employee": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v5/types.json#/definitions/TrackedResource" + } + ] + }, + "EmployeeListResult": { + "type": "object", + "description": "The response of a Employee list operation.", + "properties": { + "value": { + "type": "array", + "description": "The Employee items on this page", + "items": { + "$ref": "#/definitions/Employee" + } + }, + "nextLink": { + "type": "string", + "format": "uri", + "description": "The link to the next page of items" + } + }, + "required": [ + "value" + ] + }, + "EmployeeProperties": { + "type": "object", + "description": "Employee properties", + "properties": { + "age": { + "type": "integer", + "format": "int32", + "description": "Age of employee" + }, + "city": { + "type": "string", + "description": "City of employee" + }, + "profile": { + "type": "string", + "format": "base64url", + "description": "Profile of employee" + }, + "provisioningState": { + "$ref": "#/definitions/ProvisioningState", + "description": "The status of the last operation.", + "readOnly": true + } + } + }, + "EmployeeUpdate": { + "type": "object", + "description": "Employee resource", + "properties": { + "properties": { + "$ref": "#/definitions/EmployeeProperties", + "description": "The resource-specific properties for this resource." + } + }, + "allOf": [ + { + "$ref": "#/definitions/Azure.ResourceManager.CommonTypes.TrackedResourceUpdate" + } + ] + }, + "ProvisioningState": { + "type": "string", + "description": "The resource provisioning state.", + "enum": [ + "Succeeded", + "Failed", + "Canceled", + "Provisioning", + "Updating", + "Deleting", + "Accepted" + ], + "x-ms-enum": { + "name": "ProvisioningState", + "modelAsString": true, + "values": [ + { + "name": "Succeeded", + "value": "Succeeded", + "description": "Resource has been created." + }, + { + "name": "Failed", + "value": "Failed", + "description": "Resource creation failed." + }, + { + "name": "Canceled", + "value": "Canceled", + "description": "Resource creation was canceled." + }, + { + "name": "Provisioning", + "value": "Provisioning", + "description": "The resource is being provisioned" + }, + { + "name": "Updating", + "value": "Updating", + "description": "The resource is updating" + }, + { + "name": "Deleting", + "value": "Deleting", + "description": "The resource is being deleted" + }, + { + "name": "Accepted", + "value": "Accepted", + "description": "The resource create request has been accepted" + } + ] + }, + "readOnly": true + } + }, + "parameters": {} +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_CreateOrUpdate.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_CreateOrUpdate.json new file mode 100644 index 000000000000..4a13a329e3b8 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_CreateOrUpdate.json @@ -0,0 +1,76 @@ +{ + "title": "Employees_CreateOrUpdate", + "operationId": "Employees_CreateOrUpdate", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "9KF-f-8b", + "resource": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl" + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + }, + "201": { + "headers": { + "Azure-AsyncOperation": "https://contoso.com/operationstatus" + }, + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/9KF-f-8b", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Delete.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Delete.json new file mode 100644 index 000000000000..15176d86b029 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Delete.json @@ -0,0 +1,19 @@ +{ + "title": "Employees_Delete", + "operationId": "Employees_Delete", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "5vX--BxSu3ux48rI4O9OQ569" + }, + "responses": { + "202": { + "headers": { + "Retry-After": 30, + "location": "https://contoso.com/operationstatus" + } + }, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json new file mode 100644 index 000000000000..eb1917859e24 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Get.json @@ -0,0 +1,37 @@ +{ + "title": "Employees_Get", + "operationId": "Employees_Get", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "le-8MU--J3W6q8D386p3-iT3" + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/le-8MU--J3W6q8D386p3-iT3", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListByResourceGroup.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListByResourceGroup.json new file mode 100644 index 000000000000..860fab85a9b8 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListByResourceGroup.json @@ -0,0 +1,41 @@ +{ + "title": "Employees_ListByResourceGroup", + "operationId": "Employees_ListByResourceGroup", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListBySubscription.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListBySubscription.json new file mode 100644 index 000000000000..18432d58de37 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_ListBySubscription.json @@ -0,0 +1,40 @@ +{ + "title": "Employees_ListBySubscription", + "operationId": "Employees_ListBySubscription", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/rgopenapi/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + ], + "nextLink": "https://microsoft.com/a" + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Update.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Update.json new file mode 100644 index 000000000000..de46fc8ef2e8 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Employees_Update.json @@ -0,0 +1,47 @@ +{ + "title": "Employees_Update", + "operationId": "Employees_Update", + "parameters": { + "api-version": "2021-11-01", + "subscriptionId": "11809CA1-E126-4017-945E-AA795CD5C5A9", + "resourceGroupName": "rgopenapi", + "employeeName": "-XhyNJ--", + "properties": { + "tags": { + "key7952": "no" + }, + "properties": { + "age": 24, + "city": "uyfg", + "profile": "oapgijcswfkruiuuzbwco" + } + } + }, + "responses": { + "200": { + "body": { + "properties": { + "age": 30, + "city": "gydhnntudughbmxlkyzrskcdkotrxn", + "profile": "ms", + "provisioningState": "Succeeded" + }, + "tags": { + "key2913": "urperxmkkhhkp" + }, + "location": "itajgxyqozseoygnl", + "id": "/subscriptions/11809CA1-E126-4017-945E-AA795CD5C5A9/resourceGroups/contoso/providers/Microsoft.Contoso/employees/test", + "name": "xepyxhpb", + "type": "svvamxrdnnv", + "systemData": { + "createdBy": "iewyxsnriqktsvp", + "createdByType": "User", + "createdAt": "2023-05-19T00:28:48.610Z", + "lastModifiedBy": "xrchbnnuzierzpxw", + "lastModifiedByType": "User", + "lastModifiedAt": "2023-05-19T00:28:48.610Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Operations_List.json b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Operations_List.json new file mode 100644 index 000000000000..4d74e755c020 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/Microsoft.Contoso/stable/2021-11-01/examples/Operations_List.json @@ -0,0 +1,28 @@ +{ + "title": "Operations_List", + "operationId": "Operations_List", + "parameters": { + "api-version": "2021-11-01" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "ymeow", + "isDataAction": true, + "display": { + "provider": "qxyznq", + "resource": "bqfwkox", + "operation": "td", + "description": "yvgkhsuwartgxb" + }, + "origin": "user", + "actionType": "Internal" + } + ], + "nextLink": "https://sample.com/nextLink" + } + } + } +} diff --git a/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/readme.md b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/readme.md new file mode 100644 index 000000000000..3fa08c28758f --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager/readme.md @@ -0,0 +1,78 @@ +# containerstorage + +> see https://aka.ms/autorest +This is the AutoRest configuration file for Contoso. + +## Getting Started + +To build the SDKs for My API, simply install AutoRest via `npm` (`npm install -g autorest`) and then run: + +> `autorest readme.md` +To see additional help and options, run: + +> `autorest --help` +For other options on installation see [Installing AutoRest](https://aka.ms/autorest/install) on the AutoRest github page. + +--- + +## Configuration + +### Basic Information + +These are the global settings for the containerstorage. + +```yaml +openapi-type: arm +openapi-subtype: rpaas +tag: package-2021-11-01 +``` + +### Tag: package-2021-11-01 + +These settings apply only when `--tag=package-2021-11-01` is specified on the command line. + +`$(this-folder)` points to the folder where the readme.md file is located. It +may be used in some specs. In those cases, it can effectively be treated as "." +because the values in input-files are already relative to the current readme.md +file. + +Some files may also have a backslash in the path. Path separators should be +forward slashes, but backslash is supported. + +```yaml $(tag) == 'package-2021-11-01' +input-file: + - $(this-folder)/Microsoft.Contoso/stable/2021-11-01\contoso.json +``` + +### Tag: package-2021-10-01-preview + +These settings apply only when `--tag=package-2021-10-01-preview` is specified on the command line. + +input-file can be a single file or an array of files. Test the single value +scenario. + +```yaml $(tag) == 'package-2021-10-01-preview' +input-file: Microsoft.Contoso/preview/2021-10-01-preview/contoso.json +``` + +### Tag: empty-properties + +This tag has no yaml entities defined and is intended to test parser scenarios +around empty properties. + +``` yaml $(tag) == 'empty-properties' + +``` + +### Tag: no-input-files + +This tag has no input-files and is intended to test parser scenarios around no +input-files. + +``` yaml $(tag) == 'no-input-files' +some-thing: + - some-thing-1 + - some-thing-2 +``` + +--- diff --git a/.github/shared/test/fixtures/getSpecModel/specification/multi-readme/a/readme.md b/.github/shared/test/fixtures/getSpecModel/specification/multi-readme/a/readme.md new file mode 100644 index 000000000000..46d32defb15b --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/multi-readme/a/readme.md @@ -0,0 +1,7 @@ +# Service A + +## Configuration + +```yaml +openapi-type: data-plane +``` diff --git a/.github/shared/test/fixtures/getSpecModel/specification/multi-readme/b/readme.md b/.github/shared/test/fixtures/getSpecModel/specification/multi-readme/b/readme.md new file mode 100644 index 000000000000..968902b1a5fb --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/multi-readme/b/readme.md @@ -0,0 +1,7 @@ +# Service B + +## Configuration + +```yaml +openapi-type: data-plane +``` diff --git a/.github/shared/test/fixtures/getSpecModel/specification/yaml-date-parsing/readme.md b/.github/shared/test/fixtures/getSpecModel/specification/yaml-date-parsing/readme.md new file mode 100644 index 000000000000..b192c9dcd763 --- /dev/null +++ b/.github/shared/test/fixtures/getSpecModel/specification/yaml-date-parsing/readme.md @@ -0,0 +1,29 @@ +# Test date parsing in YAML decoding + +> see https://aka.ms/autorest + +This is the AutoRest configuration file for Contoso.WidgetManager. + +## Configuration + +### Basic Information + +Use a date-only string (leading or following qualifiers like "package", "preview", etc.). The YAML parser should +parse this as a string and not a Date. + +```yaml +openapi-type: data-plane +tag: 2022-12-01 +``` + +### Tag: 2022-12-01 + +These settings apply only when `--tag=package-2022-12-01` is specified on the command line. + +```yaml $(tag) == '2022-12-01' +``` + +### Tag: package-2022-12-01 + +```yaml $(tag) == 'package-2022-12-01' +``` \ No newline at end of file diff --git a/.github/shared/test/fixtures/swagger/ignoreExamples/examples/example.json b/.github/shared/test/fixtures/swagger/ignoreExamples/examples/example.json new file mode 100644 index 000000000000..05a1d7a8679e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/ignoreExamples/examples/example.json @@ -0,0 +1,6 @@ +{ + "value": { + "id": "123", + "name": "Sample Item" + } +} diff --git a/.github/shared/test/fixtures/swagger/ignoreExamples/included.json b/.github/shared/test/fixtures/swagger/ignoreExamples/included.json new file mode 100644 index 000000000000..8c15c9f184f7 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/ignoreExamples/included.json @@ -0,0 +1,22 @@ +{ + "swagger": "2.0", + "info": { + "title": "Item Model", + "version": "1.0.0" + }, + "paths": {}, + "definitions": { + "Item": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": ["id", "name"] + } + } +} diff --git a/.github/shared/test/fixtures/swagger/ignoreExamples/swagger.json b/.github/shared/test/fixtures/swagger/ignoreExamples/swagger.json new file mode 100644 index 000000000000..392038166343 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/ignoreExamples/swagger.json @@ -0,0 +1,27 @@ +{ + "swagger": "2.0", + "info": { + "title": "Test Fixture API", + "version": "1.0.0" + }, + "paths": { + "/item": { + "get": { + "summary": "Get an item", + "responses": { + "200": { + "description": "Successful response", + "schema": { + "$ref": "included.json#/definitions/Item" + }, + "examples": { + "application/json": { + "$ref": "examples/example.json" + } + } + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/common-types/resource-management/v2/types.json b/.github/shared/test/fixtures/swagger/specification/common-types/resource-management/v2/types.json new file mode 100644 index 000000000000..31f4bcaf80de --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/common-types/resource-management/v2/types.json @@ -0,0 +1,26 @@ +{ + "swagger": "2.0", + "info": { + "title": "Common Types", + "version": "v2" + }, + "definitions": { + "Resource": { + "type": "object", + "properties": { + "id": { + "type": "string", + "readOnly": true + }, + "name": { + "type": "string", + "readOnly": true + }, + "type": { + "type": "string", + "readOnly": true + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/common-types/resource-management/v3/types.json b/.github/shared/test/fixtures/swagger/specification/common-types/resource-management/v3/types.json new file mode 100644 index 000000000000..6d1a88e373f2 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/common-types/resource-management/v3/types.json @@ -0,0 +1,69 @@ +{ + "swagger": "2.0", + "info": { + "title": "Common Types - Resource Management", + "version": "v3", + "description": "Common types for resource management APIs" + }, + "host": "management.azure.com", + "schemes": ["https"], + "consumes": ["application/json"], + "produces": ["application/json"], + "definitions": { + "Resource": { + "type": "object", + "description": "Common fields that are returned in the response for all Azure Resource Manager resources", + "properties": { + "id": { + "readOnly": true, + "type": "string", + "description": "Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}" + }, + "name": { + "readOnly": true, + "type": "string", + "description": "The name of the resource" + }, + "type": { + "readOnly": true, + "type": "string", + "description": "The type of the resource. E.g. \"Microsoft.Compute/virtualMachines\" or \"Microsoft.Storage/storageAccounts\"" + } + } + }, + "ProxyResource": { + "type": "object", + "description": "The resource model definition for a Azure Resource Manager proxy resource.", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ] + }, + "TrackedResource": { + "type": "object", + "description": "The resource model definition for an Azure Resource Manager tracked top level resource", + "allOf": [ + { + "$ref": "#/definitions/Resource" + } + ], + "properties": { + "tags": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Resource tags." + }, + "location": { + "type": "string", + "description": "The geo-location where the resource lives" + } + }, + "required": [ + "location" + ] + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConfigurationNamesList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConfigurationNamesList.json new file mode 100644 index 000000000000..5bc65903c540 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConfigurationNamesList.json @@ -0,0 +1,52 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "targetService": "MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES", + "clientType": "none", + "authType": "systemAssignedIdentity", + "names": [ + { + "value": "AZURE_APPCONFIGURATION_ENDPOINT", + "description": "App configuration endpoint" + }, + { + "value": "AZURE_APPCONFIGURATION_SCOPE", + "description": "The scopes required for the token." + } + ] + } + }, + { + "properties": { + "targetService": "MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES", + "clientType": "none", + "authType": "userAssignedIdentity", + "names": [ + { + "value": "AZURE_APPCONFIGURATION_ENDPOINT", + "description": "App configuration endpoint" + }, + { + "value": "AZURE_APPCONFIGURATION_CLIENTID", + "description": "The client(application) ID of the user identity." + }, + { + "value": "AZURE_APPCONFIGURATION_SCOPE", + "description": "The scopes required for getting token." + } + ] + } + } + ], + "nextLink": null + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunCreate.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunCreate.json new file mode 100644 index 000000000000..124a0c574565 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunCreate.json @@ -0,0 +1,116 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "201": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Accepted" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunDelete.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunDelete.json new file mode 100644 index 000000000000..2ee66585cb7e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunDelete.json @@ -0,0 +1,13 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName" + }, + "responses": { + "200": {}, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunGet.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunGet.json new file mode 100644 index 000000000000..92f012ac8137 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunGet.json @@ -0,0 +1,33 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName" + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunList.json new file mode 100644 index 000000000000..4b2fdc4baa66 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunList.json @@ -0,0 +1,36 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunUpdate.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunUpdate.json new file mode 100644 index 000000000000..8267626fd374 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorDryrunUpdate.json @@ -0,0 +1,78 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorList.json new file mode 100644 index 000000000000..b5664c15c000 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ConnectorList.json @@ -0,0 +1,34 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/linkers/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/devConnectors", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/Connectors.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/Connectors.json new file mode 100644 index 000000000000..4cfeb7d61b2f --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/Connectors.json @@ -0,0 +1,43 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/devConnnectors/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/devConnectors", + "properties": { + "authInfo": { + "authType": "systemAssignedIdentity", + "roles": [ + "customizedOwner" + ] + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "publicNetworkSolution": { + "firewallRules": { + "ipRanges": [ + "182.22.120" + ], + "callerClientIP": "true" + }, + "action": "enable", + "deleteOrUpdateBehavior": "ForcedCleanup" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteConnector.json new file mode 100644 index 000000000000..f0340dfb4dfb --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteConnector.json @@ -0,0 +1,18 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": {}, + "204": {}, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteDryrun.json new file mode 100644 index 000000000000..b406311af609 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteDryrun.json @@ -0,0 +1,11 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName" + }, + "responses": { + "200": {}, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteLinker.json new file mode 100644 index 000000000000..c49d99a9b09e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/DeleteLinker.json @@ -0,0 +1,16 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": {}, + "204": {}, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GenerateConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GenerateConfigurations.json new file mode 100644 index 000000000000..3e367d73b9a3 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GenerateConfigurations.json @@ -0,0 +1,26 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "customizedKeys": { + "ASL_DocumentDb_ConnectionString": "MyConnectionstring" + } + } + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "MyConnectionstring", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetConfigurations.json new file mode 100644 index 000000000000..00908c92a5b5 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetConfigurations.json @@ -0,0 +1,41 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.App/containerApps/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "AZURE_POSTGRESQL_HOST", + "value": "Host", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_USER", + "value": "Username", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_DATABASE", + "value": "DatabaseName", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_PORT", + "value": "Port", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_PASSWORD", + "value": "SecretUri", + "configType": "KeyVaultSecret", + "keyVaultReferenceIdentity": "system" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetDaprConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetDaprConfigurations.json new file mode 100644 index 000000000000..5b6bbc3d51d4 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetDaprConfigurations.json @@ -0,0 +1,33 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "targetType": "MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES", + "authType": "secret", + "daprProperties": { + "version": "v1", + "componentType": "bindings", + "runtimeVersion": "1.10", + "bindingComponentDirection": "input", + "metadata": [ + { + "name": "containerName", + "description": "The name of the container to be used for Dapr state.", + "required": "true" + } + ] + } + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetDryrun.json new file mode 100644 index 000000000000..8a5d7404edd0 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/GetDryrun.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "name": "dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/Linker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/Linker.json new file mode 100644 index 000000000000..87ae58c108aa --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/Linker.json @@ -0,0 +1,47 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/kvname" + }, + "scope": "AKS-Namespace", + "clientType": "dotnet", + "publicNetworkSolution": { + "action": "enable" + }, + "configurationInfo": { + "deleteOrUpdateBehavior": "ForcedCleanup", + "customizedKeys": { + "AZURE_MYSQL_CONNECTIONSTRING": "myConnectionstring", + "AZURE_MYSQL_SSLMODE": "mySslmode" + }, + "additionalConfigurations": { + "throttlingLimit": "100" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/LinkerGenerateConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/LinkerGenerateConfigurations.json new file mode 100644 index 000000000000..d21e946f8ec3 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/LinkerGenerateConfigurations.json @@ -0,0 +1,24 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "customizedKeys": { + "ASL_DocumentDb_ConnectionString": "MyConnectionstring" + } + } + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "MyConnectionstring", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/LinkerList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/LinkerList.json new file mode 100644 index 000000000000..afffd7662e19 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/LinkerList.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ListDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ListDryrun.json new file mode 100644 index 000000000000..b4dda3dac29e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ListDryrun.json @@ -0,0 +1,35 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "name": "dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/OperationsList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/OperationsList.json new file mode 100644 index 000000000000..5dee50b01147 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/OperationsList.json @@ -0,0 +1,184 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "display": { + "description": "Register the subscription for Microsoft.ServiceLinker", + "operation": "Register the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/register/action" + }, + { + "display": { + "description": "Unregister the subscription for Microsoft.ServiceLinker", + "operation": "Unregister the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/unregister/action" + }, + { + "display": { + "description": "read operations", + "operation": "read_operations", + "provider": "Microsoft.ServiceLinker", + "resource": "operations" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/operations/read" + }, + { + "display": { + "description": "list dryrun jobs", + "operation": "Dryrun_List", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "get a dryrun job", + "operation": "Dryrun_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "create a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Create", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "delete a dryrun job", + "operation": "Dryrun_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/delete" + }, + { + "display": { + "description": "add a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "read operationStatuses", + "operation": "read_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/read" + }, + { + "display": { + "description": "write operationStatuses", + "operation": "write_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/write" + }, + { + "display": { + "description": "Returns list of Linkers which connects to the resource.", + "operation": "Linker_List", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Returns Linker resource for a given name.", + "operation": "Linker_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Create or update linker resource.", + "operation": "Linker_CreateOrUpdate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Delete a link.", + "operation": "Linker_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/delete" + }, + { + "display": { + "description": "Operation to update an existing link.", + "operation": "Linker_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Validate a link.", + "operation": "Linker_Validate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/validateLinker/action" + }, + { + "display": { + "description": "list source configurations for a linker.", + "operation": "Linker_ListConfigurations", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/listConfigurations/action" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchConnector.json new file mode 100644 index 000000000000..6cbf8bacfe26 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchConnector.json @@ -0,0 +1,64 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "202": { + "headers": { + "azure-asyncoperation": "http://azure.async.operation/status" + }, + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchDryrun.json new file mode 100644 index 000000000000..868435b29b8f --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchDryrun.json @@ -0,0 +1,77 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchLinker.json new file mode 100644 index 000000000000..dfe22733c45d --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PatchLinker.json @@ -0,0 +1,59 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutConnector.json new file mode 100644 index 000000000000..8d4cc02c8405 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutConnector.json @@ -0,0 +1,63 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutDryrun.json new file mode 100644 index 000000000000..3e83a7728c7a --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutDryrun.json @@ -0,0 +1,116 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Updating" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutLinker.json new file mode 100644 index 000000000000..eff0bfb84fe1 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/PutLinker.json @@ -0,0 +1,68 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + }, + "responses": { + "200": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + }, + "201": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ValidateConnectorSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ValidateConnectorSuccess.json new file mode 100644 index 000000000000..a7efdadedfb8 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ValidateConnectorSuccess.json @@ -0,0 +1,38 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": { + "body": { + "properties": { + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ValidateLinkerSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ValidateLinkerSuccess.json new file mode 100644 index 000000000000..85ec6c34a5d9 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/examples/ValidateLinkerSuccess.json @@ -0,0 +1,38 @@ +{ + "parameters": { + "api-version": "2023-04-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "properties": { + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "sourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "targetId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/servicelinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/servicelinker.json new file mode 100644 index 000000000000..c4cbc1dd94ac --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/servicelinker.json @@ -0,0 +1,2902 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.ServiceLinker", + "description": "Microsoft.ServiceLinker provider", + "version": "2023-04-01-preview" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow.", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ConnectorDryrunList": { + "$ref": "./examples/ConnectorDryrunList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "ConnectorDryrunGet": { + "$ref": "./examples/ConnectorDryrunGet.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "Connector" + ], + "operationId": "Connector_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunCreate": { + "$ref": "./examples/ConnectorDryrunCreate.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "201": { + "description": "Long running operation", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Connector" + ], + "operationId": "Connector_UpdateDryrun", + "description": "update a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunUpdate": { + "$ref": "./examples/ConnectorDryrunUpdate.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunPatch" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Connector" + ], + "operationId": "Connector_DeleteDryrun", + "description": "delete a dryrun job", + "x-ms-examples": { + "ConnectorDryrunDelete": { + "$ref": "./examples/ConnectorDryrunDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The job is deleted." + }, + "204": { + "description": "Deleted. The job is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors": { + "get": { + "deprecated": false, + "description": "Returns list of connector which connects to the resource, which supports to config the target service during the resource provision.", + "operationId": "Connector_List", + "x-ms-examples": { + "ConnectorList": { + "$ref": "./examples/ConnectorList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Connector details.", + "schema": { + "$ref": "#/definitions/ResourceList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}": { + "get": { + "description": "Returns Connector resource for a given name.", + "operationId": "Connector_Get", + "x-ms-examples": { + "Connector": { + "$ref": "./examples/Connectors.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Connector details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update Connector resource.", + "operationId": "Connector_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutConnector": { + "$ref": "./examples/PutConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connector details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a Connector.", + "x-ms-examples": { + "DeleteConnector": { + "$ref": "./examples/DeleteConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The Connector is deleted." + }, + "202": { + "description": "Long running operation." + }, + "204": { + "description": "Deleted. The Connector is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Update", + "description": "Operation to update an existing Connector.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchConnector": { + "$ref": "./examples/PatchConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connector details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a Connector.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "202": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}/validate": { + "post": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Validate", + "description": "Validate a Connector.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-examples": { + "ValidateConnectorSuccess": { + "$ref": "./examples/ValidateConnectorSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}/generateConfigurations": { + "post": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GenerateConfigurations", + "description": "Generate configurations for a Connector.", + "x-ms-examples": { + "GenerateConfiguration": { + "$ref": "./examples/GenerateConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connection Info, including format, secret store, etc", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ConfigurationInfo" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers": { + "get": { + "deprecated": false, + "description": "Returns list of Linkers which connects to the resource. which supports to config both application and target service during the resource provision.", + "operationId": "Linker_List", + "x-ms-examples": { + "LinkerList": { + "$ref": "./examples/LinkerList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/ResourceList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}": { + "get": { + "description": "Returns Linker resource for a given name.", + "operationId": "Linker_Get", + "x-ms-examples": { + "Linker": { + "$ref": "./examples/Linker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update Linker resource.", + "operationId": "Linker_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutLinker": { + "$ref": "./examples/PutLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a Linker.", + "x-ms-examples": { + "DeleteLinker": { + "$ref": "./examples/DeleteLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The Linker is deleted." + }, + "202": { + "description": "Long running operation." + }, + "204": { + "description": "Deleted. The Linker is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Update", + "description": "Operation to update an existing Linker.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchLinker": { + "$ref": "./examples/PatchLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a Linker.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/validateLinker": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Validate", + "description": "Validate a Linker.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-examples": { + "ValidateLinkerSuccess": { + "$ref": "./examples/ValidateLinkerSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/listConfigurations": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_ListConfigurations", + "description": "list source configurations for a Linker.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/GetConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/dryruns": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ListDryrun": { + "$ref": "./examples/ListDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "GetDryrun": { + "$ref": "./examples/GetDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutDryrun": { + "$ref": "./examples/PutDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "201": { + "description": "Long running operation", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_UpdateDryrun", + "description": "add a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchDryrun": { + "$ref": "./examples/PatchDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunPatch" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_DeleteDryrun", + "description": "delete a dryrun job", + "x-ms-examples": { + "DeleteDryrun": { + "$ref": "./examples/DeleteDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The job is deleted." + }, + "204": { + "description": "Deleted. The job is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/generateConfigurations": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_GenerateConfigurations", + "description": "Generate configurations for a Linker.", + "x-ms-examples": { + "GenerateConfiguration": { + "$ref": "./examples/LinkerGenerateConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Connection Info, including format, secret store, etc", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ConfigurationInfo" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/providers/Microsoft.ServiceLinker/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "description": "Lists the available ServiceLinker REST API operations.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/OperationsList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/providers/Microsoft.ServiceLinker/configurationNames": { + "get": { + "tags": [ + "ConfigurationNames" + ], + "operationId": "ConfigurationNames_List", + "description": "Lists the configuration names generated by Service Connector for all target, client types, auth types.", + "x-ms-examples": { + "GetConfigurationNames": { + "$ref": "./examples/ConfigurationNamesList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "$filter", + "in": "query", + "required": false, + "type": "string", + "description": "OData filter options." + }, + { + "name": "$skipToken", + "in": "query", + "required": false, + "type": "string", + "description": "OData skipToken option for pagination." + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationNameResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/daprConfigurations": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_ListDaprConfigurations", + "description": "List the dapr configuration supported by Service Connector.", + "x-ms-examples": { + "GetDaprConfigurations": { + "$ref": "./examples/GetDaprConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DaprConfigurationList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "TargetServiceType": { + "description": "The target service type.", + "type": "string", + "enum": [ + "AzureResource", + "ConfluentBootstrapServer", + "ConfluentSchemaRegistry", + "SelfHostedServer" + ], + "x-ms-enum": { + "name": "targetServiceType", + "modelAsString": true + } + }, + "TargetServiceBase": { + "description": "The target service properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The target service type.", + "$ref": "#/definitions/TargetServiceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResourceType": { + "description": "The azure resource type.", + "type": "string", + "enum": [ + "KeyVault" + ], + "x-ms-enum": { + "name": "azureResourceType", + "modelAsString": true + } + }, + "AzureResourcePropertiesBase": { + "description": "The azure resource properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The azure resource type.", + "$ref": "#/definitions/AzureResourceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResource": { + "x-ms-discriminator-value": "AzureResource", + "type": "object", + "description": "The azure resource info when target service type is AzureResource", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "id": { + "description": "The Id of azure resource.", + "type": "string" + }, + "resourceProperties": { + "x-nullable": true, + "description": "The azure resource connection related properties.", + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + } + }, + "AzureKeyVaultProperties": { + "x-ms-discriminator-value": "KeyVault", + "type": "object", + "description": "The resource properties when type is Azure Key Vault", + "allOf": [ + { + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + ], + "properties": { + "connectAsKubernetesCsiDriver": { + "x-nullable": true, + "description": "True if connect via Kubernetes CSI Driver.", + "type": "boolean" + } + } + }, + "ConfluentBootstrapServer": { + "x-ms-discriminator-value": "ConfluentBootstrapServer", + "type": "object", + "description": "The service properties when target service type is ConfluentBootstrapServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "SelfHostedServer": { + "x-ms-discriminator-value": "SelfHostedServer", + "type": "object", + "description": "The service properties when target service type is SelfHostedServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "ConfluentSchemaRegistry": { + "x-ms-discriminator-value": "ConfluentSchemaRegistry", + "type": "object", + "description": "The service properties when target service type is ConfluentSchemaRegistry", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "DeleteOrUpdateBehavior": { + "description": "The cleanup behavior to indicate whether clean up operation when resource is deleted or updated", + "type": "string", + "enum": [ + "Default", + "ForcedCleanup" + ], + "x-ms-enum": { + "name": "DeleteOrUpdateBehavior", + "modelAsString": true + } + }, + "ClientType": { + "description": "The application client type", + "type": "string", + "enum": [ + "none", + "dotnet", + "java", + "python", + "go", + "php", + "ruby", + "django", + "nodejs", + "springBoot", + "kafka-springBoot", + "jms-springBoot", + "dapr" + ], + "x-ms-enum": { + "name": "clientType", + "modelAsString": true + } + }, + "AuthType": { + "description": "The authentication type.", + "type": "string", + "enum": [ + "systemAssignedIdentity", + "userAssignedIdentity", + "servicePrincipalSecret", + "servicePrincipalCertificate", + "secret", + "accessKey", + "userAccount", + "easyAuthMicrosoftEntraID" + ], + "x-ms-enum": { + "name": "AuthType", + "modelAsString": true + } + }, + "SecretType": { + "description": "The secret type.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecretUri", + "keyVaultSecretReference" + ], + "x-ms-enum": { + "name": "SecretType", + "modelAsString": true + } + }, + "SecretSourceType": { + "description": "The type of secret source.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecret" + ], + "x-ms-enum": { + "name": "SecretSourceType", + "modelAsString": true + } + }, + "SecretInfoBase": { + "description": "The secret info", + "discriminator": "secretType", + "type": "object", + "properties": { + "secretType": { + "description": "The secret type.", + "$ref": "#/definitions/SecretType" + } + }, + "required": [ + "secretType" + ] + }, + "ValueSecretInfo": { + "x-ms-discriminator-value": "rawValue", + "type": "object", + "description": "The secret info when type is rawValue. It's for scenarios that user input the secret.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "x-nullable": true, + "description": "The actual value of the secret.", + "type": "string", + "x-ms-secret": true + } + } + }, + "KeyVaultSecretReferenceSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretReference", + "type": "object", + "description": "The secret info when type is keyVaultSecretReference. It's for scenario that user provides a secret stored in user's keyvault and source is Azure Kubernetes. The key Vault's resource id is linked to secretStore.keyVaultId.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "name": { + "description": "Name of the Key Vault secret.", + "type": "string" + }, + "version": { + "x-nullable": true, + "description": "Version of the Key Vault secret.", + "type": "string" + } + } + }, + "KeyVaultSecretUriSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretUri", + "type": "object", + "description": "The secret info when type is keyVaultSecretUri. It's for scenario that user provides a secret stored in user's keyvault and source is Web App, Spring Cloud or Container App.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "description": "URI to the keyvault secret", + "type": "string" + } + } + }, + "AuthInfoBase": { + "description": "The authentication info", + "discriminator": "authType", + "type": "object", + "properties": { + "authType": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "authMode": { + "description": "Optional. Indicates how to configure authentication. If optInAllAuth, service linker configures authentication such as enabling identity on source resource and granting RBAC roles. If optOutAllAuth, opt out authentication setup. Default is optInAllAuth.", + "$ref": "#/definitions/AuthMode" + } + }, + "required": [ + "authType" + ] + }, + "AccessKeyInfoBase": { + "description": "The access key directly from target resource properties, which target service is Azure Resource, such as Microsoft.Storage", + "x-ms-discriminator-value": "accessKey", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "permissions": { + "description": "Permissions of the accessKey. `Read` and `Write` are for Azure Cosmos DB and Azure App Configuration, `Listen`, `Send` and `Manage` are for Azure Event Hub and Azure Service Bus.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "Read", + "Write", + "Listen", + "Send", + "Manage" + ], + "x-ms-enum": { + "name": "accessKeyPermissions", + "modelAsString": true + } + } + } + } + }, + "DatabaseAadAuthInfo": { + "description": "The extra auth info required by Database AAD authentication.", + "type": "object", + "properties": { + "userName": { + "x-nullable": true, + "description": "Username created in the database which is mapped to a user in AAD.", + "type": "string" + } + } + }, + "SecretAuthInfo": { + "x-ms-discriminator-value": "secret", + "type": "object", + "description": "The authentication info when authType is secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "name": { + "x-nullable": true, + "description": "Username or account name for secret auth.", + "type": "string" + }, + "secretInfo": { + "x-nullable": true, + "description": "Password or key vault secret for secret auth.", + "$ref": "#/definitions/SecretInfoBase" + } + } + }, + "UserAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "userAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is userAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "clientId": { + "description": "Client Id for userAssignedIdentity.", + "type": "string" + }, + "subscriptionId": { + "description": "Subscription id for userAssignedIdentity.", + "type": "string" + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure role to be assigned" + } + } + }, + "SystemAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "systemAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is systemAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure role to be assigned" + } + } + }, + "ServicePrincipalSecretAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalSecret", + "type": "object", + "description": "The authentication info when authType is servicePrincipal secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "clientId": { + "description": "ServicePrincipal application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "secret": { + "description": "Secret for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + }, + "required": [ + "clientId", + "principalId", + "secret" + ] + }, + "ServicePrincipalCertificateAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalCertificate", + "type": "object", + "description": "The authentication info when authType is servicePrincipal certificate", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "certificate": { + "description": "ServicePrincipal certificate for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + }, + "required": [ + "clientId", + "principalId", + "certificate" + ] + }, + "UserAccountAuthInfo": { + "x-ms-discriminator-value": "userAccount", + "type": "object", + "description": "The authentication info when authType is user account", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "principalId": { + "description": "Principal Id for user account.", + "type": "string" + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + } + }, + "EasyAuthMicrosoftEntraIDAuthInfo": { + "x-ms-discriminator-value": "easyAuthMicrosoftEntraID", + "type": "object", + "description": "The authentication info when authType is EasyAuth Microsoft Entra ID", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for EasyAuth Microsoft Entra ID.", + "type": "string" + }, + "secret": { + "description": "Application Secret for EasyAuth Microsoft Entra ID.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + } + } + }, + "LinkerResource": { + "type": "object", + "description": "Linker of source and target resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "required": [ + "properties" + ], + "properties": { + "properties": { + "description": "The properties of the Linker.", + "$ref": "#/definitions/LinkerProperties", + "x-ms-client-flatten": true + }, + "systemData": { + "x-nullable": true, + "readOnly": true, + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/systemData", + "description": "The system data." + } + } + }, + "LinkerPatch": { + "description": "A Linker to be updated.", + "type": "object", + "properties": { + "properties": { + "description": "Linker properties", + "type": "object", + "x-ms-client-flatten": true, + "$ref": "#/definitions/LinkerProperties" + } + } + }, + "ResourceList": { + "description": "The list of Linker.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The Linker used to get the next page of Linker list.", + "type": "string" + }, + "value": { + "description": "The list of Linkers.", + "type": "array", + "items": { + "$ref": "#/definitions/LinkerResource" + } + } + } + }, + "LinkerProperties": { + "description": "The properties of the Linker.", + "type": "object", + "properties": { + "targetService": { + "$ref": "#/definitions/TargetServiceBase", + "description": "The target service properties" + }, + "authInfo": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthInfoBase" + }, + "clientType": { + "description": "The application client type", + "$ref": "#/definitions/ClientType" + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + }, + "vNetSolution": { + "x-nullable": true, + "description": "The VNet solution.", + "$ref": "#/definitions/VNetSolution" + }, + "secretStore": { + "x-nullable": true, + "description": "An option to store secret value in secure place", + "$ref": "#/definitions/SecretStore" + }, + "scope": { + "x-nullable": true, + "type": "string", + "description": "connection scope in source service." + }, + "publicNetworkSolution": { + "x-nullable": true, + "description": "The network solution.", + "$ref": "#/definitions/PublicNetworkSolution" + }, + "configurationInfo": { + "x-nullable": true, + "description": "The connection information consumed by applications, including secrets, connection strings.", + "$ref": "#/definitions/ConfigurationInfo" + } + } + }, + "LinkerConfigurationType": { + "description": "Type of configuration to determine whether the configuration can be modified after creation. KeyvaultSecret means the configuration references a key vault secret, such as App Service/ACA key vault reference. Default means the configuration is real value, such as user name, raw secret, etc.", + "type": "string", + "enum": [ + "Default", + "KeyVaultSecret" + ], + "x-ms-enum": { + "name": "LinkerConfigurationType", + "modelAsString": true + } + }, + "SourceConfiguration": { + "description": "A configuration item for source resource", + "type": "object", + "properties": { + "name": { + "description": "The name of setting.", + "type": "string" + }, + "value": { + "x-nullable": true, + "description": "The value of setting", + "type": "string" + }, + "configType": { + "description": "The type of setting", + "readOnly": true, + "$ref": "#/definitions/LinkerConfigurationType" + }, + "keyVaultReferenceIdentity": { + "x-nullable": true, + "description": "The identity for key vault reference, system or user-assigned managed identity ID", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "Descriptive information for the configuration", + "type": "string" + } + } + }, + "ConfigurationNameItem": { + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ConfigurationNames" + } + } + }, + "ConfigurationNames": { + "type": "object", + "description": "The configuration names which will be set based on specific target resource, client type, auth type.", + "properties": { + "targetService": { + "type": "string", + "description": "The target service provider name and resource name." + }, + "clientType": { + "$ref": "#/definitions/ClientType", + "description": "The client type for configuration names." + }, + "authType": { + "$ref": "#/definitions/AuthType", + "description": "The auth type." + }, + "secretType": { + "$ref": "#/definitions/SecretSourceType", + "description": "Indicates where the secrets in configuration from. Used when secrets are from Keyvault." + }, + "daprProperties": { + "description": "Deprecated, please use #/definitions/DaprConfigurationList instead", + "$ref": "#/definitions/DaprProperties" + }, + "names": { + "type": "array", + "description": "The configuration names to be set in compute service environment.", + "items": { + "$ref": "#/definitions/ConfigurationName" + } + } + } + }, + "ConfigurationName": { + "type": "object", + "description": "The configuration names.", + "properties": { + "value": { + "type": "string" + }, + "description": { + "type": "string", + "description": "Description for the configuration name." + }, + "required": { + "type": "boolean", + "description": "Represent the configuration is required or not" + } + } + }, + "ConfigurationNameResult": { + "description": "Configuration Name list which will be set based on different target resource, client type, auth type.", + "type": "object", + "properties": { + "value": { + "description": "Expected configuration names for each target service.", + "type": "array", + "items": { + "$ref": "#/definitions/ConfigurationNameItem" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "description": "Link to next page of resources.", + "type": "string", + "readOnly": true + } + } + }, + "ConfigurationResult": { + "description": "Configurations for source resource, include appSettings, connectionString and serviceBindings", + "type": "object", + "properties": { + "configurations": { + "description": "The configuration properties for source resource.", + "type": "array", + "items": { + "$ref": "#/definitions/SourceConfiguration" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidateOperationResult": { + "description": "The validation operation result for a Linker.", + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The validation result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ValidateResult" + }, + "resourceId": { + "x-nullable": true, + "description": "Validated Linker id.", + "type": "string" + }, + "status": { + "x-nullable": true, + "description": "Validation operation status.", + "type": "string" + } + } + }, + "ValidateResult": { + "description": "The validation result for a Linker.", + "type": "object", + "properties": { + "linkerName": { + "x-nullable": true, + "description": "The linker name.", + "type": "string" + }, + "isConnectionAvailable": { + "x-nullable": true, + "description": "A boolean value indicating whether the connection is available or not", + "type": "boolean" + }, + "reportStartTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The start time of the validation report." + }, + "reportEndTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The end time of the validation report." + }, + "sourceId": { + "x-nullable": true, + "description": "The resource id of the Linker source application.", + "type": "string" + }, + "targetId": { + "x-nullable": true, + "description": "The resource Id of target service.", + "type": "string" + }, + "authType": { + "x-nullable": true, + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "validationDetail": { + "description": "The detail of validation result", + "type": "array", + "items": { + "$ref": "#/definitions/ValidationResultItem" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidationResultItem": { + "description": "The validation item for a Linker.", + "type": "object", + "properties": { + "name": { + "description": "The validation item name.", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "The display name of validation item", + "type": "string" + }, + "result": { + "x-nullable": true, + "description": "The result of validation", + "type": "string", + "enum": [ + "success", + "failure", + "warning" + ], + "x-ms-enum": { + "name": "ValidationResultStatus", + "modelAsString": true + } + }, + "errorMessage": { + "x-nullable": true, + "description": "The error message of validation result", + "type": "string" + }, + "errorCode": { + "x-nullable": true, + "description": "The error code of validation result", + "type": "string" + } + } + }, + "VNetSolution": { + "type": "object", + "description": "The VNet solution for linker", + "properties": { + "type": { + "x-nullable": true, + "description": "Type of VNet solution.", + "type": "string", + "enum": [ + "serviceEndpoint", + "privateLink" + ], + "x-ms-enum": { + "name": "vNetSolutionType", + "modelAsString": true + } + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + } + } + }, + "PublicNetworkSolution": { + "type": "object", + "description": "Indicates public network solution, include firewall rules", + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation(such as firewall rules) when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "action": { + "description": "Optional. Indicates public network solution. If enable, enable public network access of target service with best try. Default is enable. If optOut, opt out public network access configuration.", + "$ref": "#/definitions/ActionType" + }, + "firewallRules": { + "description": "Describe firewall rules of target service to make sure source application could connect to the target.", + "$ref": "#/definitions/FirewallRules" + } + } + }, + "FirewallRules": { + "type": "object", + "description": "Target service's firewall rules. to allow connections from source service.", + "properties": { + "ipRanges": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This value specifies the set of IP addresses or IP address ranges in CIDR form to be included as the allowed list of client IPs for a given database account." + }, + "azureServices": { + "description": "Allow Azure services to access the target service if true.", + "$ref": "#/definitions/AllowType" + }, + "callerClientIP": { + "description": "Allow caller client IP to access the target service if true. the property is used when connecting local application to target service.", + "$ref": "#/definitions/AllowType" + } + } + }, + "ConfigurationInfo": { + "type": "object", + "description": "The configuration information, used to generate configurations or save to applications", + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "action": { + "description": "Optional, indicate whether to apply configurations on source application. If enable, generate configurations and applied to the source application. Default is enable. If optOut, no configuration change will be made on source.", + "$ref": "#/definitions/ActionType" + }, + "customizedKeys": { + "description": "Optional. A dictionary of default key name and customized key name mapping. If not specified, default key name will be used for generate configurations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "daprProperties": { + "description": "Indicates some additional properties for dapr client type", + "$ref": "#/definitions/DaprProperties" + }, + "additionalConfigurations": { + "description": "A dictionary of additional configurations to be added. Service will auto generate a set of basic configurations and this property is to full fill more customized configurations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "additionalConnectionStringProperties": { + "description": "A dictionary of additional properties to be added in the end of connection string.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "configurationStore": { + "x-nullable": true, + "description": "An option to store configuration into different place", + "$ref": "#/definitions/ConfigurationStore" + } + } + }, + "ConfigurationStore": { + "type": "object", + "description": "An option to store configuration into different place", + "properties": { + "appConfigurationId": { + "x-nullable": true, + "type": "string", + "description": "The app configuration id to store configuration" + } + } + }, + "DaprProperties": { + "type": "object", + "description": "Indicates some additional properties for dapr client type", + "properties": { + "version": { + "x-nullable": true, + "type": "string", + "description": "The dapr component version" + }, + "componentType": { + "x-nullable": true, + "type": "string", + "description": "The dapr component type" + }, + "secretStoreComponent": { + "x-nullable": true, + "type": "string", + "description": "The name of a secret store dapr to retrieve secret" + }, + "metadata": { + "description": "Additional dapr metadata", + "type": "array", + "items": { + "$ref": "#/definitions/DaprMetadata" + }, + "x-ms-identifiers": [ + "name" + ] + }, + "scopes": { + "description": "The dapr component scopes", + "type": "array", + "items": { + "type": "string" + } + }, + "runtimeVersion": { + "x-nullable": true, + "type": "string", + "readOnly": true, + "description": "The runtime version supported by the properties" + }, + "bindingComponentDirection": { + "x-nullable": true, + "type": "string", + "enum": [ + "input", + "output" + ], + "x-ms-enum": { + "name": "DaprBindingComponentDirection", + "modelAsString": true + }, + "readOnly": true, + "description": "The direction supported by the dapr binding component" + } + } + }, + "DaprMetadata": { + "description": "The dapr component metadata.", + "type": "object", + "properties": { + "name": { + "description": "Metadata property name.", + "type": "string" + }, + "value": { + "description": "Metadata property value.", + "type": "string" + }, + "secretRef": { + "description": "The secret name where dapr could get value", + "type": "string" + }, + "description": { + "description": "The description of the metadata, returned from configuration api", + "type": "string" + }, + "required": { + "description": "The value indicating whether the metadata is required or not", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "DaprMetadataRequired", + "modelAsString": true + } + } + } + }, + "SecretStore": { + "type": "object", + "description": "An option to store secret value in secure place", + "properties": { + "keyVaultId": { + "x-nullable": true, + "type": "string", + "description": "The key vault id to store secret" + }, + "keyVaultSecretName": { + "x-nullable": true, + "type": "string", + "description": "The key vault secret name to store secret, only valid when storing one secret" + } + } + }, + "DryrunList": { + "description": "The list of dryrun.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The link used to get the next page of dryrun list.", + "type": "string" + }, + "value": { + "description": "The list of dryrun.", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunResource" + } + } + } + }, + "DryrunResource": { + "type": "object", + "description": "a dryrun job resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "properties": { + "properties": { + "description": "The properties of the dryrun job.", + "$ref": "#/definitions/DryrunProperties", + "x-ms-client-flatten": true + } + } + }, + "DryrunPatch": { + "type": "object", + "description": "a dryrun job to be updated.", + "properties": { + "properties": { + "description": "The properties of the dryrun job.", + "$ref": "#/definitions/DryrunProperties", + "x-ms-client-flatten": true + } + } + }, + "DryrunProperties": { + "description": "The properties of the dryrun job", + "type": "object", + "properties": { + "parameters": { + "description": "The parameters of the dryrun", + "$ref": "#/definitions/DryrunParameters" + }, + "prerequisiteResults": { + "readOnly": true, + "description": "the result of the dryrun", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunPrerequisiteResult" + }, + "x-ms-identifiers": [] + }, + "operationPreviews": { + "readOnly": true, + "description": "the preview of the operations for creation", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunOperationPreview" + }, + "x-ms-identifiers": [] + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + } + } + }, + "DryrunActionName": { + "description": "The name of action for you dryrun job.", + "type": "string", + "enum": [ + "createOrUpdate" + ], + "x-ms-enum": { + "name": "DryrunActionName", + "modelAsString": true + } + }, + "DryrunParameters": { + "description": "The parameters of the dryrun", + "discriminator": "actionName", + "type": "object", + "properties": { + "actionName": { + "$ref": "#/definitions/DryrunActionName" + } + }, + "required": [ + "actionName" + ] + }, + "CreateOrUpdateDryrunParameters": { + "x-ms-discriminator-value": "createOrUpdate", + "type": "object", + "description": "The dryrun parameters for creation or update a linker", + "allOf": [ + { + "$ref": "#/definitions/DryrunParameters" + }, + { + "$ref": "#/definitions/LinkerProperties" + } + ] + }, + "DryrunPrerequisiteResultType": { + "description": "The type of dryrun result.", + "type": "string", + "enum": [ + "basicError", + "permissionsMissing" + ], + "x-ms-enum": { + "name": "DryrunPrerequisiteResultType", + "modelAsString": true + } + }, + "DryrunPrerequisiteResult": { + "description": "A result of dryrun", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/DryrunPrerequisiteResultType" + } + }, + "required": [ + "type" + ] + }, + "BasicErrorDryrunPrerequisiteResult": { + "x-ms-discriminator-value": "basicError", + "description": "The represent of basic error", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/DryrunPrerequisiteResult" + } + ], + "properties": { + "code": { + "type": "string", + "description": "The error code." + }, + "message": { + "type": "string", + "description": "The error message." + } + } + }, + "PermissionsMissingDryrunPrerequisiteResult": { + "x-ms-discriminator-value": "permissionsMissing", + "description": "The represent of missing permissions", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/DryrunPrerequisiteResult" + } + ], + "properties": { + "scope": { + "description": "The permission scope", + "type": "string" + }, + "permissions": { + "description": "The permission list", + "type": "array", + "items": { + "type": "string" + } + }, + "recommendedRole": { + "description": "The recommended role to resolve permissions missing", + "type": "string" + } + } + }, + "DryrunOperationPreview": { + "description": "The preview of the operations for creation", + "type": "object", + "properties": { + "name": { + "description": "The operation name", + "type": "string" + }, + "operationType": { + "description": "The operation type", + "type": "string", + "enum": [ + "configConnection", + "configNetwork", + "configAuth" + ], + "x-ms-enum": { + "name": "DryrunPreviewOperationType", + "modelAsString": true + } + }, + "description": { + "description": "The description of the operation", + "type": "string" + }, + "action": { + "description": "The action defined by RBAC, refer https://docs.microsoft.com/azure/role-based-access-control/role-definitions#actions-format", + "type": "string" + }, + "scope": { + "description": "The scope of the operation, refer https://docs.microsoft.com/azure/role-based-access-control/scope-overview", + "type": "string" + } + } + }, + "ActionType": { + "description": "Indicates how to apply the connector operations, such as opt out network configuration, opt in configuration.", + "type": "string", + "enum": [ + "enable", + "optOut" + ], + "x-ms-enum": { + "name": "actionType", + "modelAsString": true + } + }, + "AuthMode": { + "description": "Indicates how to apply the authentication configuration operations.", + "type": "string", + "enum": [ + "optInAllAuth", + "optOutAllAuth" + ], + "x-ms-enum": { + "name": "authMode", + "modelAsString": true, + "values": [ + { + "value": "optInAllAuth", + "description": "Default authentication configuration according to the authentication type." + }, + { + "value": "optOutAllAuth", + "description": "Skip all authentication configuration such as enabling managed identity and granting RBAC roles" + } + ] + } + }, + "AllowType": { + "description": "Whether to allow firewall rules.", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "allowType", + "modelAsString": true + } + }, + "DaprConfigurationList": { + "description": "Dapr configuration list supported by Service Connector", + "type": "object", + "properties": { + "value": { + "description": "The list of dapr configurations", + "type": "array", + "items": { + "$ref": "#/definitions/DaprConfigurationResource" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "description": "Link to next page of resources.", + "type": "string", + "readOnly": true + } + } + }, + "DaprConfigurationResource": { + "description": "Represent one resource of the dapr configuration list", + "type": "object", + "properties": { + "properties": { + "description": "The properties of the dapr configuration.", + "$ref": "#/definitions/DaprConfigurationProperties", + "x-ms-client-flatten": true + } + } + }, + "DaprConfigurationProperties": { + "type": "object", + "properties": { + "targetType": { + "type": "string", + "description": "Supported target resource type, extract from resource id, uppercase" + }, + "authType": { + "$ref": "#/definitions/AuthType" + }, + "daprProperties": { + "$ref": "#/definitions/DaprProperties" + } + } + } + }, + "parameters": { + "LinkerNameParameter": { + "name": "linkerName", + "in": "path", + "required": true, + "type": "string", + "description": "The name Linker resource.", + "x-ms-parameter-location": "method" + }, + "ConnectorNameParameter": { + "name": "connectorName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of resource.", + "x-ms-parameter-location": "method" + }, + "ResourceUriParameter": { + "name": "resourceUri", + "in": "path", + "required": true, + "type": "string", + "description": "The fully qualified Azure Resource manager identifier of the resource to be connected.", + "x-ms-skip-url-encoding": true, + "x-ms-parameter-location": "method" + }, + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription.", + "minLength": 1, + "x-ms-parameter-location": "method" + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConfigurationNamesList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConfigurationNamesList.json new file mode 100644 index 000000000000..57c406a4b875 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConfigurationNamesList.json @@ -0,0 +1,52 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "targetService": "MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES", + "clientType": "none", + "authType": "systemAssignedIdentity", + "names": [ + { + "value": "AZURE_APPCONFIGURATION_ENDPOINT", + "description": "App configuration endpoint" + }, + { + "value": "AZURE_APPCONFIGURATION_SCOPE", + "description": "The scopes required for the token." + } + ] + } + }, + { + "properties": { + "targetService": "MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES", + "clientType": "none", + "authType": "userAssignedIdentity", + "names": [ + { + "value": "AZURE_APPCONFIGURATION_ENDPOINT", + "description": "App configuration endpoint" + }, + { + "value": "AZURE_APPCONFIGURATION_CLIENTID", + "description": "The client(application) ID of the user identity." + }, + { + "value": "AZURE_APPCONFIGURATION_SCOPE", + "description": "The scopes required for getting token." + } + ] + } + } + ], + "nextLink": null + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunCreate.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunCreate.json new file mode 100644 index 000000000000..d4103f9d88e4 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunCreate.json @@ -0,0 +1,116 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "201": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Accepted" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunDelete.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunDelete.json new file mode 100644 index 000000000000..d1cd053dfdf2 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunDelete.json @@ -0,0 +1,13 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName" + }, + "responses": { + "200": {}, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunGet.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunGet.json new file mode 100644 index 000000000000..e9fab0f0d0fb --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunGet.json @@ -0,0 +1,33 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName" + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunList.json new file mode 100644 index 000000000000..b0d6cb39937d --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunList.json @@ -0,0 +1,36 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunUpdate.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunUpdate.json new file mode 100644 index 000000000000..3f87be091230 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorDryrunUpdate.json @@ -0,0 +1,78 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorList.json new file mode 100644 index 000000000000..ac02963e6953 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ConnectorList.json @@ -0,0 +1,34 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/linkers/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/devConnectors", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/Connectors.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/Connectors.json new file mode 100644 index 000000000000..b774d9142b09 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/Connectors.json @@ -0,0 +1,43 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/devConnnectors/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/devConnectors", + "properties": { + "authInfo": { + "authType": "systemAssignedIdentity", + "roles": [ + "customizedOwner" + ] + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "publicNetworkSolution": { + "firewallRules": { + "ipRanges": [ + "182.22.120" + ], + "callerClientIP": "true" + }, + "action": "enable", + "deleteOrUpdateBehavior": "ForcedCleanup" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteConnector.json new file mode 100644 index 000000000000..1dc02aed0953 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteConnector.json @@ -0,0 +1,18 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": {}, + "204": {}, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteDryrun.json new file mode 100644 index 000000000000..b6d84517cba6 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteDryrun.json @@ -0,0 +1,11 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName" + }, + "responses": { + "200": {}, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteLinker.json new file mode 100644 index 000000000000..a2eb35ce6361 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/DeleteLinker.json @@ -0,0 +1,16 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": {}, + "204": {}, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GenerateConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GenerateConfigurations.json new file mode 100644 index 000000000000..b51f80725ab6 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GenerateConfigurations.json @@ -0,0 +1,26 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "customizedKeys": { + "ASL_DocumentDb_ConnectionString": "MyConnectionstring" + } + } + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "MyConnectionstring", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetConfigurations.json new file mode 100644 index 000000000000..39d787a2211d --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetConfigurations.json @@ -0,0 +1,41 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.App/containerApps/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "AZURE_POSTGRESQL_HOST", + "value": "Host", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_USER", + "value": "Username", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_DATABASE", + "value": "DatabaseName", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_PORT", + "value": "Port", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_PASSWORD", + "value": "SecretUri", + "configType": "KeyVaultSecret", + "keyVaultReferenceIdentity": "system" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetDaprConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetDaprConfigurations.json new file mode 100644 index 000000000000..cdbc03e325fc --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetDaprConfigurations.json @@ -0,0 +1,33 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "targetType": "MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES", + "authType": "secret", + "daprProperties": { + "version": "v1", + "componentType": "bindings", + "runtimeVersion": "1.10", + "bindingComponentDirection": "input", + "metadata": [ + { + "name": "containerName", + "description": "The name of the container to be used for Dapr state.", + "required": "true" + } + ] + } + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetDryrun.json new file mode 100644 index 000000000000..6545c44b1163 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/GetDryrun.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "name": "dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/Linker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/Linker.json new file mode 100644 index 000000000000..eabc04aa76e7 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/Linker.json @@ -0,0 +1,47 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/kvname" + }, + "scope": "AKS-Namespace", + "clientType": "dotnet", + "publicNetworkSolution": { + "action": "enable" + }, + "configurationInfo": { + "deleteOrUpdateBehavior": "ForcedCleanup", + "customizedKeys": { + "AZURE_MYSQL_CONNECTIONSTRING": "myConnectionstring", + "AZURE_MYSQL_SSLMODE": "mySslmode" + }, + "additionalConfigurations": { + "throttlingLimit": "100" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/LinkerGenerateConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/LinkerGenerateConfigurations.json new file mode 100644 index 000000000000..20077dc3ba0b --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/LinkerGenerateConfigurations.json @@ -0,0 +1,24 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "customizedKeys": { + "ASL_DocumentDb_ConnectionString": "MyConnectionstring" + } + } + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "MyConnectionstring", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/LinkerList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/LinkerList.json new file mode 100644 index 000000000000..99a8f52427c4 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/LinkerList.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ListDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ListDryrun.json new file mode 100644 index 000000000000..4a8dde8c63f0 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ListDryrun.json @@ -0,0 +1,35 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "name": "dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/OperationsList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/OperationsList.json new file mode 100644 index 000000000000..905bfe616da0 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/OperationsList.json @@ -0,0 +1,184 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "display": { + "description": "Register the subscription for Microsoft.ServiceLinker", + "operation": "Register the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/register/action" + }, + { + "display": { + "description": "Unregister the subscription for Microsoft.ServiceLinker", + "operation": "Unregister the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/unregister/action" + }, + { + "display": { + "description": "read operations", + "operation": "read_operations", + "provider": "Microsoft.ServiceLinker", + "resource": "operations" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/operations/read" + }, + { + "display": { + "description": "list dryrun jobs", + "operation": "Dryrun_List", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "get a dryrun job", + "operation": "Dryrun_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "create a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Create", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "delete a dryrun job", + "operation": "Dryrun_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/delete" + }, + { + "display": { + "description": "add a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "read operationStatuses", + "operation": "read_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/read" + }, + { + "display": { + "description": "write operationStatuses", + "operation": "write_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/write" + }, + { + "display": { + "description": "Returns list of Linkers which connects to the resource.", + "operation": "Linker_List", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Returns Linker resource for a given name.", + "operation": "Linker_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Create or update linker resource.", + "operation": "Linker_CreateOrUpdate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Delete a link.", + "operation": "Linker_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/delete" + }, + { + "display": { + "description": "Operation to update an existing link.", + "operation": "Linker_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Validate a link.", + "operation": "Linker_Validate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/validateLinker/action" + }, + { + "display": { + "description": "list source configurations for a linker.", + "operation": "Linker_ListConfigurations", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/listConfigurations/action" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchConnector.json new file mode 100644 index 000000000000..a302ac667d38 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchConnector.json @@ -0,0 +1,64 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "202": { + "headers": { + "azure-asyncoperation": "http://azure.async.operation/status" + }, + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchDryrun.json new file mode 100644 index 000000000000..c7da10d3eac5 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchDryrun.json @@ -0,0 +1,77 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchLinker.json new file mode 100644 index 000000000000..6a85c703e63b --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PatchLinker.json @@ -0,0 +1,59 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutConnector.json new file mode 100644 index 000000000000..b85bfd26ae2e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutConnector.json @@ -0,0 +1,63 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutDryrun.json new file mode 100644 index 000000000000..65e6713bb9c6 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutDryrun.json @@ -0,0 +1,116 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Updating" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutLinker.json new file mode 100644 index 000000000000..f678acb875be --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/PutLinker.json @@ -0,0 +1,68 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + }, + "responses": { + "200": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + }, + "201": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ValidateConnectorSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ValidateConnectorSuccess.json new file mode 100644 index 000000000000..a2e570267b75 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ValidateConnectorSuccess.json @@ -0,0 +1,38 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": { + "body": { + "properties": { + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ValidateLinkerSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ValidateLinkerSuccess.json new file mode 100644 index 000000000000..3bb0f31ce67f --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/examples/ValidateLinkerSuccess.json @@ -0,0 +1,38 @@ +{ + "parameters": { + "api-version": "2024-07-01-preview", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "properties": { + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "sourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "targetId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/servicelinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/servicelinker.json new file mode 100644 index 000000000000..3be7908389ae --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/servicelinker.json @@ -0,0 +1,2937 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.ServiceLinker", + "description": "Microsoft.ServiceLinker provider", + "version": "2024-07-01-preview" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow.", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ConnectorDryrunList": { + "$ref": "./examples/ConnectorDryrunList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "ConnectorDryrunGet": { + "$ref": "./examples/ConnectorDryrunGet.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "Connector" + ], + "operationId": "Connector_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunCreate": { + "$ref": "./examples/ConnectorDryrunCreate.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "201": { + "description": "Long running operation", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Connector" + ], + "operationId": "Connector_UpdateDryrun", + "description": "update a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunUpdate": { + "$ref": "./examples/ConnectorDryrunUpdate.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunPatch" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Connector" + ], + "operationId": "Connector_DeleteDryrun", + "description": "delete a dryrun job", + "x-ms-examples": { + "ConnectorDryrunDelete": { + "$ref": "./examples/ConnectorDryrunDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The job is deleted." + }, + "204": { + "description": "Deleted. The job is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors": { + "get": { + "deprecated": false, + "description": "Returns list of connector which connects to the resource, which supports to config the target service during the resource provision.", + "operationId": "Connector_List", + "x-ms-examples": { + "ConnectorList": { + "$ref": "./examples/ConnectorList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Connector details.", + "schema": { + "$ref": "#/definitions/ResourceList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}": { + "get": { + "description": "Returns Connector resource for a given name.", + "operationId": "Connector_Get", + "x-ms-examples": { + "Connector": { + "$ref": "./examples/Connectors.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Connector details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update Connector resource.", + "operationId": "Connector_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutConnector": { + "$ref": "./examples/PutConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connector details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a Connector.", + "x-ms-examples": { + "DeleteConnector": { + "$ref": "./examples/DeleteConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The Connector is deleted." + }, + "202": { + "description": "Long running operation." + }, + "204": { + "description": "Deleted. The Connector is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Update", + "description": "Operation to update an existing Connector.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchConnector": { + "$ref": "./examples/PatchConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connector details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a Connector.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "202": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}/validate": { + "post": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Validate", + "description": "Validate a Connector.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-examples": { + "ValidateConnectorSuccess": { + "$ref": "./examples/ValidateConnectorSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}/generateConfigurations": { + "post": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GenerateConfigurations", + "description": "Generate configurations for a Connector.", + "x-ms-examples": { + "GenerateConfiguration": { + "$ref": "./examples/GenerateConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connection Info, including format, secret store, etc", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ConfigurationInfo" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers": { + "get": { + "deprecated": false, + "description": "Returns list of Linkers which connects to the resource. which supports to config both application and target service during the resource provision.", + "operationId": "Linker_List", + "x-ms-examples": { + "LinkerList": { + "$ref": "./examples/LinkerList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/ResourceList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}": { + "get": { + "description": "Returns Linker resource for a given name.", + "operationId": "Linker_Get", + "x-ms-examples": { + "Linker": { + "$ref": "./examples/Linker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update Linker resource.", + "operationId": "Linker_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutLinker": { + "$ref": "./examples/PutLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a Linker.", + "x-ms-examples": { + "DeleteLinker": { + "$ref": "./examples/DeleteLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The Linker is deleted." + }, + "202": { + "description": "Long running operation." + }, + "204": { + "description": "Deleted. The Linker is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Update", + "description": "Operation to update an existing Linker.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchLinker": { + "$ref": "./examples/PatchLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a Linker.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/validateLinker": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Validate", + "description": "Validate a Linker.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-examples": { + "ValidateLinkerSuccess": { + "$ref": "./examples/ValidateLinkerSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/listConfigurations": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_ListConfigurations", + "description": "list source configurations for a Linker.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/GetConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/dryruns": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ListDryrun": { + "$ref": "./examples/ListDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "GetDryrun": { + "$ref": "./examples/GetDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutDryrun": { + "$ref": "./examples/PutDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "201": { + "description": "Long running operation", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_UpdateDryrun", + "description": "add a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchDryrun": { + "$ref": "./examples/PatchDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunPatch" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_DeleteDryrun", + "description": "delete a dryrun job", + "x-ms-examples": { + "DeleteDryrun": { + "$ref": "./examples/DeleteDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The job is deleted." + }, + "204": { + "description": "Deleted. The job is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/generateConfigurations": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_GenerateConfigurations", + "description": "Generate configurations for a Linker.", + "x-ms-examples": { + "GenerateConfiguration": { + "$ref": "./examples/LinkerGenerateConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Connection Info, including format, secret store, etc", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ConfigurationInfo" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/providers/Microsoft.ServiceLinker/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "description": "Lists the available ServiceLinker REST API operations.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/OperationsList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/providers/Microsoft.ServiceLinker/configurationNames": { + "get": { + "tags": [ + "ConfigurationNames" + ], + "operationId": "ConfigurationNames_List", + "description": "Lists the configuration names generated by Service Connector for all target, client types, auth types.", + "x-ms-examples": { + "GetConfigurationNames": { + "$ref": "./examples/ConfigurationNamesList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "$filter", + "in": "query", + "required": false, + "type": "string", + "description": "OData filter options." + }, + { + "name": "$skipToken", + "in": "query", + "required": false, + "type": "string", + "description": "OData skipToken option for pagination." + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationNameResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/daprConfigurations": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_ListDaprConfigurations", + "description": "List the dapr configuration supported by Service Connector.", + "x-ms-examples": { + "GetDaprConfigurations": { + "$ref": "./examples/GetDaprConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DaprConfigurationList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "TargetServiceType": { + "description": "The target service type.", + "type": "string", + "enum": [ + "AzureResource", + "ConfluentBootstrapServer", + "ConfluentSchemaRegistry", + "SelfHostedServer", + "FabricPlatform" + ], + "x-ms-enum": { + "name": "targetServiceType", + "modelAsString": true + } + }, + "TargetServiceBase": { + "description": "The target service properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The target service type.", + "$ref": "#/definitions/TargetServiceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResourceType": { + "description": "The azure resource type.", + "type": "string", + "enum": [ + "KeyVault", + "AppConfig" + ], + "x-ms-enum": { + "name": "azureResourceType", + "modelAsString": true + } + }, + "AzureResourcePropertiesBase": { + "description": "The azure resource properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The azure resource type.", + "$ref": "#/definitions/AzureResourceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResource": { + "x-ms-discriminator-value": "AzureResource", + "type": "object", + "description": "The azure resource info when target service type is AzureResource", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "id": { + "description": "The Id of azure resource.", + "type": "string" + }, + "resourceProperties": { + "x-nullable": true, + "description": "The azure resource connection related properties.", + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + } + }, + "AzureKeyVaultProperties": { + "x-ms-discriminator-value": "KeyVault", + "type": "object", + "description": "The resource properties when type is Azure Key Vault", + "allOf": [ + { + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + ], + "properties": { + "connectAsKubernetesCsiDriver": { + "x-nullable": true, + "description": "True if connect via Kubernetes CSI Driver.", + "type": "boolean" + } + } + }, + "AzureAppConfigProperties": { + "x-ms-discriminator-value": "AppConfig", + "type": "object", + "description": "The resource properties when type is Azure App Configuration", + "allOf": [ + { + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + ], + "properties": { + "connectWithKubernetesExtension": { + "x-nullable": true, + "description": "True if connection enables app configuration kubernetes extension.", + "type": "boolean" + } + } + }, + "ConfluentBootstrapServer": { + "x-ms-discriminator-value": "ConfluentBootstrapServer", + "type": "object", + "description": "The service properties when target service type is ConfluentBootstrapServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "FabricPlatform": { + "x-ms-discriminator-value": "FabricPlatform", + "type": "object", + "description": "The service properties when target service type is FabricPlatform", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "SelfHostedServer": { + "x-ms-discriminator-value": "SelfHostedServer", + "type": "object", + "description": "The service properties when target service type is SelfHostedServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "ConfluentSchemaRegistry": { + "x-ms-discriminator-value": "ConfluentSchemaRegistry", + "type": "object", + "description": "The service properties when target service type is ConfluentSchemaRegistry", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "DeleteOrUpdateBehavior": { + "description": "The cleanup behavior to indicate whether clean up operation when resource is deleted or updated", + "type": "string", + "enum": [ + "Default", + "ForcedCleanup" + ], + "x-ms-enum": { + "name": "DeleteOrUpdateBehavior", + "modelAsString": true + } + }, + "ClientType": { + "description": "The application client type", + "type": "string", + "enum": [ + "none", + "dotnet", + "java", + "python", + "go", + "php", + "ruby", + "django", + "nodejs", + "springBoot", + "kafka-springBoot", + "jms-springBoot", + "dapr" + ], + "x-ms-enum": { + "name": "clientType", + "modelAsString": true + } + }, + "AuthType": { + "description": "The authentication type.", + "type": "string", + "enum": [ + "systemAssignedIdentity", + "userAssignedIdentity", + "servicePrincipalSecret", + "servicePrincipalCertificate", + "secret", + "accessKey", + "userAccount", + "easyAuthMicrosoftEntraID" + ], + "x-ms-enum": { + "name": "AuthType", + "modelAsString": true + } + }, + "SecretType": { + "description": "The secret type.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecretUri", + "keyVaultSecretReference" + ], + "x-ms-enum": { + "name": "SecretType", + "modelAsString": true + } + }, + "SecretSourceType": { + "description": "The type of secret source.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecret" + ], + "x-ms-enum": { + "name": "SecretSourceType", + "modelAsString": true + } + }, + "SecretInfoBase": { + "description": "The secret info", + "discriminator": "secretType", + "type": "object", + "properties": { + "secretType": { + "description": "The secret type.", + "$ref": "#/definitions/SecretType" + } + }, + "required": [ + "secretType" + ] + }, + "ValueSecretInfo": { + "x-ms-discriminator-value": "rawValue", + "type": "object", + "description": "The secret info when type is rawValue. It's for scenarios that user input the secret.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "x-nullable": true, + "description": "The actual value of the secret.", + "type": "string", + "x-ms-secret": true + } + } + }, + "KeyVaultSecretReferenceSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretReference", + "type": "object", + "description": "The secret info when type is keyVaultSecretReference. It's for scenario that user provides a secret stored in user's keyvault and source is Azure Kubernetes. The key Vault's resource id is linked to secretStore.keyVaultId.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "name": { + "description": "Name of the Key Vault secret.", + "type": "string" + }, + "version": { + "x-nullable": true, + "description": "Version of the Key Vault secret.", + "type": "string" + } + } + }, + "KeyVaultSecretUriSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretUri", + "type": "object", + "description": "The secret info when type is keyVaultSecretUri. It's for scenario that user provides a secret stored in user's keyvault and source is Web App, Spring Cloud or Container App.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "description": "URI to the keyvault secret", + "type": "string" + } + } + }, + "AuthInfoBase": { + "description": "The authentication info", + "discriminator": "authType", + "type": "object", + "properties": { + "authType": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "authMode": { + "description": "Optional. Indicates how to configure authentication. If optInAllAuth, service linker configures authentication such as enabling identity on source resource and granting RBAC roles. If optOutAllAuth, opt out authentication setup. Default is optInAllAuth.", + "$ref": "#/definitions/AuthMode" + } + }, + "required": [ + "authType" + ] + }, + "AccessKeyInfoBase": { + "description": "The access key directly from target resource properties, which target service is Azure Resource, such as Microsoft.Storage", + "x-ms-discriminator-value": "accessKey", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "permissions": { + "description": "Permissions of the accessKey. `Read` and `Write` are for Azure Cosmos DB and Azure App Configuration, `Listen`, `Send` and `Manage` are for Azure Event Hub and Azure Service Bus.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "Read", + "Write", + "Listen", + "Send", + "Manage" + ], + "x-ms-enum": { + "name": "accessKeyPermissions", + "modelAsString": true + } + } + } + } + }, + "DatabaseAadAuthInfo": { + "description": "The extra auth info required by Database AAD authentication.", + "type": "object", + "properties": { + "userName": { + "x-nullable": true, + "description": "Username created in the database which is mapped to a user in AAD.", + "type": "string" + } + } + }, + "SecretAuthInfo": { + "x-ms-discriminator-value": "secret", + "type": "object", + "description": "The authentication info when authType is secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "name": { + "x-nullable": true, + "description": "Username or account name for secret auth.", + "type": "string" + }, + "secretInfo": { + "x-nullable": true, + "description": "Password or key vault secret for secret auth.", + "$ref": "#/definitions/SecretInfoBase" + } + } + }, + "UserAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "userAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is userAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "clientId": { + "description": "Client Id for userAssignedIdentity.", + "type": "string" + }, + "subscriptionId": { + "description": "Subscription id for userAssignedIdentity.", + "type": "string" + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure role to be assigned" + } + } + }, + "SystemAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "systemAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is systemAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure role to be assigned" + } + } + }, + "ServicePrincipalSecretAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalSecret", + "type": "object", + "description": "The authentication info when authType is servicePrincipal secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "clientId": { + "description": "ServicePrincipal application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "secret": { + "description": "Secret for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + }, + "required": [ + "clientId", + "principalId", + "secret" + ] + }, + "ServicePrincipalCertificateAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalCertificate", + "type": "object", + "description": "The authentication info when authType is servicePrincipal certificate", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "certificate": { + "description": "ServicePrincipal certificate for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + }, + "required": [ + "clientId", + "principalId", + "certificate" + ] + }, + "UserAccountAuthInfo": { + "x-ms-discriminator-value": "userAccount", + "type": "object", + "description": "The authentication info when authType is user account", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "principalId": { + "description": "Principal Id for user account.", + "type": "string" + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + } + }, + "EasyAuthMicrosoftEntraIDAuthInfo": { + "x-ms-discriminator-value": "easyAuthMicrosoftEntraID", + "type": "object", + "description": "The authentication info when authType is EasyAuth Microsoft Entra ID", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for EasyAuth Microsoft Entra ID.", + "type": "string" + }, + "secret": { + "description": "Application Secret for EasyAuth Microsoft Entra ID.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + } + } + }, + "LinkerResource": { + "type": "object", + "description": "Linker of source and target resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "required": [ + "properties" + ], + "properties": { + "properties": { + "description": "The properties of the Linker.", + "$ref": "#/definitions/LinkerProperties", + "x-ms-client-flatten": true + }, + "systemData": { + "x-nullable": true, + "readOnly": true, + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/systemData", + "description": "The system data." + } + } + }, + "LinkerPatch": { + "description": "A Linker to be updated.", + "type": "object", + "properties": { + "properties": { + "description": "Linker properties", + "type": "object", + "x-ms-client-flatten": true, + "$ref": "#/definitions/LinkerProperties" + } + } + }, + "ResourceList": { + "description": "The list of Linker.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The Linker used to get the next page of Linker list.", + "type": "string" + }, + "value": { + "description": "The list of Linkers.", + "type": "array", + "items": { + "$ref": "#/definitions/LinkerResource" + } + } + } + }, + "LinkerProperties": { + "description": "The properties of the Linker.", + "type": "object", + "properties": { + "targetService": { + "$ref": "#/definitions/TargetServiceBase", + "description": "The target service properties" + }, + "authInfo": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthInfoBase" + }, + "clientType": { + "description": "The application client type", + "$ref": "#/definitions/ClientType" + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + }, + "vNetSolution": { + "x-nullable": true, + "description": "The VNet solution.", + "$ref": "#/definitions/VNetSolution" + }, + "secretStore": { + "x-nullable": true, + "description": "An option to store secret value in secure place", + "$ref": "#/definitions/SecretStore" + }, + "scope": { + "x-nullable": true, + "type": "string", + "description": "connection scope in source service." + }, + "publicNetworkSolution": { + "x-nullable": true, + "description": "The network solution.", + "$ref": "#/definitions/PublicNetworkSolution" + }, + "configurationInfo": { + "x-nullable": true, + "description": "The connection information consumed by applications, including secrets, connection strings.", + "$ref": "#/definitions/ConfigurationInfo" + } + } + }, + "LinkerConfigurationType": { + "description": "Type of configuration to determine whether the configuration can be modified after creation. KeyvaultSecret means the configuration references a key vault secret, such as App Service/ACA key vault reference. Default means the configuration is real value, such as user name, raw secret, etc.", + "type": "string", + "enum": [ + "Default", + "KeyVaultSecret" + ], + "x-ms-enum": { + "name": "LinkerConfigurationType", + "modelAsString": true + } + }, + "SourceConfiguration": { + "description": "A configuration item for source resource", + "type": "object", + "properties": { + "name": { + "description": "The name of setting.", + "type": "string" + }, + "value": { + "x-nullable": true, + "description": "The value of setting", + "type": "string" + }, + "configType": { + "description": "The type of setting", + "readOnly": true, + "$ref": "#/definitions/LinkerConfigurationType" + }, + "keyVaultReferenceIdentity": { + "x-nullable": true, + "description": "The identity for key vault reference, system or user-assigned managed identity ID", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "Descriptive information for the configuration", + "type": "string" + } + } + }, + "ConfigurationNameItem": { + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ConfigurationNames" + } + } + }, + "ConfigurationNames": { + "type": "object", + "description": "The configuration names which will be set based on specific target resource, client type, auth type.", + "properties": { + "targetService": { + "type": "string", + "description": "The target service provider name and resource name." + }, + "clientType": { + "$ref": "#/definitions/ClientType", + "description": "The client type for configuration names." + }, + "authType": { + "$ref": "#/definitions/AuthType", + "description": "The auth type." + }, + "secretType": { + "$ref": "#/definitions/SecretSourceType", + "description": "Indicates where the secrets in configuration from. Used when secrets are from Keyvault." + }, + "daprProperties": { + "description": "Deprecated, please use #/definitions/DaprConfigurationList instead", + "$ref": "#/definitions/DaprProperties" + }, + "names": { + "type": "array", + "description": "The configuration names to be set in compute service environment.", + "items": { + "$ref": "#/definitions/ConfigurationName" + } + } + } + }, + "ConfigurationName": { + "type": "object", + "description": "The configuration names.", + "properties": { + "value": { + "type": "string" + }, + "description": { + "type": "string", + "description": "Description for the configuration name." + }, + "required": { + "type": "boolean", + "description": "Represent the configuration is required or not" + } + } + }, + "ConfigurationNameResult": { + "description": "Configuration Name list which will be set based on different target resource, client type, auth type.", + "type": "object", + "properties": { + "value": { + "description": "Expected configuration names for each target service.", + "type": "array", + "items": { + "$ref": "#/definitions/ConfigurationNameItem" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "description": "Link to next page of resources.", + "type": "string", + "readOnly": true + } + } + }, + "ConfigurationResult": { + "description": "Configurations for source resource, include appSettings, connectionString and serviceBindings", + "type": "object", + "properties": { + "configurations": { + "description": "The configuration properties for source resource.", + "type": "array", + "items": { + "$ref": "#/definitions/SourceConfiguration" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidateOperationResult": { + "description": "The validation operation result for a Linker.", + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The validation result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ValidateResult" + }, + "resourceId": { + "x-nullable": true, + "description": "Validated Linker id.", + "type": "string" + }, + "status": { + "x-nullable": true, + "description": "Validation operation status.", + "type": "string" + } + } + }, + "ValidateResult": { + "description": "The validation result for a Linker.", + "type": "object", + "properties": { + "linkerName": { + "x-nullable": true, + "description": "The linker name.", + "type": "string" + }, + "isConnectionAvailable": { + "x-nullable": true, + "description": "A boolean value indicating whether the connection is available or not", + "type": "boolean" + }, + "reportStartTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The start time of the validation report." + }, + "reportEndTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The end time of the validation report." + }, + "sourceId": { + "x-nullable": true, + "description": "The resource id of the Linker source application.", + "type": "string" + }, + "targetId": { + "x-nullable": true, + "description": "The resource Id of target service.", + "type": "string" + }, + "authType": { + "x-nullable": true, + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "validationDetail": { + "description": "The detail of validation result", + "type": "array", + "items": { + "$ref": "#/definitions/ValidationResultItem" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidationResultItem": { + "description": "The validation item for a Linker.", + "type": "object", + "properties": { + "name": { + "description": "The validation item name.", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "The display name of validation item", + "type": "string" + }, + "result": { + "x-nullable": true, + "description": "The result of validation", + "type": "string", + "enum": [ + "success", + "failure", + "warning" + ], + "x-ms-enum": { + "name": "ValidationResultStatus", + "modelAsString": true + } + }, + "errorMessage": { + "x-nullable": true, + "description": "The error message of validation result", + "type": "string" + }, + "errorCode": { + "x-nullable": true, + "description": "The error code of validation result", + "type": "string" + } + } + }, + "VNetSolution": { + "type": "object", + "description": "The VNet solution for linker", + "properties": { + "type": { + "x-nullable": true, + "description": "Type of VNet solution.", + "type": "string", + "enum": [ + "serviceEndpoint", + "privateLink" + ], + "x-ms-enum": { + "name": "vNetSolutionType", + "modelAsString": true + } + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + } + } + }, + "PublicNetworkSolution": { + "type": "object", + "description": "Indicates public network solution, include firewall rules", + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation(such as firewall rules) when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "action": { + "description": "Optional. Indicates public network solution. If enable, enable public network access of target service with best try. Default is enable. If optOut, opt out public network access configuration.", + "$ref": "#/definitions/ActionType" + }, + "firewallRules": { + "description": "Describe firewall rules of target service to make sure source application could connect to the target.", + "$ref": "#/definitions/FirewallRules" + } + } + }, + "FirewallRules": { + "type": "object", + "description": "Target service's firewall rules. to allow connections from source service.", + "properties": { + "ipRanges": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This value specifies the set of IP addresses or IP address ranges in CIDR form to be included as the allowed list of client IPs for a given database account." + }, + "azureServices": { + "description": "Allow Azure services to access the target service if true.", + "$ref": "#/definitions/AllowType" + }, + "callerClientIP": { + "description": "Allow caller client IP to access the target service if true. the property is used when connecting local application to target service.", + "$ref": "#/definitions/AllowType" + } + } + }, + "ConfigurationInfo": { + "type": "object", + "description": "The configuration information, used to generate configurations or save to applications", + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "action": { + "description": "Optional, indicate whether to apply configurations on source application. If enable, generate configurations and applied to the source application. Default is enable. If optOut, no configuration change will be made on source.", + "$ref": "#/definitions/ActionType" + }, + "customizedKeys": { + "description": "Optional. A dictionary of default key name and customized key name mapping. If not specified, default key name will be used for generate configurations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "daprProperties": { + "description": "Indicates some additional properties for dapr client type", + "$ref": "#/definitions/DaprProperties" + }, + "additionalConfigurations": { + "description": "A dictionary of additional configurations to be added. Service will auto generate a set of basic configurations and this property is to full fill more customized configurations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "additionalConnectionStringProperties": { + "description": "A dictionary of additional properties to be added in the end of connection string.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "configurationStore": { + "x-nullable": true, + "description": "An option to store configuration into different place", + "$ref": "#/definitions/ConfigurationStore" + } + } + }, + "ConfigurationStore": { + "type": "object", + "description": "An option to store configuration into different place", + "properties": { + "appConfigurationId": { + "x-nullable": true, + "type": "string", + "description": "The app configuration id to store configuration" + } + } + }, + "DaprProperties": { + "type": "object", + "description": "Indicates some additional properties for dapr client type", + "properties": { + "version": { + "x-nullable": true, + "type": "string", + "description": "The dapr component version" + }, + "componentType": { + "x-nullable": true, + "type": "string", + "description": "The dapr component type" + }, + "secretStoreComponent": { + "x-nullable": true, + "type": "string", + "description": "The name of a secret store dapr to retrieve secret" + }, + "metadata": { + "description": "Additional dapr metadata", + "type": "array", + "items": { + "$ref": "#/definitions/DaprMetadata" + }, + "x-ms-identifiers": [ + "name" + ] + }, + "scopes": { + "description": "The dapr component scopes", + "type": "array", + "items": { + "type": "string" + } + }, + "runtimeVersion": { + "x-nullable": true, + "type": "string", + "readOnly": true, + "description": "The runtime version supported by the properties" + }, + "bindingComponentDirection": { + "x-nullable": true, + "type": "string", + "enum": [ + "input", + "output" + ], + "x-ms-enum": { + "name": "DaprBindingComponentDirection", + "modelAsString": true + }, + "readOnly": true, + "description": "The direction supported by the dapr binding component" + } + } + }, + "DaprMetadata": { + "description": "The dapr component metadata.", + "type": "object", + "properties": { + "name": { + "description": "Metadata property name.", + "type": "string" + }, + "value": { + "description": "Metadata property value.", + "type": "string" + }, + "secretRef": { + "description": "The secret name where dapr could get value", + "type": "string" + }, + "description": { + "description": "The description of the metadata, returned from configuration api", + "type": "string" + }, + "required": { + "description": "The value indicating whether the metadata is required or not", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "DaprMetadataRequired", + "modelAsString": true + } + } + } + }, + "SecretStore": { + "type": "object", + "description": "An option to store secret value in secure place", + "properties": { + "keyVaultId": { + "x-nullable": true, + "type": "string", + "description": "The key vault id to store secret" + }, + "keyVaultSecretName": { + "x-nullable": true, + "type": "string", + "description": "The key vault secret name to store secret, only valid when storing one secret" + } + } + }, + "DryrunList": { + "description": "The list of dryrun.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The link used to get the next page of dryrun list.", + "type": "string" + }, + "value": { + "description": "The list of dryrun.", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunResource" + } + } + } + }, + "DryrunResource": { + "type": "object", + "description": "a dryrun job resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "properties": { + "properties": { + "description": "The properties of the dryrun job.", + "$ref": "#/definitions/DryrunProperties", + "x-ms-client-flatten": true + } + } + }, + "DryrunPatch": { + "type": "object", + "description": "a dryrun job to be updated.", + "properties": { + "properties": { + "description": "The properties of the dryrun job.", + "$ref": "#/definitions/DryrunProperties", + "x-ms-client-flatten": true + } + } + }, + "DryrunProperties": { + "description": "The properties of the dryrun job", + "type": "object", + "properties": { + "parameters": { + "description": "The parameters of the dryrun", + "$ref": "#/definitions/DryrunParameters" + }, + "prerequisiteResults": { + "readOnly": true, + "description": "the result of the dryrun", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunPrerequisiteResult" + }, + "x-ms-identifiers": [] + }, + "operationPreviews": { + "readOnly": true, + "description": "the preview of the operations for creation", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunOperationPreview" + }, + "x-ms-identifiers": [] + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + } + } + }, + "DryrunActionName": { + "description": "The name of action for you dryrun job.", + "type": "string", + "enum": [ + "createOrUpdate" + ], + "x-ms-enum": { + "name": "DryrunActionName", + "modelAsString": true + } + }, + "DryrunParameters": { + "description": "The parameters of the dryrun", + "discriminator": "actionName", + "type": "object", + "properties": { + "actionName": { + "$ref": "#/definitions/DryrunActionName" + } + }, + "required": [ + "actionName" + ] + }, + "CreateOrUpdateDryrunParameters": { + "x-ms-discriminator-value": "createOrUpdate", + "type": "object", + "description": "The dryrun parameters for creation or update a linker", + "allOf": [ + { + "$ref": "#/definitions/DryrunParameters" + }, + { + "$ref": "#/definitions/LinkerProperties" + } + ] + }, + "DryrunPrerequisiteResultType": { + "description": "The type of dryrun result.", + "type": "string", + "enum": [ + "basicError", + "permissionsMissing" + ], + "x-ms-enum": { + "name": "DryrunPrerequisiteResultType", + "modelAsString": true + } + }, + "DryrunPrerequisiteResult": { + "description": "A result of dryrun", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/DryrunPrerequisiteResultType" + } + }, + "required": [ + "type" + ] + }, + "BasicErrorDryrunPrerequisiteResult": { + "x-ms-discriminator-value": "basicError", + "description": "The represent of basic error", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/DryrunPrerequisiteResult" + } + ], + "properties": { + "code": { + "type": "string", + "description": "The error code." + }, + "message": { + "type": "string", + "description": "The error message." + } + } + }, + "PermissionsMissingDryrunPrerequisiteResult": { + "x-ms-discriminator-value": "permissionsMissing", + "description": "The represent of missing permissions", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/DryrunPrerequisiteResult" + } + ], + "properties": { + "scope": { + "description": "The permission scope", + "type": "string" + }, + "permissions": { + "description": "The permission list", + "type": "array", + "items": { + "type": "string" + } + }, + "recommendedRole": { + "description": "The recommended role to resolve permissions missing", + "type": "string" + } + } + }, + "DryrunOperationPreview": { + "description": "The preview of the operations for creation", + "type": "object", + "properties": { + "name": { + "description": "The operation name", + "type": "string" + }, + "operationType": { + "description": "The operation type", + "type": "string", + "enum": [ + "configConnection", + "configNetwork", + "configAuth" + ], + "x-ms-enum": { + "name": "DryrunPreviewOperationType", + "modelAsString": true + } + }, + "description": { + "description": "The description of the operation", + "type": "string" + }, + "action": { + "description": "The action defined by RBAC, refer https://docs.microsoft.com/azure/role-based-access-control/role-definitions#actions-format", + "type": "string" + }, + "scope": { + "description": "The scope of the operation, refer https://docs.microsoft.com/azure/role-based-access-control/scope-overview", + "type": "string" + } + } + }, + "ActionType": { + "description": "Indicates how to apply the connector operations, such as opt out network configuration, opt in configuration.", + "type": "string", + "enum": [ + "enable", + "optOut" + ], + "x-ms-enum": { + "name": "actionType", + "modelAsString": true + } + }, + "AuthMode": { + "description": "Indicates how to apply the authentication configuration operations.", + "type": "string", + "enum": [ + "optInAllAuth", + "optOutAllAuth" + ], + "x-ms-enum": { + "name": "authMode", + "modelAsString": true, + "values": [ + { + "value": "optInAllAuth", + "description": "Default authentication configuration according to the authentication type." + }, + { + "value": "optOutAllAuth", + "description": "Skip all authentication configuration such as enabling managed identity and granting RBAC roles" + } + ] + } + }, + "AllowType": { + "description": "Whether to allow firewall rules.", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "allowType", + "modelAsString": true + } + }, + "DaprConfigurationList": { + "description": "Dapr configuration list supported by Service Connector", + "type": "object", + "properties": { + "value": { + "description": "The list of dapr configurations", + "type": "array", + "items": { + "$ref": "#/definitions/DaprConfigurationResource" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "description": "Link to next page of resources.", + "type": "string", + "readOnly": true + } + } + }, + "DaprConfigurationResource": { + "description": "Represent one resource of the dapr configuration list", + "type": "object", + "properties": { + "properties": { + "description": "The properties of the dapr configuration.", + "$ref": "#/definitions/DaprConfigurationProperties", + "x-ms-client-flatten": true + } + } + }, + "DaprConfigurationProperties": { + "type": "object", + "properties": { + "targetType": { + "type": "string", + "description": "Supported target resource type, extract from resource id, uppercase" + }, + "authType": { + "$ref": "#/definitions/AuthType" + }, + "daprProperties": { + "$ref": "#/definitions/DaprProperties" + } + } + } + }, + "parameters": { + "LinkerNameParameter": { + "name": "linkerName", + "in": "path", + "required": true, + "type": "string", + "description": "The name Linker resource.", + "x-ms-parameter-location": "method" + }, + "ConnectorNameParameter": { + "name": "connectorName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of resource.", + "x-ms-parameter-location": "method" + }, + "ResourceUriParameter": { + "name": "resourceUri", + "in": "path", + "required": true, + "type": "string", + "description": "The fully qualified Azure Resource manager identifier of the resource to be connected.", + "x-ms-skip-url-encoding": true, + "x-ms-parameter-location": "method" + }, + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription.", + "minLength": 1, + "x-ms-parameter-location": "method" + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/DeleteLink.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/DeleteLink.json new file mode 100644 index 000000000000..1665cb62d617 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/DeleteLink.json @@ -0,0 +1,12 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": {}, + "204": {}, + "202": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/GetConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/GetConfigurations.json new file mode 100644 index 000000000000..b9ac679ce37e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/GetConfigurations.json @@ -0,0 +1,19 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "ASL_DocumentDb_ConnectionString", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/Link.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/Link.json new file mode 100644 index 000000000000..f6fc96a81031 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/Link.json @@ -0,0 +1,29 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/LinkList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/LinkList.json new file mode 100644 index 000000000000..b0156db7285b --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/LinkList.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/OperationsList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/OperationsList.json new file mode 100644 index 000000000000..8f67473f5c42 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/OperationsList.json @@ -0,0 +1,185 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "display": { + "description": "Register the subscription for Microsoft.ServiceLinker", + "operation": "Register the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/register/action" + }, + { + "display": { + "description": "Unregister the subscription for Microsoft.ServiceLinker", + "operation": "Unregister the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/unregister/action" + }, + { + "display": { + "description": "read operations", + "operation": "read_operations", + "provider": "Microsoft.ServiceLinker", + "resource": "operations" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/operations/read" + }, + { + "display": { + "description": "list dryrun jobs", + "operation": "Dryrun_List", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "get a dryrun job", + "operation": "Dryrun_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "create a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Create", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "delete a dryrun job", + "operation": "Dryrun_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/delete" + }, + { + "display": { + "description": "add a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "read operationStatuses", + "operation": "read_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/read" + }, + { + "display": { + "description": "write operationStatuses", + "operation": "write_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/write" + }, + { + "display": { + "description": "Returns list of Linkers which connects to the resource.", + "operation": "Linker_List", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Returns Linker resource for a given name.", + "operation": "Linker_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Create or update linker resource.", + "operation": "Linker_CreateOrUpdate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Delete a link.", + "operation": "Linker_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/delete" + }, + { + "display": { + "description": "Operation to update an existing link.", + "operation": "Linker_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Validate a link.", + "operation": "Linker_Validate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/validateLinker/action" + }, + { + "display": { + "description": "list source configurations for a linker.", + "operation": "Linker_ListConfigurations", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/listConfigurations/action" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PatchLink.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PatchLink.json new file mode 100644 index 000000000000..eabeb61953cb --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PatchLink.json @@ -0,0 +1,59 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLink.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLink.json new file mode 100644 index 000000000000..0cf5efec9cf7 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLink.json @@ -0,0 +1,57 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + }, + "responses": { + "200": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + }, + "201": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLinkWithSecretStore.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLinkWithSecretStore.json new file mode 100644 index 000000000000..b3b37c417811 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLinkWithSecretStore.json @@ -0,0 +1,61 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLinkWithServiceEndpoint.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLinkWithServiceEndpoint.json new file mode 100644 index 000000000000..33b69d5fcb15 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/PutLinkWithServiceEndpoint.json @@ -0,0 +1,68 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "keyVaultSecretUri", + "value": "https://vault-name.vault.azure.net/secrets/secret-name/00000000000000000000000000000000" + } + }, + "vNetSolution": { + "type": "serviceEndpoint" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/ValidateLinkSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/ValidateLinkSuccess.json new file mode 100644 index 000000000000..5704a4b9f312 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/examples/ValidateLinkSuccess.json @@ -0,0 +1,35 @@ +{ + "parameters": { + "api-version": "2022-05-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "properties": { + "linkerName": "linkName", + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "sourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "targetId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/servicelinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/servicelinker.json new file mode 100644 index 000000000000..36c50fd40b7a --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/servicelinker.json @@ -0,0 +1,1043 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.ServiceLinker", + "description": "Microsoft.ServiceLinker provider", + "version": "2022-05-01" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow.", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers": { + "get": { + "deprecated": false, + "description": "Returns list of Linkers which connects to the resource.", + "operationId": "Linker_List", + "x-ms-examples": { + "LinkList": { + "$ref": "./examples/LinkList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "linker details.", + "schema": { + "$ref": "#/definitions/LinkerList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}": { + "get": { + "description": "Returns Linker resource for a given name.", + "operationId": "Linker_Get", + "x-ms-examples": { + "Link": { + "$ref": "./examples/Link.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update linker resource.", + "operationId": "Linker_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutLink": { + "$ref": "./examples/PutLink.json" + }, + "PutLinkWithServiceEndpoint": { + "$ref": "./examples/PutLinkWithServiceEndpoint.json" + }, + "PutLinkWithSecretStore": { + "$ref": "./examples/PutLinkWithSecretStore.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Links" + ], + "operationId": "Linker_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a link.", + "x-ms-examples": { + "DeleteLink": { + "$ref": "./examples/DeleteLink.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The link is deleted." + }, + "204": { + "description": "Deleted. The link is not found." + }, + "202": { + "description": "Long running operation." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Links" + ], + "operationId": "Linker_Update", + "description": "Operation to update an existing link.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchLink": { + "$ref": "./examples/PatchLink.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a link.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/validateLinker": { + "post": { + "tags": [ + "Links" + ], + "operationId": "Linker_Validate", + "description": "Validate a link.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ValidateLinkSuccess": { + "$ref": "./examples/ValidateLinkSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/listConfigurations": { + "post": { + "tags": [ + "Links" + ], + "operationId": "Linker_ListConfigurations", + "description": "list source configurations for a linker.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/GetConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/SourceConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/providers/Microsoft.ServiceLinker/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "description": "Lists the available ServiceLinker REST API operations.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/OperationsList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "TargetServiceType": { + "description": "The target service type.", + "type": "string", + "enum": [ + "AzureResource", + "ConfluentBootstrapServer", + "ConfluentSchemaRegistry" + ], + "x-ms-enum": { + "name": "targetServiceType", + "modelAsString": true + } + }, + "TargetServiceBase": { + "description": "The target service properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The target service type.", + "$ref": "#/definitions/TargetServiceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResourceType": { + "description": "The azure resource type.", + "type": "string", + "enum": [ + "KeyVault" + ], + "x-ms-enum": { + "name": "azureResourceType", + "modelAsString": true + } + }, + "AzureResourcePropertiesBase": { + "description": "The azure resource properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The azure resource type.", + "$ref": "#/definitions/AzureResourceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResource": { + "x-ms-discriminator-value": "AzureResource", + "type": "object", + "description": "The azure resource info when target service type is AzureResource", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "id": { + "description": "The Id of azure resource.", + "type": "string" + }, + "resourceProperties": { + "x-nullable": true, + "description": "The azure resource connection related properties.", + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + } + }, + "AzureKeyVaultProperties": { + "x-ms-discriminator-value": "KeyVault", + "type": "object", + "description": "The resource properties when type is Azure Key Vault", + "allOf": [ + { + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + ], + "properties": { + "connectAsKubernetesCsiDriver": { + "x-nullable": true, + "description": "True if connect via Kubernetes CSI Driver.", + "type": "boolean" + } + } + }, + "ConfluentBootstrapServer": { + "x-ms-discriminator-value": "ConfluentBootstrapServer", + "type": "object", + "description": "The service properties when target service type is ConfluentBootstrapServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "ConfluentSchemaRegistry": { + "x-ms-discriminator-value": "ConfluentSchemaRegistry", + "type": "object", + "description": "The service properties when target service type is ConfluentSchemaRegistry", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "AuthType": { + "description": "The authentication type.", + "type": "string", + "enum": [ + "systemAssignedIdentity", + "userAssignedIdentity", + "servicePrincipalSecret", + "servicePrincipalCertificate", + "secret" + ], + "x-ms-enum": { + "name": "AuthType", + "modelAsString": true + } + }, + "SecretType": { + "description": "The secret type.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecretUri", + "keyVaultSecretReference" + ], + "x-ms-enum": { + "name": "SecretType", + "modelAsString": true + } + }, + "SecretInfoBase": { + "description": "The secret info", + "discriminator": "secretType", + "type": "object", + "properties": { + "secretType": { + "description": "The secret type.", + "$ref": "#/definitions/SecretType" + } + }, + "required": [ + "secretType" + ] + }, + "ValueSecretInfo": { + "x-ms-discriminator-value": "rawValue", + "type": "object", + "description": "The secret info when type is rawValue. It's for scenarios that user input the secret.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "x-nullable": true, + "description": "The actual value of the secret.", + "type": "string", + "x-ms-secret": true + } + } + }, + "KeyVaultSecretReferenceSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretReference", + "type": "object", + "description": "The secret info when type is keyVaultSecretReference. It's for scenario that user provides a secret stored in user's keyvault and source is Azure Kubernetes. The key Vault's resource id is linked to secretStore.keyVaultId.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "name": { + "description": "Name of the Key Vault secret.", + "type": "string" + }, + "version": { + "x-nullable": true, + "description": "Version of the Key Vault secret.", + "type": "string" + } + } + }, + "KeyVaultSecretUriSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretUri", + "type": "object", + "description": "The secret info when type is keyVaultSecretUri. It's for scenario that user provides a secret stored in user's keyvault and source is Web App, Spring Cloud or Container App.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "description": "URI to the keyvault secret", + "type": "string" + } + } + }, + "AuthInfoBase": { + "description": "The authentication info", + "discriminator": "authType", + "type": "object", + "properties": { + "authType": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + } + }, + "required": [ + "authType" + ] + }, + "SecretAuthInfo": { + "x-ms-discriminator-value": "secret", + "type": "object", + "description": "The authentication info when authType is secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "name": { + "x-nullable": true, + "description": "Username or account name for secret auth.", + "type": "string" + }, + "secretInfo": { + "x-nullable": true, + "description": "Password or key vault secret for secret auth.", + "$ref": "#/definitions/SecretInfoBase" + } + } + }, + "UserAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "userAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is userAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Client Id for userAssignedIdentity.", + "type": "string" + }, + "subscriptionId": { + "description": "Subscription id for userAssignedIdentity.", + "type": "string" + } + } + }, + "SystemAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "systemAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is systemAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ] + }, + "ServicePrincipalSecretAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalSecret", + "type": "object", + "description": "The authentication info when authType is servicePrincipal secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "ServicePrincipal application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "secret": { + "description": "Secret for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + } + }, + "required": [ + "clientId", + "principalId", + "secret" + ] + }, + "ServicePrincipalCertificateAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalCertificate", + "type": "object", + "description": "The authentication info when authType is servicePrincipal certificate", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "certificate": { + "description": "ServicePrincipal certificate for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + } + }, + "required": [ + "clientId", + "principalId", + "certificate" + ] + }, + "LinkerResource": { + "type": "object", + "description": "Linker of source and target resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "required": [ + "properties" + ], + "properties": { + "properties": { + "description": "The properties of the linker.", + "$ref": "#/definitions/LinkerProperties", + "x-ms-client-flatten": true + }, + "systemData": { + "x-nullable": true, + "readOnly": true, + "$ref": "../../../../../common-types/resource-management/v2/types.json#/definitions/systemData", + "description": "The system data." + } + } + }, + "LinkerPatch": { + "description": "A linker to be updated.", + "type": "object", + "properties": { + "properties": { + "description": "Linker properties", + "type": "object", + "x-ms-client-flatten": true, + "$ref": "#/definitions/LinkerProperties" + } + } + }, + "LinkerList": { + "description": "The list of Linker.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The link used to get the next page of Linker list.", + "type": "string" + }, + "value": { + "description": "The list of Linkers.", + "type": "array", + "items": { + "$ref": "#/definitions/LinkerResource" + } + } + } + }, + "LinkerProperties": { + "description": "The properties of the linker.", + "type": "object", + "properties": { + "targetService": { + "$ref": "#/definitions/TargetServiceBase", + "description": "The target service properties" + }, + "authInfo": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthInfoBase" + }, + "clientType": { + "description": "The application client type", + "type": "string", + "enum": [ + "none", + "dotnet", + "java", + "python", + "go", + "php", + "ruby", + "django", + "nodejs", + "springBoot", + "kafka-springBoot" + ], + "x-ms-enum": { + "name": "clientType", + "modelAsString": true + } + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + }, + "vNetSolution": { + "x-nullable": true, + "description": "The VNet solution.", + "$ref": "#/definitions/VNetSolution" + }, + "secretStore": { + "x-nullable": true, + "description": "An option to store secret value in secure place", + "$ref": "#/definitions/SecretStore" + }, + "scope": { + "x-nullable": true, + "type": "string", + "description": "connection scope in source service." + } + } + }, + "SourceConfiguration": { + "description": "A configuration item for source resource", + "type": "object", + "properties": { + "name": { + "description": "The name of setting.", + "type": "string" + }, + "value": { + "x-nullable": true, + "description": "The value of setting", + "type": "string" + } + } + }, + "SourceConfigurationResult": { + "description": "Configurations for source resource, include appSettings, connectionString and serviceBindings", + "type": "object", + "properties": { + "configurations": { + "description": "The configuration properties for source resource.", + "type": "array", + "items": { + "$ref": "#/definitions/SourceConfiguration" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidateOperationResult": { + "description": "The validation operation result for a linker.", + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The validation result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ValidateResult" + }, + "resourceId": { + "x-nullable": true, + "description": "Validated linker id.", + "type": "string" + }, + "status": { + "x-nullable": true, + "description": "Validation operation status.", + "type": "string" + } + } + }, + "ValidateResult": { + "description": "The validation result for a linker.", + "type": "object", + "properties": { + "linkerName": { + "x-nullable": true, + "description": "The linker name.", + "type": "string" + }, + "isConnectionAvailable": { + "x-nullable": true, + "description": "A boolean value indicating whether the connection is available or not", + "type": "boolean" + }, + "reportStartTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The start time of the validation report." + }, + "reportEndTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The end time of the validation report." + }, + "sourceId": { + "x-nullable": true, + "description": "The resource id of the linker source application.", + "type": "string" + }, + "targetId": { + "x-nullable": true, + "description": "The resource Id of target service.", + "type": "string" + }, + "authType": { + "x-nullable": true, + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "validationDetail": { + "description": "The detail of validation result", + "type": "array", + "items": { + "$ref": "#/definitions/ValidationResultItem" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidationResultItem": { + "description": "The validation item for a linker.", + "type": "object", + "properties": { + "name": { + "description": "The validation item name.", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "The display name of validation item", + "type": "string" + }, + "result": { + "x-nullable": true, + "description": "The result of validation", + "type": "string", + "enum": [ + "success", + "failure", + "warning" + ], + "x-ms-enum": { + "name": "ValidationResultStatus", + "modelAsString": true + } + }, + "errorMessage": { + "x-nullable": true, + "description": "The error message of validation result", + "type": "string" + }, + "errorCode": { + "x-nullable": true, + "description": "The error code of validation result", + "type": "string" + } + } + }, + "VNetSolution": { + "type": "object", + "description": "The VNet solution for linker", + "properties": { + "type": { + "x-nullable": true, + "description": "Type of VNet solution.", + "type": "string", + "enum": [ + "serviceEndpoint", + "privateLink" + ], + "x-ms-enum": { + "name": "vNetSolutionType", + "modelAsString": true + } + } + } + }, + "SecretStore": { + "type": "object", + "description": "An option to store secret value in secure place", + "properties": { + "keyVaultId": { + "x-nullable": true, + "type": "string", + "description": "The key vault id to store secret" + } + } + } + }, + "parameters": { + "LinkerNameParameter": { + "name": "linkerName", + "in": "path", + "required": true, + "type": "string", + "description": "The name Linker resource.", + "x-ms-parameter-location": "method" + }, + "ResourceUriParameter": { + "name": "resourceUri", + "in": "path", + "required": true, + "type": "string", + "description": "The fully qualified Azure Resource manager identifier of the resource to be connected.", + "x-ms-skip-url-encoding": true, + "x-ms-parameter-location": "method" + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConfigurationNamesList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConfigurationNamesList.json new file mode 100644 index 000000000000..e78bcd89e157 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConfigurationNamesList.json @@ -0,0 +1,52 @@ +{ + "parameters": { + "api-version": "2024-04-01" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "targetService": "MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES", + "clientType": "none", + "authType": "systemAssignedIdentity", + "names": [ + { + "value": "AZURE_APPCONFIGURATION_ENDPOINT", + "description": "App configuration endpoint" + }, + { + "value": "AZURE_APPCONFIGURATION_SCOPE", + "description": "The scopes required for the token." + } + ] + } + }, + { + "properties": { + "targetService": "MICROSOFT.APPCONFIGURATION/CONFIGURATIONSTORES", + "clientType": "none", + "authType": "userAssignedIdentity", + "names": [ + { + "value": "AZURE_APPCONFIGURATION_ENDPOINT", + "description": "App configuration endpoint" + }, + { + "value": "AZURE_APPCONFIGURATION_CLIENTID", + "description": "The client(application) ID of the user identity." + }, + { + "value": "AZURE_APPCONFIGURATION_SCOPE", + "description": "The scopes required for getting token." + } + ] + } + } + ], + "nextLink": null + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunCreate.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunCreate.json new file mode 100644 index 000000000000..f5f690730a3c --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunCreate.json @@ -0,0 +1,116 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "201": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Accepted" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunDelete.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunDelete.json new file mode 100644 index 000000000000..a2bae803c32a --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunDelete.json @@ -0,0 +1,13 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName" + }, + "responses": { + "200": {}, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunGet.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunGet.json new file mode 100644 index 000000000000..e4aa9704d7e2 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunGet.json @@ -0,0 +1,33 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName" + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunList.json new file mode 100644 index 000000000000..ef3f43ad4e14 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunList.json @@ -0,0 +1,36 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunUpdate.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunUpdate.json new file mode 100644 index 000000000000..adc1ea615588 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorDryrunUpdate.json @@ -0,0 +1,78 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "name": "dryrunName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/locations/westus/dryruns/dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorList.json new file mode 100644 index 000000000000..dc6561c8b804 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ConnectorList.json @@ -0,0 +1,34 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/linkers/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/devConnectors", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/Connectors.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/Connectors.json new file mode 100644 index 000000000000..c75b7998a450 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/Connectors.json @@ -0,0 +1,43 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/devConnnectors/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/devConnectors", + "properties": { + "authInfo": { + "authType": "systemAssignedIdentity", + "roles": [ + "customizedOwner" + ] + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "publicNetworkSolution": { + "firewallRules": { + "ipRanges": [ + "182.22.120" + ], + "callerClientIP": "true" + }, + "action": "enable", + "deleteOrUpdateBehavior": "ForcedCleanup" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteConnector.json new file mode 100644 index 000000000000..ee18d68b35c3 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteConnector.json @@ -0,0 +1,18 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": {}, + "204": {}, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteDryrun.json new file mode 100644 index 000000000000..6170545eefdf --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteDryrun.json @@ -0,0 +1,11 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName" + }, + "responses": { + "200": {}, + "204": {} + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteLinker.json new file mode 100644 index 000000000000..9d03d6e82f6e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/DeleteLinker.json @@ -0,0 +1,16 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": {}, + "204": {}, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GenerateConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GenerateConfigurations.json new file mode 100644 index 000000000000..ce8d8ca14863 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GenerateConfigurations.json @@ -0,0 +1,26 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "customizedKeys": { + "ASL_DocumentDb_ConnectionString": "MyConnectionstring" + } + } + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "MyConnectionstring", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetConfigurations.json new file mode 100644 index 000000000000..54118985b95a --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetConfigurations.json @@ -0,0 +1,41 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.App/containerApps/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "AZURE_POSTGRESQL_HOST", + "value": "Host", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_USER", + "value": "Username", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_DATABASE", + "value": "DatabaseName", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_PORT", + "value": "Port", + "configType": "Default" + }, + { + "name": "AZURE_POSTGRESQL_PASSWORD", + "value": "SecretUri", + "configType": "KeyVaultSecret", + "keyVaultReferenceIdentity": "system" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetDaprConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetDaprConfigurations.json new file mode 100644 index 000000000000..4154317a74c1 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetDaprConfigurations.json @@ -0,0 +1,33 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "properties": { + "targetType": "MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES", + "authType": "secret", + "daprProperties": { + "version": "v1", + "componentType": "bindings", + "runtimeVersion": "1.10", + "bindingComponentDirection": "input", + "metadata": [ + { + "name": "containerName", + "description": "The name of the container to be used for Dapr state.", + "required": "true" + } + ] + } + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetDryrun.json new file mode 100644 index 000000000000..ecdc7df7acda --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/GetDryrun.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "name": "dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/Linker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/Linker.json new file mode 100644 index 000000000000..d09f31330555 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/Linker.json @@ -0,0 +1,47 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/kvname" + }, + "scope": "AKS-Namespace", + "clientType": "dotnet", + "publicNetworkSolution": { + "action": "enable" + }, + "configurationInfo": { + "deleteOrUpdateBehavior": "ForcedCleanup", + "customizedKeys": { + "AZURE_MYSQL_CONNECTIONSTRING": "myConnectionstring", + "AZURE_MYSQL_SSLMODE": "mySslmode" + }, + "additionalConfigurations": { + "throttlingLimit": "100" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/LinkerGenerateConfigurations.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/LinkerGenerateConfigurations.json new file mode 100644 index 000000000000..17261ebabd97 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/LinkerGenerateConfigurations.json @@ -0,0 +1,24 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "customizedKeys": { + "ASL_DocumentDb_ConnectionString": "MyConnectionstring" + } + } + }, + "responses": { + "200": { + "body": { + "configurations": [ + { + "name": "MyConnectionstring", + "value": "ConnectionString" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/LinkerList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/LinkerList.json new file mode 100644 index 000000000000..ac851789d850 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/LinkerList.json @@ -0,0 +1,32 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.ServiceLinker/links/linkName", + "name": "linkName", + "type": "Microsoft.ServiceLinker/links", + "properties": { + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ListDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ListDryrun.json new file mode 100644 index 000000000000..7425c56a7c5e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ListDryrun.json @@ -0,0 +1,35 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "name": "dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "authInfo": { + "authType": "secret", + "name": "username" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + }, + "systemData": { + "createdAt": "2020-07-12T22:05:09Z" + } + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/OperationsList.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/OperationsList.json new file mode 100644 index 000000000000..4db0c00028ba --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/OperationsList.json @@ -0,0 +1,184 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app" + }, + "responses": { + "200": { + "body": { + "value": [ + { + "display": { + "description": "Register the subscription for Microsoft.ServiceLinker", + "operation": "Register the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/register/action" + }, + { + "display": { + "description": "Unregister the subscription for Microsoft.ServiceLinker", + "operation": "Unregister the Microsoft.ServiceLinker", + "provider": "Microsoft.ServiceLinker", + "resource": "Microsoft.ServiceLinker" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/unregister/action" + }, + { + "display": { + "description": "read operations", + "operation": "read_operations", + "provider": "Microsoft.ServiceLinker", + "resource": "operations" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/operations/read" + }, + { + "display": { + "description": "list dryrun jobs", + "operation": "Dryrun_List", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "get a dryrun job", + "operation": "Dryrun_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/read" + }, + { + "display": { + "description": "create a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Create", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "delete a dryrun job", + "operation": "Dryrun_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/delete" + }, + { + "display": { + "description": "add a dryrun job to do necessary check before actual creation", + "operation": "Dryrun_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "dryruns" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/dryruns/write" + }, + { + "display": { + "description": "read operationStatuses", + "operation": "read_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/read" + }, + { + "display": { + "description": "write operationStatuses", + "operation": "write_operationStatuses", + "provider": "Microsoft.ServiceLinker", + "resource": "locations/operationStatuses" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/locations/operationStatuses/write" + }, + { + "display": { + "description": "Returns list of Linkers which connects to the resource.", + "operation": "Linker_List", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Returns Linker resource for a given name.", + "operation": "Linker_Get", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/read" + }, + { + "display": { + "description": "Create or update linker resource.", + "operation": "Linker_CreateOrUpdate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Delete a link.", + "operation": "Linker_Delete", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/delete" + }, + { + "display": { + "description": "Operation to update an existing link.", + "operation": "Linker_Update", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/write" + }, + { + "display": { + "description": "Validate a link.", + "operation": "Linker_Validate", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/validateLinker/action" + }, + { + "display": { + "description": "list source configurations for a linker.", + "operation": "Linker_ListConfigurations", + "provider": "Microsoft.ServiceLinker", + "resource": "linkers" + }, + "isDataAction": false, + "name": "Microsoft.ServiceLinker/linkers/listConfigurations/action" + } + ] + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchConnector.json new file mode 100644 index 000000000000..2d33a6ac50b8 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchConnector.json @@ -0,0 +1,64 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "202": { + "headers": { + "azure-asyncoperation": "http://azure.async.operation/status" + }, + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchDryrun.json new file mode 100644 index 000000000000..fe0fbc9e9342 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchDryrun.json @@ -0,0 +1,77 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchLinker.json new file mode 100644 index 000000000000..f43d2a751af7 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PatchLinker.json @@ -0,0 +1,59 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id", + "secret": "secret" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "servicePrincipalSecret", + "clientId": "name", + "principalId": "id" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutConnector.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutConnector.json new file mode 100644 index 000000000000..e59f28e633dd --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutConnector.json @@ -0,0 +1,63 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "properties": { + "authInfo": { + "authType": "secret" + }, + "secretStore": { + "keyVaultId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.KeyVault/vaults/test-kv" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutDryrun.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutDryrun.json new file mode 100644 index 000000000000..91619e5257a6 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutDryrun.json @@ -0,0 +1,116 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "dryrunName": "dryrunName", + "parameters": { + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + } + }, + "responses": { + "200": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Succeeded" + } + } + }, + "201": { + "body": { + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/dryruns/dryrunName", + "type": "Microsoft.ServiceLinker/dryruns", + "name": "dryrunName", + "properties": { + "parameters": { + "actionName": "createOrUpdate", + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db" + }, + "authInfo": { + "authType": "secret", + "name": "name" + } + }, + "prerequisiteResults": [ + { + "type": "basicError", + "code": "ResourceNotFound", + "message": "Target resource is not found" + }, + { + "type": "permissionsMissing", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc", + "permissions": [ + "Microsoft.DocumentDb/databaseAccounts/write" + ] + } + ], + "operationPreviews": [ + { + "name": "configFirewallRule", + "operationType": "configNetwork", + "description": "Config firewall rule for target service to allow source service access", + "action": "Microsoft.DocumentDb/databaseAccounts/write", + "scope": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc" + } + ], + "provisioningState": "Updating" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutLinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutLinker.json new file mode 100644 index 000000000000..679db2cb61f2 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/PutLinker.json @@ -0,0 +1,68 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName", + "parameters": { + "properties": { + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "authInfo": { + "authType": "secret", + "name": "name", + "secretInfo": { + "secretType": "rawValue", + "value": "secret" + } + } + } + } + }, + "responses": { + "200": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + }, + "201": { + "body": { + "type": "Microsoft.ServiceLinker/links", + "name": "linkName", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app/providers/Microsoft.ServiceLinker/links/linkName", + "properties": { + "authInfo": { + "authType": "secret", + "name": "name" + }, + "vNetSolution": { + "type": "serviceEndpoint" + }, + "targetService": { + "type": "AzureResource", + "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforPostgreSQL/servers/test-pg/databases/test-db" + } + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ValidateConnectorSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ValidateConnectorSuccess.json new file mode 100644 index 000000000000..ca8ab2093d98 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ValidateConnectorSuccess.json @@ -0,0 +1,38 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "subscriptionId": "00000000-0000-0000-0000-000000000000", + "resourceGroupName": "test-rg", + "location": "westus", + "connectorName": "connectorName" + }, + "responses": { + "200": { + "body": { + "properties": { + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ValidateLinkerSuccess.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ValidateLinkerSuccess.json new file mode 100644 index 000000000000..9bbe684cf2dd --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/examples/ValidateLinkerSuccess.json @@ -0,0 +1,38 @@ +{ + "parameters": { + "api-version": "2024-04-01", + "resourceUri": "subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/test-app", + "linkerName": "linkName" + }, + "responses": { + "200": { + "body": { + "properties": { + "isConnectionAvailable": true, + "reportStartTimeUtc": "2020-07-12T22:05:09Z", + "reportEndTimeUtc": "2020-07-12T22:06:09Z", + "sourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "targetId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DocumentDb/databaseAccounts/test-acc/mongodbDatabases/test-db", + "authType": "secret", + "validationDetail": [ + { + "name": "TargetExistence", + "description": "The target existence is validated", + "result": "success" + }, + { + "name": "TargetNetworkAccess", + "description": "Deny public network access is set to yes. Please confirm you are using private endpoint connection to access target resource.", + "result": "warning" + } + ] + } + } + }, + "202": { + "headers": { + "azure-AsyncOperation": "http://azure.async.operation/status" + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/servicelinker.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/servicelinker.json new file mode 100644 index 000000000000..011ae9cf4964 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/servicelinker.json @@ -0,0 +1,2902 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.ServiceLinker", + "description": "Microsoft.ServiceLinker provider", + "version": "2024-04-01" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow.", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ConnectorDryrunList": { + "$ref": "./examples/ConnectorDryrunList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "ConnectorDryrunGet": { + "$ref": "./examples/ConnectorDryrunGet.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "Connector" + ], + "operationId": "Connector_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunCreate": { + "$ref": "./examples/ConnectorDryrunCreate.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "201": { + "description": "Long running operation", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Connector" + ], + "operationId": "Connector_UpdateDryrun", + "description": "update a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunUpdate": { + "$ref": "./examples/ConnectorDryrunUpdate.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunPatch" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Connector" + ], + "operationId": "Connector_DeleteDryrun", + "description": "delete a dryrun job", + "x-ms-examples": { + "ConnectorDryrunDelete": { + "$ref": "./examples/ConnectorDryrunDelete.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The job is deleted." + }, + "204": { + "description": "Deleted. The job is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors": { + "get": { + "deprecated": false, + "description": "Returns list of connector which connects to the resource, which supports to config the target service during the resource provision.", + "operationId": "Connector_List", + "x-ms-examples": { + "ConnectorList": { + "$ref": "./examples/ConnectorList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Connector details.", + "schema": { + "$ref": "#/definitions/ResourceList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}": { + "get": { + "description": "Returns Connector resource for a given name.", + "operationId": "Connector_Get", + "x-ms-examples": { + "Connector": { + "$ref": "./examples/Connectors.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Connector details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update Connector resource.", + "operationId": "Connector_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutConnector": { + "$ref": "./examples/PutConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connector details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a Connector.", + "x-ms-examples": { + "DeleteConnector": { + "$ref": "./examples/DeleteConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The Connector is deleted." + }, + "202": { + "description": "Long running operation." + }, + "204": { + "description": "Deleted. The Connector is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Update", + "description": "Operation to update an existing Connector.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchConnector": { + "$ref": "./examples/PatchConnector.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connector details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a Connector.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "202": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}/validate": { + "post": { + "tags": [ + "Connector" + ], + "operationId": "Connector_Validate", + "description": "Validate a Connector.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-examples": { + "ValidateConnectorSuccess": { + "$ref": "./examples/ValidateConnectorSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/connectors/{connectorName}/generateConfigurations": { + "post": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GenerateConfigurations", + "description": "Generate configurations for a Connector.", + "x-ms-examples": { + "GenerateConfiguration": { + "$ref": "./examples/GenerateConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/SubscriptionIdParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ResourceGroupNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/LocationParameter" + }, + { + "$ref": "#/parameters/ConnectorNameParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "parameters", + "description": "Connection Info, including format, secret store, etc", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ConfigurationInfo" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers": { + "get": { + "deprecated": false, + "description": "Returns list of Linkers which connects to the resource. which supports to config both application and target service during the resource provision.", + "operationId": "Linker_List", + "x-ms-examples": { + "LinkerList": { + "$ref": "./examples/LinkerList.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/ResourceList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}": { + "get": { + "description": "Returns Linker resource for a given name.", + "operationId": "Linker_Get", + "x-ms-examples": { + "Linker": { + "$ref": "./examples/Linker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "Linker details.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "description": "Create or update Linker resource.", + "operationId": "Linker_CreateOrUpdate", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutLinker": { + "$ref": "./examples/PutLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerResource" + } + } + ], + "responses": { + "200": { + "description": "Successful.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Delete", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "description": "Delete a Linker.", + "x-ms-examples": { + "DeleteLinker": { + "$ref": "./examples/DeleteLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The Linker is deleted." + }, + "202": { + "description": "Long running operation." + }, + "204": { + "description": "Deleted. The Linker is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Update", + "description": "Operation to update an existing Linker.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchLinker": { + "$ref": "./examples/PatchLinker.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Linker details.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LinkerPatch" + } + } + ], + "responses": { + "200": { + "description": "Success. The response describes a Linker.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "201": { + "description": "Long running operation.", + "schema": { + "$ref": "#/definitions/LinkerResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/validateLinker": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_Validate", + "description": "Validate a Linker.", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "location" + }, + "x-ms-examples": { + "ValidateLinkerSuccess": { + "$ref": "./examples/ValidateLinkerSuccess.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ValidateOperationResult" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/listConfigurations": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linker_ListConfigurations", + "description": "list source configurations for a Linker.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/GetConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/dryruns": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ListDryrun": { + "$ref": "./examples/ListDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "GetDryrun": { + "$ref": "./examples/GetDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "put": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PutDryrun": { + "$ref": "./examples/PutDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "201": { + "description": "Long running operation", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "patch": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_UpdateDryrun", + "description": "add a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "PatchDryrun": { + "$ref": "./examples/PatchDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + }, + { + "name": "parameters", + "description": "dryrun resource.", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DryrunPatch" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + }, + "202": { + "description": "Accepted - Returns this status until the asynchronous operation has completed." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + }, + "delete": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_DeleteDryrun", + "description": "delete a dryrun job", + "x-ms-examples": { + "DeleteDryrun": { + "$ref": "./examples/DeleteDryrun.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "dryrunName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of dryrun.", + "x-ms-parameter-location": "method" + } + ], + "responses": { + "200": { + "description": "OK. The job is deleted." + }, + "204": { + "description": "Deleted. The job is not found." + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/linkers/{linkerName}/generateConfigurations": { + "post": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_GenerateConfigurations", + "description": "Generate configurations for a Linker.", + "x-ms-examples": { + "GenerateConfiguration": { + "$ref": "./examples/LinkerGenerateConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "$ref": "#/parameters/LinkerNameParameter" + }, + { + "name": "parameters", + "description": "Connection Info, including format, secret store, etc", + "in": "body", + "required": false, + "schema": { + "$ref": "#/definitions/ConfigurationInfo" + } + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + } + } + }, + "/providers/Microsoft.ServiceLinker/operations": { + "get": { + "tags": [ + "Operations" + ], + "operationId": "Operations_List", + "description": "Lists the available ServiceLinker REST API operations.", + "x-ms-examples": { + "GetConfiguration": { + "$ref": "./examples/OperationsList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/OperationListResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/providers/Microsoft.ServiceLinker/configurationNames": { + "get": { + "tags": [ + "ConfigurationNames" + ], + "operationId": "ConfigurationNames_List", + "description": "Lists the configuration names generated by Service Connector for all target, client types, auth types.", + "x-ms-examples": { + "GetConfigurationNames": { + "$ref": "./examples/ConfigurationNamesList.json" + } + }, + "parameters": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + }, + { + "name": "$filter", + "in": "query", + "required": false, + "type": "string", + "description": "OData filter options." + }, + { + "name": "$skipToken", + "in": "query", + "required": false, + "type": "string", + "description": "OData skipToken option for pagination." + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/ConfigurationNameResult" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + }, + "/{resourceUri}/providers/Microsoft.ServiceLinker/daprConfigurations": { + "get": { + "tags": [ + "Linkers" + ], + "operationId": "Linkers_ListDaprConfigurations", + "description": "List the dapr configuration supported by Service Connector.", + "x-ms-examples": { + "GetDaprConfigurations": { + "$ref": "./examples/GetDaprConfigurations.json" + } + }, + "parameters": [ + { + "$ref": "#/parameters/ResourceUriParameter" + }, + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/parameters/ApiVersionParameter" + } + ], + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DaprConfigurationList" + } + }, + "default": { + "description": "Error response describing why the operation failed.", + "schema": { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ErrorResponse" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "definitions": { + "TargetServiceType": { + "description": "The target service type.", + "type": "string", + "enum": [ + "AzureResource", + "ConfluentBootstrapServer", + "ConfluentSchemaRegistry", + "SelfHostedServer" + ], + "x-ms-enum": { + "name": "targetServiceType", + "modelAsString": true + } + }, + "TargetServiceBase": { + "description": "The target service properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The target service type.", + "$ref": "#/definitions/TargetServiceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResourceType": { + "description": "The azure resource type.", + "type": "string", + "enum": [ + "KeyVault" + ], + "x-ms-enum": { + "name": "azureResourceType", + "modelAsString": true + } + }, + "AzureResourcePropertiesBase": { + "description": "The azure resource properties", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "description": "The azure resource type.", + "$ref": "#/definitions/AzureResourceType" + } + }, + "required": [ + "type" + ] + }, + "AzureResource": { + "x-ms-discriminator-value": "AzureResource", + "type": "object", + "description": "The azure resource info when target service type is AzureResource", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "id": { + "description": "The Id of azure resource.", + "type": "string" + }, + "resourceProperties": { + "x-nullable": true, + "description": "The azure resource connection related properties.", + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + } + }, + "AzureKeyVaultProperties": { + "x-ms-discriminator-value": "KeyVault", + "type": "object", + "description": "The resource properties when type is Azure Key Vault", + "allOf": [ + { + "$ref": "#/definitions/AzureResourcePropertiesBase" + } + ], + "properties": { + "connectAsKubernetesCsiDriver": { + "x-nullable": true, + "description": "True if connect via Kubernetes CSI Driver.", + "type": "boolean" + } + } + }, + "ConfluentBootstrapServer": { + "x-ms-discriminator-value": "ConfluentBootstrapServer", + "type": "object", + "description": "The service properties when target service type is ConfluentBootstrapServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "SelfHostedServer": { + "x-ms-discriminator-value": "SelfHostedServer", + "type": "object", + "description": "The service properties when target service type is SelfHostedServer", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "ConfluentSchemaRegistry": { + "x-ms-discriminator-value": "ConfluentSchemaRegistry", + "type": "object", + "description": "The service properties when target service type is ConfluentSchemaRegistry", + "allOf": [ + { + "$ref": "#/definitions/TargetServiceBase" + } + ], + "properties": { + "endpoint": { + "description": "The endpoint of service.", + "type": "string" + } + } + }, + "DeleteOrUpdateBehavior": { + "description": "The cleanup behavior to indicate whether clean up operation when resource is deleted or updated", + "type": "string", + "enum": [ + "Default", + "ForcedCleanup" + ], + "x-ms-enum": { + "name": "DeleteOrUpdateBehavior", + "modelAsString": true + } + }, + "ClientType": { + "description": "The application client type", + "type": "string", + "enum": [ + "none", + "dotnet", + "java", + "python", + "go", + "php", + "ruby", + "django", + "nodejs", + "springBoot", + "kafka-springBoot", + "jms-springBoot", + "dapr" + ], + "x-ms-enum": { + "name": "clientType", + "modelAsString": true + } + }, + "AuthType": { + "description": "The authentication type.", + "type": "string", + "enum": [ + "systemAssignedIdentity", + "userAssignedIdentity", + "servicePrincipalSecret", + "servicePrincipalCertificate", + "secret", + "accessKey", + "userAccount", + "easyAuthMicrosoftEntraID" + ], + "x-ms-enum": { + "name": "AuthType", + "modelAsString": true + } + }, + "SecretType": { + "description": "The secret type.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecretUri", + "keyVaultSecretReference" + ], + "x-ms-enum": { + "name": "SecretType", + "modelAsString": true + } + }, + "SecretSourceType": { + "description": "The type of secret source.", + "type": "string", + "enum": [ + "rawValue", + "keyVaultSecret" + ], + "x-ms-enum": { + "name": "SecretSourceType", + "modelAsString": true + } + }, + "SecretInfoBase": { + "description": "The secret info", + "discriminator": "secretType", + "type": "object", + "properties": { + "secretType": { + "description": "The secret type.", + "$ref": "#/definitions/SecretType" + } + }, + "required": [ + "secretType" + ] + }, + "ValueSecretInfo": { + "x-ms-discriminator-value": "rawValue", + "type": "object", + "description": "The secret info when type is rawValue. It's for scenarios that user input the secret.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "x-nullable": true, + "description": "The actual value of the secret.", + "type": "string", + "x-ms-secret": true + } + } + }, + "KeyVaultSecretReferenceSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretReference", + "type": "object", + "description": "The secret info when type is keyVaultSecretReference. It's for scenario that user provides a secret stored in user's keyvault and source is Azure Kubernetes. The key Vault's resource id is linked to secretStore.keyVaultId.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "name": { + "description": "Name of the Key Vault secret.", + "type": "string" + }, + "version": { + "x-nullable": true, + "description": "Version of the Key Vault secret.", + "type": "string" + } + } + }, + "KeyVaultSecretUriSecretInfo": { + "x-ms-discriminator-value": "keyVaultSecretUri", + "type": "object", + "description": "The secret info when type is keyVaultSecretUri. It's for scenario that user provides a secret stored in user's keyvault and source is Web App, Spring Cloud or Container App.", + "allOf": [ + { + "$ref": "#/definitions/SecretInfoBase" + } + ], + "properties": { + "value": { + "description": "URI to the keyvault secret", + "type": "string" + } + } + }, + "AuthInfoBase": { + "description": "The authentication info", + "discriminator": "authType", + "type": "object", + "properties": { + "authType": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "authMode": { + "description": "Optional. Indicates how to configure authentication. If optInAllAuth, service linker configures authentication such as enabling identity on source resource and granting RBAC roles. If optOutAllAuth, opt out authentication setup. Default is optInAllAuth.", + "$ref": "#/definitions/AuthMode" + } + }, + "required": [ + "authType" + ] + }, + "AccessKeyInfoBase": { + "description": "The access key directly from target resource properties, which target service is Azure Resource, such as Microsoft.Storage", + "x-ms-discriminator-value": "accessKey", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "permissions": { + "description": "Permissions of the accessKey. `Read` and `Write` are for Azure Cosmos DB and Azure App Configuration, `Listen`, `Send` and `Manage` are for Azure Event Hub and Azure Service Bus.", + "type": "array", + "items": { + "type": "string", + "enum": [ + "Read", + "Write", + "Listen", + "Send", + "Manage" + ], + "x-ms-enum": { + "name": "accessKeyPermissions", + "modelAsString": true + } + } + } + } + }, + "DatabaseAadAuthInfo": { + "description": "The extra auth info required by Database AAD authentication.", + "type": "object", + "properties": { + "userName": { + "x-nullable": true, + "description": "Username created in the database which is mapped to a user in AAD.", + "type": "string" + } + } + }, + "SecretAuthInfo": { + "x-ms-discriminator-value": "secret", + "type": "object", + "description": "The authentication info when authType is secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "name": { + "x-nullable": true, + "description": "Username or account name for secret auth.", + "type": "string" + }, + "secretInfo": { + "x-nullable": true, + "description": "Password or key vault secret for secret auth.", + "$ref": "#/definitions/SecretInfoBase" + } + } + }, + "UserAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "userAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is userAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "clientId": { + "description": "Client Id for userAssignedIdentity.", + "type": "string" + }, + "subscriptionId": { + "description": "Subscription id for userAssignedIdentity.", + "type": "string" + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure role to be assigned" + } + } + }, + "SystemAssignedIdentityAuthInfo": { + "x-ms-discriminator-value": "systemAssignedIdentity", + "type": "object", + "description": "The authentication info when authType is systemAssignedIdentity", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure role to be assigned" + } + } + }, + "ServicePrincipalSecretAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalSecret", + "type": "object", + "description": "The authentication info when authType is servicePrincipal secret", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "clientId": { + "description": "ServicePrincipal application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "secret": { + "description": "Secret for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + }, + "required": [ + "clientId", + "principalId", + "secret" + ] + }, + "ServicePrincipalCertificateAuthInfo": { + "x-ms-discriminator-value": "servicePrincipalCertificate", + "type": "object", + "description": "The authentication info when authType is servicePrincipal certificate", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for servicePrincipal auth.", + "type": "string" + }, + "principalId": { + "description": "Principal Id for servicePrincipal auth.", + "type": "string" + }, + "certificate": { + "description": "ServicePrincipal certificate for servicePrincipal auth.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + }, + "required": [ + "clientId", + "principalId", + "certificate" + ] + }, + "UserAccountAuthInfo": { + "x-ms-discriminator-value": "userAccount", + "type": "object", + "description": "The authentication info when authType is user account", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + }, + { + "$ref": "#/definitions/DatabaseAadAuthInfo" + } + ], + "properties": { + "principalId": { + "description": "Principal Id for user account.", + "type": "string" + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Optional, this value specifies the Azure roles to be assigned. Automatically " + } + } + }, + "EasyAuthMicrosoftEntraIDAuthInfo": { + "x-ms-discriminator-value": "easyAuthMicrosoftEntraID", + "type": "object", + "description": "The authentication info when authType is EasyAuth Microsoft Entra ID", + "allOf": [ + { + "$ref": "#/definitions/AuthInfoBase" + } + ], + "properties": { + "clientId": { + "description": "Application clientId for EasyAuth Microsoft Entra ID.", + "type": "string" + }, + "secret": { + "description": "Application Secret for EasyAuth Microsoft Entra ID.", + "type": "string", + "x-ms-secret": true + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + } + } + }, + "LinkerResource": { + "type": "object", + "description": "Linker of source and target resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "required": [ + "properties" + ], + "properties": { + "properties": { + "description": "The properties of the Linker.", + "$ref": "#/definitions/LinkerProperties", + "x-ms-client-flatten": true + }, + "systemData": { + "x-nullable": true, + "readOnly": true, + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/systemData", + "description": "The system data." + } + } + }, + "LinkerPatch": { + "description": "A Linker to be updated.", + "type": "object", + "properties": { + "properties": { + "description": "Linker properties", + "type": "object", + "x-ms-client-flatten": true, + "$ref": "#/definitions/LinkerProperties" + } + } + }, + "ResourceList": { + "description": "The list of Linker.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The Linker used to get the next page of Linker list.", + "type": "string" + }, + "value": { + "description": "The list of Linkers.", + "type": "array", + "items": { + "$ref": "#/definitions/LinkerResource" + } + } + } + }, + "LinkerProperties": { + "description": "The properties of the Linker.", + "type": "object", + "properties": { + "targetService": { + "$ref": "#/definitions/TargetServiceBase", + "description": "The target service properties" + }, + "authInfo": { + "description": "The authentication type.", + "$ref": "#/definitions/AuthInfoBase" + }, + "clientType": { + "description": "The application client type", + "$ref": "#/definitions/ClientType" + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + }, + "vNetSolution": { + "x-nullable": true, + "description": "The VNet solution.", + "$ref": "#/definitions/VNetSolution" + }, + "secretStore": { + "x-nullable": true, + "description": "An option to store secret value in secure place", + "$ref": "#/definitions/SecretStore" + }, + "scope": { + "x-nullable": true, + "type": "string", + "description": "connection scope in source service." + }, + "publicNetworkSolution": { + "x-nullable": true, + "description": "The network solution.", + "$ref": "#/definitions/PublicNetworkSolution" + }, + "configurationInfo": { + "x-nullable": true, + "description": "The connection information consumed by applications, including secrets, connection strings.", + "$ref": "#/definitions/ConfigurationInfo" + } + } + }, + "LinkerConfigurationType": { + "description": "Type of configuration to determine whether the configuration can be modified after creation. KeyvaultSecret means the configuration references a key vault secret, such as App Service/ACA key vault reference. Default means the configuration is real value, such as user name, raw secret, etc.", + "type": "string", + "enum": [ + "Default", + "KeyVaultSecret" + ], + "x-ms-enum": { + "name": "LinkerConfigurationType", + "modelAsString": true + } + }, + "SourceConfiguration": { + "description": "A configuration item for source resource", + "type": "object", + "properties": { + "name": { + "description": "The name of setting.", + "type": "string" + }, + "value": { + "x-nullable": true, + "description": "The value of setting", + "type": "string" + }, + "configType": { + "description": "The type of setting", + "readOnly": true, + "$ref": "#/definitions/LinkerConfigurationType" + }, + "keyVaultReferenceIdentity": { + "x-nullable": true, + "description": "The identity for key vault reference, system or user-assigned managed identity ID", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "Descriptive information for the configuration", + "type": "string" + } + } + }, + "ConfigurationNameItem": { + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ConfigurationNames" + } + } + }, + "ConfigurationNames": { + "type": "object", + "description": "The configuration names which will be set based on specific target resource, client type, auth type.", + "properties": { + "targetService": { + "type": "string", + "description": "The target service provider name and resource name." + }, + "clientType": { + "$ref": "#/definitions/ClientType", + "description": "The client type for configuration names." + }, + "authType": { + "$ref": "#/definitions/AuthType", + "description": "The auth type." + }, + "secretType": { + "$ref": "#/definitions/SecretSourceType", + "description": "Indicates where the secrets in configuration from. Used when secrets are from Keyvault." + }, + "daprProperties": { + "description": "Deprecated, please use #/definitions/DaprConfigurationList instead", + "$ref": "#/definitions/DaprProperties" + }, + "names": { + "type": "array", + "description": "The configuration names to be set in compute service environment.", + "items": { + "$ref": "#/definitions/ConfigurationName" + } + } + } + }, + "ConfigurationName": { + "type": "object", + "description": "The configuration names.", + "properties": { + "value": { + "type": "string" + }, + "description": { + "type": "string", + "description": "Description for the configuration name." + }, + "required": { + "type": "boolean", + "description": "Represent the configuration is required or not" + } + } + }, + "ConfigurationNameResult": { + "description": "Configuration Name list which will be set based on different target resource, client type, auth type.", + "type": "object", + "properties": { + "value": { + "description": "Expected configuration names for each target service.", + "type": "array", + "items": { + "$ref": "#/definitions/ConfigurationNameItem" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "description": "Link to next page of resources.", + "type": "string", + "readOnly": true + } + } + }, + "ConfigurationResult": { + "description": "Configurations for source resource, include appSettings, connectionString and serviceBindings", + "type": "object", + "properties": { + "configurations": { + "description": "The configuration properties for source resource.", + "type": "array", + "items": { + "$ref": "#/definitions/SourceConfiguration" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidateOperationResult": { + "description": "The validation operation result for a Linker.", + "type": "object", + "properties": { + "properties": { + "x-nullable": true, + "description": "The validation result detail.", + "x-ms-client-flatten": true, + "$ref": "#/definitions/ValidateResult" + }, + "resourceId": { + "x-nullable": true, + "description": "Validated Linker id.", + "type": "string" + }, + "status": { + "x-nullable": true, + "description": "Validation operation status.", + "type": "string" + } + } + }, + "ValidateResult": { + "description": "The validation result for a Linker.", + "type": "object", + "properties": { + "linkerName": { + "x-nullable": true, + "description": "The linker name.", + "type": "string" + }, + "isConnectionAvailable": { + "x-nullable": true, + "description": "A boolean value indicating whether the connection is available or not", + "type": "boolean" + }, + "reportStartTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The start time of the validation report." + }, + "reportEndTimeUtc": { + "x-nullable": true, + "type": "string", + "format": "date-time", + "description": "The end time of the validation report." + }, + "sourceId": { + "x-nullable": true, + "description": "The resource id of the Linker source application.", + "type": "string" + }, + "targetId": { + "x-nullable": true, + "description": "The resource Id of target service.", + "type": "string" + }, + "authType": { + "x-nullable": true, + "description": "The authentication type.", + "$ref": "#/definitions/AuthType" + }, + "validationDetail": { + "description": "The detail of validation result", + "type": "array", + "items": { + "$ref": "#/definitions/ValidationResultItem" + }, + "x-ms-identifiers": [ + "name" + ] + } + } + }, + "ValidationResultItem": { + "description": "The validation item for a Linker.", + "type": "object", + "properties": { + "name": { + "description": "The validation item name.", + "type": "string" + }, + "description": { + "x-nullable": true, + "description": "The display name of validation item", + "type": "string" + }, + "result": { + "x-nullable": true, + "description": "The result of validation", + "type": "string", + "enum": [ + "success", + "failure", + "warning" + ], + "x-ms-enum": { + "name": "ValidationResultStatus", + "modelAsString": true + } + }, + "errorMessage": { + "x-nullable": true, + "description": "The error message of validation result", + "type": "string" + }, + "errorCode": { + "x-nullable": true, + "description": "The error code of validation result", + "type": "string" + } + } + }, + "VNetSolution": { + "type": "object", + "description": "The VNet solution for linker", + "properties": { + "type": { + "x-nullable": true, + "description": "Type of VNet solution.", + "type": "string", + "enum": [ + "serviceEndpoint", + "privateLink" + ], + "x-ms-enum": { + "name": "vNetSolutionType", + "modelAsString": true + } + }, + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + } + } + }, + "PublicNetworkSolution": { + "type": "object", + "description": "Indicates public network solution, include firewall rules", + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation(such as firewall rules) when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "action": { + "description": "Optional. Indicates public network solution. If enable, enable public network access of target service with best try. Default is enable. If optOut, opt out public network access configuration.", + "$ref": "#/definitions/ActionType" + }, + "firewallRules": { + "description": "Describe firewall rules of target service to make sure source application could connect to the target.", + "$ref": "#/definitions/FirewallRules" + } + } + }, + "FirewallRules": { + "type": "object", + "description": "Target service's firewall rules. to allow connections from source service.", + "properties": { + "ipRanges": { + "type": "array", + "items": { + "type": "string" + }, + "description": "This value specifies the set of IP addresses or IP address ranges in CIDR form to be included as the allowed list of client IPs for a given database account." + }, + "azureServices": { + "description": "Allow Azure services to access the target service if true.", + "$ref": "#/definitions/AllowType" + }, + "callerClientIP": { + "description": "Allow caller client IP to access the target service if true. the property is used when connecting local application to target service.", + "$ref": "#/definitions/AllowType" + } + } + }, + "ConfigurationInfo": { + "type": "object", + "description": "The configuration information, used to generate configurations or save to applications", + "properties": { + "deleteOrUpdateBehavior": { + "description": "Indicates whether to clean up previous operation when Linker is updating or deleting", + "$ref": "#/definitions/DeleteOrUpdateBehavior" + }, + "action": { + "description": "Optional, indicate whether to apply configurations on source application. If enable, generate configurations and applied to the source application. Default is enable. If optOut, no configuration change will be made on source.", + "$ref": "#/definitions/ActionType" + }, + "customizedKeys": { + "description": "Optional. A dictionary of default key name and customized key name mapping. If not specified, default key name will be used for generate configurations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "daprProperties": { + "description": "Indicates some additional properties for dapr client type", + "$ref": "#/definitions/DaprProperties" + }, + "additionalConfigurations": { + "description": "A dictionary of additional configurations to be added. Service will auto generate a set of basic configurations and this property is to full fill more customized configurations", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "additionalConnectionStringProperties": { + "description": "A dictionary of additional properties to be added in the end of connection string.", + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "configurationStore": { + "x-nullable": true, + "description": "An option to store configuration into different place", + "$ref": "#/definitions/ConfigurationStore" + } + } + }, + "ConfigurationStore": { + "type": "object", + "description": "An option to store configuration into different place", + "properties": { + "appConfigurationId": { + "x-nullable": true, + "type": "string", + "description": "The app configuration id to store configuration" + } + } + }, + "DaprProperties": { + "type": "object", + "description": "Indicates some additional properties for dapr client type", + "properties": { + "version": { + "x-nullable": true, + "type": "string", + "description": "The dapr component version" + }, + "componentType": { + "x-nullable": true, + "type": "string", + "description": "The dapr component type" + }, + "secretStoreComponent": { + "x-nullable": true, + "type": "string", + "description": "The name of a secret store dapr to retrieve secret" + }, + "metadata": { + "description": "Additional dapr metadata", + "type": "array", + "items": { + "$ref": "#/definitions/DaprMetadata" + }, + "x-ms-identifiers": [ + "name" + ] + }, + "scopes": { + "description": "The dapr component scopes", + "type": "array", + "items": { + "type": "string" + } + }, + "runtimeVersion": { + "x-nullable": true, + "type": "string", + "readOnly": true, + "description": "The runtime version supported by the properties" + }, + "bindingComponentDirection": { + "x-nullable": true, + "type": "string", + "enum": [ + "input", + "output" + ], + "x-ms-enum": { + "name": "DaprBindingComponentDirection", + "modelAsString": true + }, + "readOnly": true, + "description": "The direction supported by the dapr binding component" + } + } + }, + "DaprMetadata": { + "description": "The dapr component metadata.", + "type": "object", + "properties": { + "name": { + "description": "Metadata property name.", + "type": "string" + }, + "value": { + "description": "Metadata property value.", + "type": "string" + }, + "secretRef": { + "description": "The secret name where dapr could get value", + "type": "string" + }, + "description": { + "description": "The description of the metadata, returned from configuration api", + "type": "string" + }, + "required": { + "description": "The value indicating whether the metadata is required or not", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "DaprMetadataRequired", + "modelAsString": true + } + } + } + }, + "SecretStore": { + "type": "object", + "description": "An option to store secret value in secure place", + "properties": { + "keyVaultId": { + "x-nullable": true, + "type": "string", + "description": "The key vault id to store secret" + }, + "keyVaultSecretName": { + "x-nullable": true, + "type": "string", + "description": "The key vault secret name to store secret, only valid when storing one secret" + } + } + }, + "DryrunList": { + "description": "The list of dryrun.", + "type": "object", + "properties": { + "nextLink": { + "x-nullable": true, + "description": "The link used to get the next page of dryrun list.", + "type": "string" + }, + "value": { + "description": "The list of dryrun.", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunResource" + } + } + } + }, + "DryrunResource": { + "type": "object", + "description": "a dryrun job resource", + "allOf": [ + { + "$ref": "../../../../../common-types/resource-management/v3/types.json#/definitions/ProxyResource", + "description": "The resource model definition for an Azure Resource Manager proxy resource." + } + ], + "properties": { + "properties": { + "description": "The properties of the dryrun job.", + "$ref": "#/definitions/DryrunProperties", + "x-ms-client-flatten": true + } + } + }, + "DryrunPatch": { + "type": "object", + "description": "a dryrun job to be updated.", + "properties": { + "properties": { + "description": "The properties of the dryrun job.", + "$ref": "#/definitions/DryrunProperties", + "x-ms-client-flatten": true + } + } + }, + "DryrunProperties": { + "description": "The properties of the dryrun job", + "type": "object", + "properties": { + "parameters": { + "description": "The parameters of the dryrun", + "$ref": "#/definitions/DryrunParameters" + }, + "prerequisiteResults": { + "readOnly": true, + "description": "the result of the dryrun", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunPrerequisiteResult" + }, + "x-ms-identifiers": [] + }, + "operationPreviews": { + "readOnly": true, + "description": "the preview of the operations for creation", + "type": "array", + "items": { + "$ref": "#/definitions/DryrunOperationPreview" + }, + "x-ms-identifiers": [] + }, + "provisioningState": { + "readOnly": true, + "type": "string", + "description": "The provisioning state. " + } + } + }, + "DryrunActionName": { + "description": "The name of action for you dryrun job.", + "type": "string", + "enum": [ + "createOrUpdate" + ], + "x-ms-enum": { + "name": "DryrunActionName", + "modelAsString": true + } + }, + "DryrunParameters": { + "description": "The parameters of the dryrun", + "discriminator": "actionName", + "type": "object", + "properties": { + "actionName": { + "$ref": "#/definitions/DryrunActionName" + } + }, + "required": [ + "actionName" + ] + }, + "CreateOrUpdateDryrunParameters": { + "x-ms-discriminator-value": "createOrUpdate", + "type": "object", + "description": "The dryrun parameters for creation or update a linker", + "allOf": [ + { + "$ref": "#/definitions/DryrunParameters" + }, + { + "$ref": "#/definitions/LinkerProperties" + } + ] + }, + "DryrunPrerequisiteResultType": { + "description": "The type of dryrun result.", + "type": "string", + "enum": [ + "basicError", + "permissionsMissing" + ], + "x-ms-enum": { + "name": "DryrunPrerequisiteResultType", + "modelAsString": true + } + }, + "DryrunPrerequisiteResult": { + "description": "A result of dryrun", + "discriminator": "type", + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/DryrunPrerequisiteResultType" + } + }, + "required": [ + "type" + ] + }, + "BasicErrorDryrunPrerequisiteResult": { + "x-ms-discriminator-value": "basicError", + "description": "The represent of basic error", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/DryrunPrerequisiteResult" + } + ], + "properties": { + "code": { + "type": "string", + "description": "The error code." + }, + "message": { + "type": "string", + "description": "The error message." + } + } + }, + "PermissionsMissingDryrunPrerequisiteResult": { + "x-ms-discriminator-value": "permissionsMissing", + "description": "The represent of missing permissions", + "type": "object", + "allOf": [ + { + "$ref": "#/definitions/DryrunPrerequisiteResult" + } + ], + "properties": { + "scope": { + "description": "The permission scope", + "type": "string" + }, + "permissions": { + "description": "The permission list", + "type": "array", + "items": { + "type": "string" + } + }, + "recommendedRole": { + "description": "The recommended role to resolve permissions missing", + "type": "string" + } + } + }, + "DryrunOperationPreview": { + "description": "The preview of the operations for creation", + "type": "object", + "properties": { + "name": { + "description": "The operation name", + "type": "string" + }, + "operationType": { + "description": "The operation type", + "type": "string", + "enum": [ + "configConnection", + "configNetwork", + "configAuth" + ], + "x-ms-enum": { + "name": "DryrunPreviewOperationType", + "modelAsString": true + } + }, + "description": { + "description": "The description of the operation", + "type": "string" + }, + "action": { + "description": "The action defined by RBAC, refer https://docs.microsoft.com/azure/role-based-access-control/role-definitions#actions-format", + "type": "string" + }, + "scope": { + "description": "The scope of the operation, refer https://docs.microsoft.com/azure/role-based-access-control/scope-overview", + "type": "string" + } + } + }, + "ActionType": { + "description": "Indicates how to apply the connector operations, such as opt out network configuration, opt in configuration.", + "type": "string", + "enum": [ + "enable", + "optOut" + ], + "x-ms-enum": { + "name": "actionType", + "modelAsString": true + } + }, + "AuthMode": { + "description": "Indicates how to apply the authentication configuration operations.", + "type": "string", + "enum": [ + "optInAllAuth", + "optOutAllAuth" + ], + "x-ms-enum": { + "name": "authMode", + "modelAsString": true, + "values": [ + { + "value": "optInAllAuth", + "description": "Default authentication configuration according to the authentication type." + }, + { + "value": "optOutAllAuth", + "description": "Skip all authentication configuration such as enabling managed identity and granting RBAC roles" + } + ] + } + }, + "AllowType": { + "description": "Whether to allow firewall rules.", + "type": "string", + "enum": [ + "true", + "false" + ], + "x-ms-enum": { + "name": "allowType", + "modelAsString": true + } + }, + "DaprConfigurationList": { + "description": "Dapr configuration list supported by Service Connector", + "type": "object", + "properties": { + "value": { + "description": "The list of dapr configurations", + "type": "array", + "items": { + "$ref": "#/definitions/DaprConfigurationResource" + }, + "x-ms-identifiers": [] + }, + "nextLink": { + "description": "Link to next page of resources.", + "type": "string", + "readOnly": true + } + } + }, + "DaprConfigurationResource": { + "description": "Represent one resource of the dapr configuration list", + "type": "object", + "properties": { + "properties": { + "description": "The properties of the dapr configuration.", + "$ref": "#/definitions/DaprConfigurationProperties", + "x-ms-client-flatten": true + } + } + }, + "DaprConfigurationProperties": { + "type": "object", + "properties": { + "targetType": { + "type": "string", + "description": "Supported target resource type, extract from resource id, uppercase" + }, + "authType": { + "$ref": "#/definitions/AuthType" + }, + "daprProperties": { + "$ref": "#/definitions/DaprProperties" + } + } + } + }, + "parameters": { + "LinkerNameParameter": { + "name": "linkerName", + "in": "path", + "required": true, + "type": "string", + "description": "The name Linker resource.", + "x-ms-parameter-location": "method" + }, + "ConnectorNameParameter": { + "name": "connectorName", + "in": "path", + "required": true, + "type": "string", + "description": "The name of resource.", + "x-ms-parameter-location": "method" + }, + "ResourceUriParameter": { + "name": "resourceUri", + "in": "path", + "required": true, + "type": "string", + "description": "The fully qualified Azure Resource manager identifier of the resource to be connected.", + "x-ms-skip-url-encoding": true, + "x-ms-parameter-location": "method" + }, + "SubscriptionIdParameter": { + "name": "subscriptionId", + "in": "path", + "required": true, + "type": "string", + "description": "The ID of the target subscription.", + "minLength": 1, + "x-ms-parameter-location": "method" + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/test.json b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/test.json new file mode 100644 index 000000000000..40bbf5b4ad97 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/test.json @@ -0,0 +1,145 @@ +{ + "swagger": "2.0", + "info": { + "title": "Microsoft.ServiceLinker", + "description": "Microsoft.ServiceLinker provider", + "version": "2024-04-01" + }, + "host": "management.azure.com", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "security": [ + { + "azure_auth": [ + "user_impersonation" + ] + } + ], + "securityDefinitions": { + "azure_auth": { + "type": "oauth2", + "authorizationUrl": "https://login.microsoftonline.com/common/oauth2/authorize", + "flow": "implicit", + "description": "Azure Active Directory OAuth2 Flow.", + "scopes": { + "user_impersonation": "impersonate your user account" + } + } + }, + "paths": { + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns": { + "parameters": [], + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_ListDryrun", + "description": "list dryrun jobs", + "x-ms-examples": { + "ConnectorDryrunList": { + "$ref": "./examples/ConnectorDryrunList.json" + } + }, + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunList" + } + } + }, + "x-ms-pageable": { + "nextLinkName": "nextLink" + } + } + } + }, + "x-ms-paths": { + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns/{dryrunName}": { + "get": { + "tags": [ + "Connector" + ], + "operationId": "Connector_GetDryrun", + "description": "get a dryrun job", + "x-ms-examples": { + "ConnectorDryrunGet": { + "$ref": "./examples/ConnectorDryrunGet.json" + } + }, + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + } + }, + "put": { + "tags": [ + "Connector" + ], + "operationId": "Connector_CreateDryrun", + "description": "create a dryrun job to do necessary check before actual creation", + "x-ms-long-running-operation": true, + "x-ms-long-running-operation-options": { + "final-state-via": "azure-async-operation" + }, + "x-ms-examples": { + "ConnectorDryrunCreate": { + "$ref": "./examples/ConnectorDryrunCreate.json" + } + }, + "responses": { + "200": { + "description": "OK. The request has succeeded.", + "schema": { + "$ref": "#/definitions/DryrunResource" + } + } + } + } + } + }, + "definitions": { + "DryrunList": { + "type": "object", + "properties": { + "value": { + "type": "array", + "items": { + "$ref": "#/definitions/DryrunResource" + } + }, + "nextLink": { + "type": "string" + } + } + }, + "DryrunResource": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "type": { + "type": "string" + }, + "location": { + "type": "string" + } + } + } + } +} diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.csharp.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.csharp.md new file mode 100644 index 000000000000..cec7ea43ab74 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.csharp.md @@ -0,0 +1,15 @@ +## C + +These settings apply only when `--csharp` is specified on the command line. +Please also specify `--csharp-sdks-folder=`. + +```yaml $(csharp) +csharp: + azure-arm: true + license-header: MICROSOFT_MIT_NO_VERSION + payload-flattening-threshold: 1 + clear-output-folder: true + client-side-validation: false + namespace: Microsoft.ServiceLinker + output-folder: $(csharp-sdks-folder)/servicelinker/management/Microsoft.ServiceLinker/GeneratedProtocol +``` diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.go.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.go.md new file mode 100644 index 000000000000..5a6d630e721c --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.go.md @@ -0,0 +1,11 @@ +## Go + +These settings apply only when `--go` is specified on the command line. + +``` yaml $(go) && $(track2) +license-header: MICROSOFT_MIT_NO_VERSION +module-name: sdk/resourcemanager/servicelinker/armservicelinker +module: github.com/Azure/azure-sdk-for-go/$(module-name) +output-folder: $(go-sdk-folder)/$(module-name) +azure-arm: true +``` diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.java.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.java.md new file mode 100644 index 000000000000..d548eb7e399c --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.java.md @@ -0,0 +1,9 @@ +## Java + +These settings apply only when `--java` is specified on the command line. + +```yaml $(java) +resource-collection-associations: +- resource: LinkerResource + collection: Linkers +``` diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.md new file mode 100644 index 000000000000..6079f7701073 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.md @@ -0,0 +1,121 @@ +# ServiceLinker + +> see https://aka.ms/autorest + +This is the AutoRest configuration file for ServiceLinker. + +## Getting Started + +To build the SDKs for My API, simply install AutoRest via `npm` (`npm install -g autorest`) and then run: + +> `autorest readme.md` + +To see additional help and options, run: + +> `autorest --help` + +For other options on installation see [Installing AutoRest](https://aka.ms/autorest/install) on the AutoRest github page. + +--- + +## Configuration + +### Basic Information + +These are the global settings for the ServiceLinker. + +```yaml +title: ServiceLinkerManagementClient +openapi-type: arm +openapi-subtype : rpaas +tag: package-2024-07-01-preview +``` + +### Tag: package-2022-05-01 + +These settings apply only when `--tag=package-2022-05-01` is specified on the command line. + +```yaml $(tag) == 'package-2022-05-01' +input-file: + - Microsoft.ServiceLinker/stable/2022-05-01/servicelinker.json +``` + +### Tag: package-2023-04-01-preview + +These settings apply only when `--tag=package-2023-04-01-preview` is specified on the command line. + +```yaml $(tag) == 'package-2023-04-01-preview' +input-file: + - Microsoft.ServiceLinker/preview/2023-04-01-preview/servicelinker.json +``` + +### Tag: package-2024-04-01 + +These settings apply only when `--tag=package-2024-04-01` is specified on the command line. + +```yaml $(tag) == 'package-2024-04-01' +input-file: + - Microsoft.ServiceLinker/stable/2024-04-01/servicelinker.json + - Microsoft.ServiceLinker/stable/2024-04-01/test.json +``` + +### Tag: package-2024-07-01-preview + +These settings apply only when `--tag=package-2024-07-01-preview` is specified on the command line. + +```yaml $(tag) == 'package-2024-07-01-preview' +input-file: + - Microsoft.ServiceLinker/preview/2024-07-01-preview/servicelinker.json +``` + +## Suppression + +``` yaml +directive: + - suppress: TopLevelResourcesListBySubscription + from: servicelinker.json + where: $.definitions.LinkerResource + reason: This is an extension resource +``` + +--- + +# Code Generation + +## Swagger to SDK + +This section describes what SDK should be generated by the automatic system. +This is not used by Autorest itself. + +```yaml $(swagger-to-sdk) +swagger-to-sdk: + - repo: azure-sdk-for-python + - repo: azure-sdk-for-java + - repo: azure-sdk-for-go-track2 + - repo: azure-sdk-for-js + - repo: azure-sdk-for-ruby + after_scripts: + - bundle install && rake arm:regen_all_profiles['azure_mgmt_servicelinker'] + - repo: azure-resource-manager-schemas + - repo: azure-powershell +``` + +## Go + +See configuration in [readme.go.md](./readme.go.md) + +## Python + +See configuration in [readme.python.md](./readme.python.md) + +## Ruby + +See configuration in [readme.ruby.md](./readme.ruby.md) + +## TypeScript + +See configuration in [readme.typescript.md](./readme.typescript.md) + +## CSharp + +See configuration in [readme.csharp.md](./readme.csharp.md) diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.python.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.python.md new file mode 100644 index 000000000000..07d5dae67222 --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.python.md @@ -0,0 +1,18 @@ +## Python + +These settings apply only when `--python` is specified on the command line. +Please also specify `--python-sdks-folder=`. + +``` yaml $(python) +azure-arm: true +license-header: MICROSOFT_MIT_NO_VERSION +package-name: azure-mgmt-servicelinker +namespace: azure.mgmt.servicelinker +package-version: 1.0.0b1 +clear-output-folder: true +``` + +``` yaml $(python) +no-namespace-folders: true +output-folder: $(python-sdks-folder)/servicelinker/azure-mgmt-servicelinker/azure/mgmt/servicelinker +``` \ No newline at end of file diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.ruby.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.ruby.md new file mode 100644 index 000000000000..cae33db1eebf --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.ruby.md @@ -0,0 +1,9 @@ +## Ruby + +These settings apply only when `--ruby` is specified on the command line. + +``` yaml $(ruby) +azure-arm: true +namespace: Azure::ServiceLinker +package-name: azure_mgmt_servicelinker +``` \ No newline at end of file diff --git a/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.typescript.md b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.typescript.md new file mode 100644 index 000000000000..f10dd7331a2e --- /dev/null +++ b/.github/shared/test/fixtures/swagger/specification/servicelinker/resource-manager/readme.typescript.md @@ -0,0 +1,13 @@ +## TypeScript + +These settings apply only when `--typescript` is specified on the command line. +Please also specify `--typescript-sdks-folder=`. + +```yaml $(typescript) +typescript: + azure-arm: true + package-name: "@azure/arm-servicelinker" + output-folder: "$(typescript-sdks-folder)/sdk/servicelinker/arm-servicelinker" + payload-flattening-threshold: 1 + generate-metadata: true +``` diff --git a/.github/shared/test/git.test.js b/.github/shared/test/git.test.js new file mode 100644 index 000000000000..1e7e635d8ef5 --- /dev/null +++ b/.github/shared/test/git.test.js @@ -0,0 +1,23 @@ +import { describe, expect, it } from "vitest"; +import { isFullGitSha } from "../src/git.js"; +import { fullGitSha } from "./examples.js"; + +describe("git", () => { + it.each([ + [undefined, false], + [null, false], + ["", false], + // Short SHAs of 7 chars are not valid + ["abc1234", false], + // Invalid hex chars + ["aBcDeG0189".repeat(4), false], + ["aBcDe 0189".repeat(4), false], + ["aBcDe_0189".repeat(4), false], + // Valid + ["aBcDeF0189".repeat(4), true], + [fullGitSha, true], + ])("isFullGitSha(%o) => %o", (string, result) => { + // @ts-expect-error Testing invalid input types + expect(isFullGitSha(string)).toBe(result); + }); +}); diff --git a/.github/shared/test/logger.test.js b/.github/shared/test/logger.test.js new file mode 100644 index 000000000000..d855eb0b6d39 --- /dev/null +++ b/.github/shared/test/logger.test.js @@ -0,0 +1,48 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { ConsoleLogger, debugLogger, defaultLogger } from "../src/logger.js"; + +describe("logger", () => { + /** @type {import("vitest").MockInstance} */ let debugSpy; + /** @type {import("vitest").MockInstance} */ let errorSpy; + /** @type {import("vitest").MockInstance} */ let logSpy; + /** @type {import("vitest").MockInstance} */ let warnSpy; + + beforeEach(() => { + debugSpy = vi.spyOn(console, "debug"); + errorSpy = vi.spyOn(console, "error"); + logSpy = vi.spyOn(console, "log"); + warnSpy = vi.spyOn(console, "warn"); + }); + + afterEach(() => { + debugSpy.mockRestore(); + errorSpy.mockRestore(); + logSpy.mockRestore(); + warnSpy.mockRestore(); + }); + + it.each([ + ["defaultLogger", defaultLogger, false], + ["debugLogger", debugLogger, true], + ["new ConsoleLogger(isDebug: false)", new ConsoleLogger(false), false], + ["new ConsoleLogger(isDebug: true)", new ConsoleLogger(true), true], + ])("%s", (_name, logger, isDebug) => { + expect(logger.isDebug()).toBe(isDebug); + + logger.info("test info"); + expect(logSpy).toBeCalledWith("test info"); + + logger.warning("test warning"); + expect(warnSpy).toBeCalledWith("test warning"); + + logger.error("test error"); + expect(errorSpy).toBeCalledWith("test error"); + + logger.debug("test debug"); + if (isDebug) { + expect(debugSpy).toBeCalledWith("test debug"); + } else { + expect(debugSpy).toBeCalledTimes(0); + } + }); +}); diff --git a/.github/shared/test/math.test.js b/.github/shared/test/math.test.js new file mode 100644 index 000000000000..3583699936e0 --- /dev/null +++ b/.github/shared/test/math.test.js @@ -0,0 +1,27 @@ +import { describe, expect, it } from "vitest"; +import { toPercent } from "../src/math.js"; + +describe("math", () => { + it.each([ + [0, "0%"], + [0, "0.0%", 1], + [0, "0.00%", 2], + [0.0001, "0%"], + [0.0001, "0.0%", 1], + [0.0001, "0.01%", 2], + [0.001, "0%"], + [0.001, "0.1%", 1], + [0.01, "1%"], + [0.25, "25%"], + [1.0 / 3, "33%"], + [1.0 / 3, "33.3%", 1], + [1.0 / 3, "33.33%", 2], + [1.0 / 3, "33.333%", 3], + [0.5, "50%"], + [0.99, "99%"], + [0.999, "100%"], + [1, "100%"], + ])("toPercent(%f)=%s", (value, expected, decimals = 0) => { + expect(toPercent(value, decimals)).toEqual(expected); + }); +}); diff --git a/.github/shared/test/path.test.js b/.github/shared/test/path.test.js new file mode 100644 index 000000000000..1e5088cd147e --- /dev/null +++ b/.github/shared/test/path.test.js @@ -0,0 +1,73 @@ +import { basename, resolve, sep } from "path"; +import { describe, expect, it } from "vitest"; +import { includesSegment, untilLastSegment, untilLastSegmentWithParent } from "../src/path.js"; + +describe("path", () => { + it.each([ + ["/a/b/c/d.txt", "d.txt", true], + ["/a/b/c/d.txt", "c", true], + ["/a/b/c/d.txt", "b", true], + ["/a/b/c/d.txt", "a", true], + ["/a/b/c/d.txt", "", true], + ["/a/b/c/d.txt", "z", false], + ["/a/b/c/d.txt", sep, false], + // Ensure path is resolved (against cwd) before searching + ["a/b/c/d.txt", "d.txt", true], + ["a/b/c/d.txt", "c", true], + ["a/b/c/d.txt", "b", true], + ["a/b/c/d.txt", "a", true], + ["a/b/c/d.txt", basename(process.cwd()), true], + ["a/b/c/d.txt", "", true], + ["a/b/c/d.txt", sep, false], + // Multiple occurrences of segment + ["/a/b/a/c/a/d.txt", "a", true], + ])("includesSegment(%o, %o) => %o", (path, segment, expected) => { + expect(includesSegment(path, segment)).toEqual(expected); + }); + + it.each([ + ["/a/b/c/d.txt", "d.txt", "/a/b/c/d.txt"], + ["/a/b/c/d.txt", "c", "/a/b/c"], + ["/a/b/c/d.txt", "b", "/a/b"], + ["/a/b/c/d.txt", "a", "/a"], + ["/a/b/c/d.txt", "", "/"], + ["/a/b/c/d.txt", "z", ""], + ["/a/b/c/d.txt", sep, ""], + // Ensure path is resolved (against cwd) before searching + ["a/b/c/d.txt", "d.txt", "a/b/c/d.txt"], + ["a/b/c/d.txt", "c", "a/b/c"], + ["a/b/c/d.txt", "b", "a/b"], + ["a/b/c/d.txt", "a", "a"], + // Cannot easily test segment "" with relative path, since result is subset of cwd. Covered in absolute path test. + // ["a/b/c/d.txt", "", "/"], + ["a/b/c/d.txt", sep, ""], + // Ensure last occurrence of segment is used + ["/a/b/a/c/a/d.txt", "a", "/a/b/a/c/a"], + ])("untilLastSegment(%o, %o) => %o", (path, segment, expected) => { + const resolvedExpected = expected === "" ? "" : resolve(expected); + expect(untilLastSegment(path, segment)).toEqual(resolvedExpected); + }); + + it.each([ + ["/a/b/c/d.txt", "d.txt", ""], + ["/a/b/c/d.txt", "c", "/a/b/c/d.txt"], + ["/a/b/c/d.txt", "b", "/a/b/c"], + ["/a/b/c/d.txt", "a", "/a/b"], + ["/a/b/c/d.txt", "", "/a"], + ["/a/b/c/d.txt", "z", ""], + ["/a/b/c/d.txt", sep, ""], + // Ensure path is resolved (against cwd) before searching + ["a/b/c/d.txt", "d.txt", ""], + ["a/b/c/d.txt", "c", "a/b/c/d.txt"], + ["a/b/c/d.txt", "b", "a/b/c"], + ["a/b/c/d.txt", "a", "a/b"], + // Cannot easily test segment "" with relative path, since result is subset of cwd. Covered in absolute path test. + // ["a/b/c/d.txt", "", "/home"], + ["a/b/c/d.txt", sep, ""], + // Ensure last occurrence of segment is used + ["/a/b/a/c/a/d.txt", "a", "/a/b/a/c/a/d.txt"], + ])("untilLastSegmentWithParent(%o, %o) => %o", (path, segment, expected) => { + const resolvedExpected = expected === "" ? "" : resolve(expected); + expect(untilLastSegmentWithParent(path, segment)).toEqual(resolvedExpected); + }); +}); diff --git a/.github/shared/test/readme.test.js b/.github/shared/test/readme.test.js new file mode 100644 index 000000000000..30820a5fea5e --- /dev/null +++ b/.github/shared/test/readme.test.js @@ -0,0 +1,181 @@ +import { resolve } from "path"; +import { describe, expect, it } from "vitest"; +import { ConsoleLogger } from "../src/logger.js"; +import { Readme, TagMatchRegex } from "../src/readme.js"; +import { SpecModel } from "../src/spec-model.js"; +import { contosoReadme } from "./examples.js"; + +const options = { logger: new ConsoleLogger(/*debug*/ true) }; + +describe("readme", () => { + it("can be created with mock path", async () => { + const readme = new Readme("bar"); + expect(readme.path).toBe(resolve("bar")); + + await expect(readme.getTags()).rejects.toThrowError(/no such file or directory/i); + + expect(readme.specModel).toBeUndefined(); + }); + + it("resolves path against SpecModel", () => { + const readme = new Readme("readme.md", { + specModel: new SpecModel("/specs/foo"), + }); + expect(readme.path).toBe(resolve("/specs/foo/readme.md")); + }); + + it("can be created with string content", async () => { + const folder = "/fake"; + const readme = new Readme(resolve(folder, "readme.md"), { + ...options, + content: contosoReadme, + }); + + const tags = await readme.getTags(); + const tagNames = [...tags.keys()]; + const expectedTagNames = ["package-2021-11-01", "package-2021-10-01-preview"]; + + expect(tagNames.sort()).toEqual(expectedTagNames.sort()); + + const swaggerPaths = [...tags.values()].flatMap((t) => [...t.inputFiles.keys()]); + + const expectedPaths = [ + resolve(folder, "Microsoft.Contoso/stable/2021-11-01/contoso.json"), + resolve(folder, "Microsoft.Contoso/preview/2021-10-01-preview/contoso.json"), + ]; + + expect(swaggerPaths.sort()).toEqual(expectedPaths.sort()); + }); + + // If tag names are duplicated (with no disambiguating conditionals), it's almost certainly a bug + // in the readme that should be fixed. + it("throws if duplicate tags", async () => { + let content = ` +\`\`\`yaml $(tag) == 'package-2025-01-01' +input-file: + - foo.json +\`\`\` +\`\`\`yaml $(tag) == 'package-2025-01-01' +input-file: + - bar.json +\`\`\` +`; + + let readme = new Readme("foo", { ...options, content }); + + await expect(readme.getTags()).rejects.toThrowError( + "Multiple input-file definitions for tag package-2025-01-01", + ); + }); + + // A few existing specs use duplicate tags, but with conditionals to disambiguate at runtime. + // + // While this may work for generating the SDK itself (where you can specify the additional values), + // it doesn't work for static analysis tools like LintDiff, since LintDiff wouldn't know what + // additional values to pass to autorest. + // + // It may be possible to support this in spec-model, by allowing duplicate tags with different conditionals. + // However, downstream users of the tags for static analysis would still need to throw. Also, we only + // found two specs using this pattern (and only in the private repo). So I think it's better to continue + // disallowing this, and instead rename the conflicting tags in the readme. Rather than adding + // complexity to spec-model for an edge case (with workarounds). + // + // More details: https://github.com/Azure/azure-rest-api-specs/issues/37003 + it("throws if duplicate tags with different conditionals", async () => { + let content = ` +\`\`\`yaml $(tag) == 'package-2025-01-01' +input-file: + - foo.json +\`\`\` +\`\`\`yaml $(tag) == 'package-2025-01-01' && $(test-condition) +input-file: + - bar.json +\`\`\` +`; + + let readme = new Readme("foo", { ...options, content }); + + await expect(readme.getTags()).rejects.toThrowError( + "Multiple input-file definitions for tag package-2025-01-01", + ); + }); + + it("throws if input-file is not string", async () => { + let content = ` +\`\`\`yaml $(tag) == 'package-2025-01-01' +input-file: + - foo.json + - invalid-object: + - bar.json +\`\`\` +`; + + let readme = new Readme("readme.md", { ...options, content }); + + await expect(readme.getTags()).rejects.toThrowErrorMatchingInlineSnapshot(` + [SpecModelError: Unable to parse input-file YAML for tag package-2025-01-01 in ${readme.path} + Problem File: ${readme.path} + Readme: ${readme.path} + Tag: package-2025-01-01 + Cause: [ + { + "code": "invalid_union", + "errors": [ + [ + { + "expected": "string", + "code": "invalid_type", + "path": [], + "message": "Invalid input: expected string, received array" + } + ], + [ + { + "expected": "string", + "code": "invalid_type", + "path": [ + 1 + ], + "message": "Invalid input: expected string, received object" + } + ] + ], + "path": [ + "input-file" + ], + "message": "Invalid input" + } + ]] + `); + }); + + it("can be created with empty content", async () => { + const folder = "/fake"; + const readme = new Readme(resolve(folder, "readme.md"), { + ...options, + // Simulate empty file + content: "", + }); + + const tags = await readme.getTags(); + + // Ensures code doesn't try to read file `/fake/readme.md` which would throw + expect(tags.size).toBe(0); + }); +}); + +describe("TagMatchRegex", () => { + it.each([ + ["```yaml $(package-A-tag) == 'package-A-[[Version]]'", false, undefined], + ["``` yaml $(tag)=='package-2017-03' && $(go)", true, "package-2017-03"], + ["``` yaml $(csharp) && $(tag) == 'release_4_0'", true, "release_4_0"], + ["``` yaml $(tag) == 'package-2021-12-01-preview'", true, "package-2021-12-01-preview"], + ['``` yaml $(tag) == "package-2025-06-05"', true, "package-2025-06-05"], + ["``` yaml $(tag) == 'package-2025-06-05\"", false, undefined], + ["``` yaml $(tag) == \"package-2025-06-05'", false, undefined], + ])("matches tags and extracts tag names properly: %s", (example, expectedMatch, expectedTag) => { + const match = example.match(TagMatchRegex); + expect(TagMatchRegex.test(example)).toEqual(expectedMatch); + expect(match?.[2]).toEqual(expectedTag); + }); +}); diff --git a/.github/shared/test/repo.js b/.github/shared/test/repo.js new file mode 100644 index 000000000000..5c65b1383ab7 --- /dev/null +++ b/.github/shared/test/repo.js @@ -0,0 +1,6 @@ +import { dirname, join } from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +export const repoRoot = join(__dirname, "..", "..", ".."); diff --git a/.github/shared/test/sdk-types.js b/.github/shared/test/sdk-types.js new file mode 100644 index 000000000000..6027697d48a7 --- /dev/null +++ b/.github/shared/test/sdk-types.js @@ -0,0 +1,24 @@ +import { SdkName } from "../src/sdk-types.js"; + +/** + * @typedef {import("../src/sdk-types.js").SpecGenSdkArtifactInfo} SpecGenSdkArtifactInfo + */ + +/** + * Create a mock SpecGenSdkArtifactInfo, filling unspecified properties with defaults. + * + * @param {Partial} [overrides] + * @returns {SpecGenSdkArtifactInfo} + */ +export function createMockSpecGenSdkArtifactInfo(overrides = {}) { + /** @type {SpecGenSdkArtifactInfo} */ + const defaults = { + apiViewRequestData: [], + headSha: "abc123", + isSpecGenSdkCheckRequired: true, + language: SdkName.Go, + result: "test result", + }; + + return { ...defaults, ...overrides }; +} diff --git a/.github/shared/test/sdk-types.test.js b/.github/shared/test/sdk-types.test.js new file mode 100644 index 000000000000..07cf14fea3ab --- /dev/null +++ b/.github/shared/test/sdk-types.test.js @@ -0,0 +1,22 @@ +import { describe, expect, it } from "vitest"; +import { sdkLabels, SpecGenSdkArtifactInfoSchema } from "../src/sdk-types.js"; +import { createMockSpecGenSdkArtifactInfo } from "./sdk-types.js"; + +describe("sdk-types", () => { + it("defines sdkLabels", () => { + // Ensures constant "sdkLabels" is considered "covered" by codecov + expect(sdkLabels).toBeDefined(); + }); + + it("parses SpecGetSdkArtifactInfo", () => { + const artifactInfo = createMockSpecGenSdkArtifactInfo(); + + const json = JSON.stringify(artifactInfo); + expect(json).toMatchInlineSnapshot( + `"{"apiViewRequestData":[],"headSha":"abc123","isSpecGenSdkCheckRequired":true,"language":"azure-sdk-for-go","result":"test result"}"`, + ); + + const parsed = SpecGenSdkArtifactInfoSchema.parse(JSON.parse(json)); + expect(parsed).toEqual(artifactInfo); + }); +}); diff --git a/.github/shared/test/set.test.js b/.github/shared/test/set.test.js new file mode 100644 index 000000000000..bc909b5c58d2 --- /dev/null +++ b/.github/shared/test/set.test.js @@ -0,0 +1,73 @@ +import { describe, expect, it } from "vitest"; +import { equals, intersect } from "../src/set.js"; + +describe("set", () => { + it.each([ + // not instanceof Set: null, undefined + [null, null, false], + [undefined, undefined, false], + [null, undefined, false], + [null, [], false], + [undefined, [], false], + // not instanceof Set: number, string, object, array + [1, 1, false], + ["a", "a", false], + [{}, {}, false], + [[], [], false], + // different lengths + [new Set(), new Set([1]), false], + [new Set([1]), new Set([1, 2]), false], + [new Set([1, 2]), new Set([1, 2, 3]), false], + // different elements + [new Set([1]), new Set([2]), false], + [new Set([1, 2]), new Set([1, 3]), false], + [new Set([1, 2]), new Set([2, 3]), false], + [new Set([1, 2, 3]), new Set([2, 3, 4]), false], + // sets with same elements, size >= 0 + [new Set(), new Set(), true], + [new Set([1]), new Set([1]), true], + [new Set([1, 2]), new Set([1, 2]), true], + [new Set([1, 2, 3]), new Set([1, 2, 3]), true], + ])("equals(%o, %o) = %o", (set1, set2, expected) => { + // @ts-expect-error testing runtime behavior of invalid types + expect(equals(set1, set2)).toBe(expected); + // @ts-expect-error testing runtime behavior of invalid types + expect(equals(set2, set1)).toBe(expected); + }); + + it.each([ + [[], [], []], + [[1, 2, 3], [], []], + [ + [1, 2, 3], + [2, 3, 4], + [2, 3], + ], + [[1, 2, 3], [4, 5, 6], []], + [ + [1, 2, 3], + [1, 2, 3], + [1, 2, 3], + ], + [ + ["a", "b", "c"], + ["b", "c", "d"], + ["b", "c"], + ], + ])( + "intersect(%o, %o) = %o", + ( + /** @type {(string|number)[]} */ a, + /** @type {(string|number)[]} */ b, + /** @type {(string|number)[]} */ result, + ) => { + const setA = new Set(a); + const setB = new Set(b); + const setResult = new Set(result); + + // Check both orders, result should be same + expect(intersect(setA, setB)).toEqual(setResult); + expect(intersect(setB, setA)).toEqual(setResult); + }, + ); +}); diff --git a/.github/shared/test/simple-git.test.js b/.github/shared/test/simple-git.test.js new file mode 100644 index 000000000000..706ab6407ce8 --- /dev/null +++ b/.github/shared/test/simple-git.test.js @@ -0,0 +1,20 @@ +import { mkdtemp, rm } from "fs/promises"; +import os from "os"; +import path from "path"; +import { describe, expect, it } from "vitest"; +import { getRootFolder } from "../src/simple-git.js"; + +describe("getRootFolder", () => { + it("resolves to repo root from a nested folder", async () => { + const testDir = __dirname; + const calculatedRoot = await getRootFolder(testDir); + const expectedRoot = path.resolve(path.join(__dirname, "..", "..", "..")); + expect(calculatedRoot).toBe(expectedRoot); + }); + + it("throws when directory is not a git repository", async () => { + const tempDir = await mkdtemp(path.join(os.tmpdir(), "non-git-")); + await expect(getRootFolder(tempDir)).rejects.toThrow(); + await rm(tempDir, { recursive: true, force: true }); + }); +}); diff --git a/.github/shared/test/sleep.test.js b/.github/shared/test/sleep.test.js new file mode 100644 index 000000000000..d3419c33df6c --- /dev/null +++ b/.github/shared/test/sleep.test.js @@ -0,0 +1,8 @@ +import { describe, expect, it } from "vitest"; +import { sleep } from "../src/sleep.js"; + +describe("sleep", () => { + it.each([-1, 0, 1, 2])("sleep(%s)", async (ms) => { + await expect(sleep(ms)).resolves.toBeUndefined(); + }); +}); diff --git a/.github/shared/test/sort.test.js b/.github/shared/test/sort.test.js new file mode 100644 index 000000000000..8d424950068e --- /dev/null +++ b/.github/shared/test/sort.test.js @@ -0,0 +1,32 @@ +import { describe, expect, it } from "vitest"; +import { byDate, invert } from "../src/sort.js"; + +describe("byDate", () => { + const input = [{ foo: "2025-01-01" }, { foo: "2023-01-01" }, { foo: "2024-01-01" }]; + + it("ascending by default", () => { + input.sort(byDate((s) => s.foo)); + + // Value `undefined` always sorts to the end + expect(input).toEqual([{ foo: "2023-01-01" }, { foo: "2024-01-01" }, { foo: "2025-01-01" }]); + }); + + it("descending with invert()", () => { + input.sort(invert(byDate((s) => s.foo))); + + // Value `undefined` always sorts to the end + expect(input).toEqual([{ foo: "2025-01-01" }, { foo: "2024-01-01" }, { foo: "2023-01-01" }]); + }); + + it.each([null, undefined, "invalid"])("invalid input: %s", (i) => { + const input = [{ foo: "2025-01-01" }, { foo: "2024-01-01" }]; + const comparator = byDate((/** @type {{foo: string}} */ i) => i.foo); + + // Ensure base case doesn't throw + input.sort(comparator); + expect(input).toEqual([{ foo: "2024-01-01" }, { foo: "2025-01-01" }]); + + input[0].foo = /** @type {string} */ (i); + expect(() => input.sort(comparator)).toThrowError(`Unable to parse '${i}' to a valid date`); + }); +}); diff --git a/.github/shared/test/spec-model-error.test.js b/.github/shared/test/spec-model-error.test.js new file mode 100644 index 000000000000..f7c9f6df978f --- /dev/null +++ b/.github/shared/test/spec-model-error.test.js @@ -0,0 +1,51 @@ +import { describe, expect, it } from "vitest"; +import { SpecModelError } from "../src/spec-model-error.js"; + +describe("SpecModelError", () => { + it("builds full message from message and options", () => { + let message = "test message"; + let options = {}; + + let error = new SpecModelError(message, options); + expect(error).toMatchInlineSnapshot(`[SpecModelError: test message]`); + expect(error.message).toEqual(message); + + options.source = "/test/source.json"; + error = new SpecModelError(message, options); + expect(error).toMatchInlineSnapshot(` + [SpecModelError: test message + Problem File: /test/source.json] + `); + expect(error.source).toEqual("/test/source.json"); + + options.readme = "/test/readme.md"; + error = new SpecModelError(message, options); + expect(error).toMatchInlineSnapshot(` + [SpecModelError: test message + Problem File: /test/source.json + Readme: /test/readme.md] + `); + expect(error.readme).toEqual("/test/readme.md"); + + options.tag = "2025-01-01"; + error = new SpecModelError(message, options); + expect(error).toMatchInlineSnapshot(` + [SpecModelError: test message + Problem File: /test/source.json + Readme: /test/readme.md + Tag: 2025-01-01] + `); + expect(error.tag).toEqual("2025-01-01"); + + options.cause = new TypeError("inner error"); + error = new SpecModelError(message, options); + expect(error).toMatchInlineSnapshot(` + [SpecModelError: test message + Problem File: /test/source.json + Readme: /test/readme.md + Tag: 2025-01-01 + Cause: TypeError: inner error] + `); + expect(error.cause).toEqual(options.cause); + }); +}); diff --git a/.github/shared/test/spec-model.test.js b/.github/shared/test/spec-model.test.js new file mode 100644 index 000000000000..1c5f31afa9c4 --- /dev/null +++ b/.github/shared/test/spec-model.test.js @@ -0,0 +1,532 @@ +import { randomUUID } from "crypto"; +import { readdir } from "fs/promises"; +import { dirname, isAbsolute, join, resolve } from "path"; +import { describe, expect, it } from "vitest"; +import { mapAsync } from "../src/array.js"; +import { ConsoleLogger } from "../src/logger.js"; +import { SpecModel } from "../src/spec-model.js"; +import { Duration } from "../src/time.js"; +import { repoRoot } from "./repo.js"; + +/** + * @typedef {import('../src/readme.js').ReadmeJSON} ReadmeJSON + * @typedef {import('../src/spec-model.js').SpecModelJSON} SpecModelJSON + * @typedef {import('../src/swagger.js').SwaggerJSON} SwaggerJSON + * @typedef {import('../src/tag.js').TagJSON} TagJSON + */ + +const options = { logger: new ConsoleLogger(/*debug*/ true) }; + +describe("SpecModel", () => { + it("can be created with mock folder", async () => { + const specModel = new SpecModel("foo"); + expect(specModel.folder).toBe(resolve("foo")); + + await expect(specModel.getReadmes()).rejects.toThrowError(/no such file or directory/i); + }); + + it("returns cached spec model", () => { + const path = randomUUID(); + + const specModel1 = new SpecModel(path); + const specModel2 = new SpecModel(path); + + expect(specModel1).toBe(specModel2); + }); + + it("returns spec model", async () => { + const folder = resolve( + __dirname, + "fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager", + ); + + const specModel = new SpecModel(folder, options); + + expect(specModel.toString()).toContain("SpecModel"); + expect(specModel.folder).toBe(folder); + + const readmes = [...(await specModel.getReadmes()).values()]; + expect(readmes.length).toBe(1); + + const readme = readmes[0]; + expect(readme.toString()).toContain("Readme"); + expect(readme.path).toBe(resolve(folder, "readme.md")); + expect(readme.specModel).toBe(specModel); + + await expect(readme.getGlobalConfig()).resolves.toEqual({ + "openapi-type": "arm", + "openapi-subtype": "rpaas", + tag: "package-2021-11-01", + }); + + const tags = [...(await readme.getTags()).values()].sort((a, b) => + a.name.localeCompare(b.name), + ); + expect(tags.length).toBe(2); + + expect(tags[0].toString()).toContain("Tag"); + expect(tags[0].name).toBe("package-2021-10-01-preview"); + expect(tags[0].readme).toBe(readme); + + const inputFiles0 = [...tags[0].inputFiles.values()]; + expect(inputFiles0.length).toBe(1); + expect(inputFiles0[0].toString()).toContain("Swagger"); + expect(inputFiles0[0].path).toBe( + resolve(folder, "Microsoft.Contoso/preview/2021-10-01-preview/contoso.json"), + ); + expect(inputFiles0[0].tag).toBe(tags[0]); + + const refs0 = [...(await inputFiles0[0].getRefs()).values()].sort((a, b) => + a.path.localeCompare(b.path), + ); + + expect(refs0.length).toBe(1); + + expect(refs0[0].path).toBe( + resolve( + dirname(inputFiles0[0].path), + "../../../../../common-types/resource-management/v5/types.json", + ), + ); + expect(refs0[0].tag).toBe(tags[0]); + + expect(tags[1].name).toBe("package-2021-11-01"); + const inputFiles1 = [...tags[1].inputFiles.values()]; + expect(inputFiles1.length).toBe(1); + expect(inputFiles1[0].path).toBe( + resolve(folder, "Microsoft.Contoso/stable/2021-11-01/contoso.json"), + ); + expect(inputFiles1[0].tag).toBe(tags[1]); + + const jsonDefault = /** @type {SpecModelJSON} */ (await specModel.toJSONAsync()); + const readmeJSONDefault = /** @type {ReadmeJSON} */ (jsonDefault.readmes[0]); + const readmePathDefault = readmeJSONDefault.path; + expect(isAbsolute(readmePathDefault)).toBe(true); + expect( + /** @type {SwaggerJSON} */ (/** @type {TagJSON} */ (readmeJSONDefault.tags[0]).inputFiles[0]) + .refs, + ).toBeUndefined(); + + const jsonRefsRelative = /** @type {SpecModelJSON} */ ( + await specModel.toJSONAsync({ + includeOperations: true, + includeRefs: true, + relativePaths: true, + }) + ); + const readmeJSONRelative = /** @type {ReadmeJSON} */ (jsonRefsRelative.readmes[0]); + const readmePathRelative = readmeJSONRelative.path; + expect(isAbsolute(readmePathRelative)).toBe(false); + expect( + /** @type {SwaggerJSON}*/ (/** @type {TagJSON} */ (readmeJSONRelative.tags[0]).inputFiles[0]) + .operations, + ).toBeDefined(); + expect( + /** @type {SwaggerJSON}*/ (/** @type {TagJSON} */ (readmeJSONRelative.tags[0]).inputFiles[0]) + .refs, + ).toBeDefined(); + }); + + it("sorts readmes in toJSONAsync", async () => { + const folder = resolve(__dirname, "fixtures/getSpecModel/specification/multi-readme"); + + const specModel = new SpecModel(folder, options); + const json = /** @type {import('../src/spec-model.js').SpecModelJSON} */ ( + await specModel.toJSONAsync() + ); + + expect(json.readmes.length).toBe(2); + const paths = json.readmes.map( + (r) => /** @type {import('../src/readme.js').ReadmeJSON} */ (r).path, + ); + expect(paths[0].localeCompare(paths[1])).toBeLessThan(0); + }); + + it("uses strings for tag names and doesn't parse Date object", async () => { + const folder = resolve(__dirname, "fixtures/getSpecModel/specification/yaml-date-parsing"); + + const specModel = new SpecModel(folder, options); + + const readme = [...(await specModel.getReadmes()).values()][0]; + + const globalConfig = await readme.getGlobalConfig(); + + const tag = /** @type {unknown} */ (globalConfig["tag"]); + + expect(tag).not.toBeTypeOf("object"); + + expect(tag).toBeTypeOf("string"); + expect(tag).toBe("2022-12-01"); + }); + + it("throws when a tag is defined more than once", async () => { + // data-plane/readme.md defines the `package-2022-12-01` tag twice. + const folder = resolve( + __dirname, + "fixtures/getSpecModel/specification/contosowidgetmanager/data-plane", + ); + + const specModel = new SpecModel(folder, options); + + const readmes = await specModel.getReadmes(); + + await expect( + mapAsync([...readmes.values()], async (r) => await r.getTags()), + ).rejects.toThrowError(/multiple.*tag/i); + + await expect(specModel.toJSONAsync()).rejects.toThrowError(/multiple.*tag/i); + + await expect(specModel.toJSONAsync({ embedErrors: true })).resolves.toMatchObject({ + readmes: [ + { + error: /** @type {unknown} */ (expect.stringMatching(/multiple.*tag/i)), + }, + ], + }); + }); + + describe("getAffectedReadmeTags", () => { + it("returns affected readme tags", async () => { + const folder = resolve( + __dirname, + "fixtures/getAffectedReadmeTags/specification/contosowidgetmanager", + ); + + const specModel = new SpecModel(folder, options); + + const swaggerPath = resolve( + folder, + "resource-manager/Microsoft.Contoso/stable/2021-11-01/contoso.json", + ); + + const affectedReadmeTags = await specModel.getAffectedReadmeTags(swaggerPath); + + expect(affectedReadmeTags.size).toBe(1); + + const readmePath = [...affectedReadmeTags.keys()][0]; + expect(readmePath).toBe(resolve(folder, "resource-manager/readme.md")); + + const tagNames = [...[...affectedReadmeTags.values()][0].keys()]; + expect(tagNames.length).toBe(1); + + expect(tagNames[0]).toBe("package-2021-11-01"); + }); + + it("returns affected readme tags for multiple tags", async () => { + const folder = resolve(__dirname, "fixtures/getAffectedSwaggers/specification/1"); + + const specModel = new SpecModel(folder, options); + + const swaggerPath = resolve(folder, "data-plane/shared/shared.json"); + + const affectedReadmeTags = await specModel.getAffectedReadmeTags(swaggerPath); + + expect(affectedReadmeTags.size).toBe(1); + + const readmePath = [...affectedReadmeTags.keys()][0]; + expect(readmePath).toBe(resolve(folder, "data-plane/readme.md")); + + const tagNames = [...[...affectedReadmeTags.values()][0].keys()].sort(); + + expect(tagNames.length).toBe(2); + expect(tagNames[0]).toBe("tag-1"); + expect(tagNames[1]).toBe("tag-2"); + }); + + it("throws when an input-file is not found", async () => { + const folder = resolve( + __dirname, + "fixtures/getAffectedReadmeTags/specification/input-file-not-found", + ); + const specModel = new SpecModel(folder, options); + + await expect( + specModel.getAffectedReadmeTags(resolve(folder, "data-plane/a.json")), + ).rejects.toThrowError(/Failed to read file for swagger/i); + }); + + it("throws when an input-file is invalid JSON", async () => { + const folder = resolve( + __dirname, + "fixtures/getAffectedReadmeTags/specification/input-file-invalid-json", + ); + const specModel = new SpecModel(folder, options); + + await expect( + specModel.getAffectedReadmeTags(resolve(folder, "data-plane/a.json")), + ).rejects.toThrowError(`SyntaxError: Unexpected token 'i', "invalid json" is not valid JSON`); + + await expect(specModel.toJSONAsync({ includeRefs: true })).rejects.toThrowError( + `SyntaxError: Unexpected token 'i', "invalid json" is not valid JSON`, + ); + + await expect( + specModel.toJSONAsync({ embedErrors: true, includeRefs: true }), + ).resolves.toMatchObject({ + readmes: [ + { + tags: [ + { + inputFiles: [ + { + error: /** @type {unknown} */ ( + expect.stringContaining( + "Unexpected token 'i', \"invalid json\" is not valid JSON", + ) + ), + }, + ], + name: "package-2021-11-01", + }, + ], + }, + ], + }); + }); + }); + + describe("getAffectedSwaggers", () => { + const folder = resolve(__dirname, "fixtures/getAffectedSwaggers/specification/1"); + + const specModel = new SpecModel(folder, options); + + it("returns directly referenced swagger", async () => { + const swaggerPath = resolve(folder, "data-plane/a.json"); + + const actual = [...(await specModel.getAffectedSwaggers(swaggerPath)).keys()].sort(); + + const expected = ["data-plane/a.json"].map((p) => resolve(folder, p)).sort(); + + expect(actual).toEqual(expected); + }); + + it("throws when swagger file is not found", async () => { + const swaggerPath = resolve(folder, "data-plane/not-found.json"); + + await expect(specModel.getAffectedSwaggers(swaggerPath)).rejects.toThrowError( + /not found in specModel/i, + ); + }); + + it("returns correct swaggers for one layer of dependencies", async () => { + const swaggerPath = resolve(folder, "data-plane/nesting/b.json"); + + const actual = [...(await specModel.getAffectedSwaggers(swaggerPath)).keys()].sort(); + + const expected = ["data-plane/a.json", "data-plane/nesting/b.json"] + .map((p) => resolve(folder, p)) + .sort(); + + expect(actual).toEqual(expected); + }); + + it("returns correct swaggers for two layers of dependencies", async () => { + const swaggerPath = resolve(folder, "data-plane/c.json"); + + const actual = [...(await specModel.getAffectedSwaggers(swaggerPath)).keys()].sort(); + + const expected = ["data-plane/a.json", "data-plane/nesting/b.json", "data-plane/c.json"] + .map((p) => resolve(folder, p)) + .sort(); + + expect(actual).toEqual(expected); + }); + + it("returns correct swaggers for three layers of dependencies", async () => { + const swaggerPath = resolve(folder, "data-plane/d.json"); + + const actual = [...(await specModel.getAffectedSwaggers(swaggerPath)).keys()].sort(); + + const expected = [ + "data-plane/a.json", + "data-plane/nesting/b.json", + "data-plane/c.json", + "data-plane/d.json", + ] + .map((p) => resolve(folder, p)) + .sort(); + + expect(actual).toEqual(expected); + }); + + it("returns correctly for multiple shared dependencies", async () => { + const swaggerPath = resolve(folder, "data-plane/shared/shared.json"); + + const actual = [...(await specModel.getAffectedSwaggers(swaggerPath)).keys()].sort(); + + const expected = [ + "data-plane/a.json", + "data-plane/nesting/b.json", + "data-plane/c.json", + "data-plane/d.json", + "data-plane/shared/shared.json", + "data-plane/e.json", + ] + .map((p) => resolve(folder, p)) + .sort(); + + expect(actual).toEqual(expected); + }); + }); +}); + +// TODO: Update tests for new object-oriented API + +// Stress test the parser against all specs in the specification/ folder. This +// is a long-running test and should be run manually. To run this test, remove +// the '.skip' from the describe block. Put '.skip' back in when done or this +// test may fail unexpectedly in the future. +describe.skip("Parse readmes", () => { + it("Does not produce exceptions", { timeout: 30 * Duration.Minute }, async ({ expect }) => { + const excludeFolders = [ + "authorization", // specification/authorization/resource-manager/readme.md defines has duplicate tags including 'package-2020-10-01' + "azureactivedirectory", // specification/azureactivedirectory/resource-manager/readme.md has duplicate tags including 'package-preview-2020-07' + "cost-management", // specification/cost-management/resource-manager/readme.md has duplicate tags including 'package-2019-01' + "migrate", // specification/migrate/resource-manager/readme.md has duplicate tags including 'package-migrate-2023-04' + "quota", // specification/quota/resource-manager/readme.md has duplicate tags including 'package-2023-02-01' + "redisenterprise", // specification/redisenterprise/resource-manager/readme.md has duplicate tags including 'package-2024-02' + "security", // specification/security/resource-manager/readme.md has duplicate tags including 'package-2021-07-preview-only' + "confidentialledger", // data-plane/readme.md tag 'package-2022-04-20-preview-ledger' points to a swagger file that doesn't exist + "network", // network takes a long time to evaluate + "servicenetworking", // servicenetworking includes a swagger file which references a file that doesn't exist + ]; + + // List all folders under specification/ + const folders = await readdir(join(repoRoot, "specification"), { + withFileTypes: true, + }); + const services = folders + .filter((f) => f.isDirectory() && !excludeFolders.includes(f.name)) + .map((f) => f.name); + for (const folder of services) { + // Folders are listed in alphabetical order, when running this function + // iteratively over all service folders, a value can be placed in in this + // condition to skip folders that appear before a given folder. This means + // you won't have to wait for tests to run over all folders that have + // previously passed. + if (folder < "000") { + console.log(`Skipping service: ${folder}`); + continue; + } + + console.log(`Testing service: ${folder}`); + const specModel = new SpecModel(`specification/${folder}`, options); + + expect(specModel).toBeDefined(); + } + }); + + it("runs properly against specific services", { timeout: 30 * Duration.Minute }, ({ expect }) => { + /** @type {string[]} */ + const folders = [ + // Fill in services to test here + ]; + for (const folder of folders) { + console.log(`Testing service: ${folder}`); + const specModel = new SpecModel(`specification/${folder}`, options); + + expect(specModel).toBeDefined(); + } + }); +}); + +describe("getSwaggers", () => { + it("should return all swagger files from tags", async () => { + const folder = resolve( + __dirname, + "fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager", + ); + + const specModel = new SpecModel(folder, options); + const swaggers = await specModel.getSwaggers(); + + expect(swaggers.length).toBeGreaterThan(0); + + // Verify that all returned items are Swagger instances + expect(swaggers.every((s) => s.constructor.name === "Swagger")).toBe(true); + + // Verify that swagger files have the expected properties + const swagger = swaggers[0]; + expect(swagger.path).toBeDefined(); + expect(swagger.versionKind).toBeDefined(); + }); + + it("should return swaggers from multiple readmes and tags", async () => { + // Using a fixture that has multiple readme files + const folder = resolve( + __dirname, + "fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager", + ); + const specModel = new SpecModel(folder, options); + + const swaggers = await specModel.getSwaggers(); + + // Should find swaggers from all readmes + expect(swaggers.length).toBeGreaterThan(0); + + // Each swagger should have a valid path + swaggers.forEach((swagger) => { + expect(swagger.path).toBeDefined(); + expect(typeof swagger.path).toBe("string"); + expect(swagger.path.length).toBeGreaterThan(0); + }); + }); + + it("should handle empty directories gracefully", async () => { + // Test with a minimal or empty spec model + const tempFolder = resolve( + __dirname, + "fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager", + ); + const specModel = new SpecModel(tempFolder, options); + + const swaggers = await specModel.getSwaggers(); + + // Should return an array even if empty + expect(Array.isArray(swaggers)).toBe(true); + }); + + it("should preserve tag relationships", async () => { + const folder = resolve( + __dirname, + "fixtures/getSpecModel/specification/contosowidgetmanager/resource-manager", + ); + + const specModel = new SpecModel(folder, options); + const swaggers = await specModel.getSwaggers(); + + // Each swagger should have a tag reference + swaggers.forEach((swagger) => { + expect(swagger.tag).toBeDefined(); + if (swagger.tag) { + expect(swagger.tag.name).toBeDefined(); + expect(typeof swagger.tag.name).toBe("string"); + } + }); + }); + + it("should work with swagger fixtures", async () => { + const folder = resolve(__dirname, "fixtures/swagger"); + + const specModel = new SpecModel(folder, options); + const swaggers = await specModel.getSwaggers(); + + // Expected paths as complete normalized paths + const expectedSwaggerPaths = [ + "specification/common-types/resource-management/v2/types.json", + "specification/common-types/resource-management/v3/types.json", + "specification/common-types/resource-management/v3/types.json", + "specification/common-types/resource-management/v3/types.json", + "specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2023-04-01-preview/servicelinker.json", + "specification/servicelinker/resource-manager/Microsoft.ServiceLinker/preview/2024-07-01-preview/servicelinker.json", + "specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2022-05-01/servicelinker.json", + "specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/servicelinker.json", + "specification/servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/test.json", + ]; + + // Sort swaggers by path to ensure consistent order + expect(swaggers.sort((a, b) => a.path.localeCompare(b.path)).map((s) => s.path)).toEqual( + expectedSwaggerPaths.map((p) => resolve(folder, p)), + ); + }); +}); diff --git a/.github/shared/test/swagger.test.js b/.github/shared/test/swagger.test.js new file mode 100644 index 000000000000..b2eb100f69ae --- /dev/null +++ b/.github/shared/test/swagger.test.js @@ -0,0 +1,312 @@ +import { dirname, join, resolve } from "path"; +import { describe, expect, it } from "vitest"; +import { API_VERSION_LIFECYCLE_STAGES, Swagger } from "../src/swagger.js"; + +import { fileURLToPath } from "url"; +import { ConsoleLogger } from "../src/logger.js"; +import { Readme } from "../src/readme.js"; +import { SpecModel } from "../src/spec-model.js"; +import { Tag } from "../src/tag.js"; +import { swaggerTypeSpecGenerated } from "./examples.js"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe("Swagger", () => { + it("can be created with mock path", async () => { + const swagger = new Swagger("bar"); + expect(swagger.path).toBe(resolve("bar")); + expect(swagger.tag).toBeUndefined(); + + await expect(swagger.getRefs()).rejects.toThrowError(/Failed to read file for swagger/i); + }); + + it("resolves path against Tag.readme", () => { + const readme = new Readme("/specs/foo/readme.md"); + const tag = new Tag("2025-01-01", [], { readme }); + const swagger = new Swagger("test.json", { tag }); + + expect(swagger.path).toBe(resolve("/specs/foo/test.json")); + }); + + it("can be created with empty string content", async () => { + const folder = "/fake"; + const swagger = new Swagger(resolve(folder, "empty.json"), { + content: "{}", + }); + + const operations = await swagger.getOperations(); + expect(new Set(operations.keys())).toEqual(new Set()); + + const examples = await swagger.getExamples(); + expect(new Set(examples.keys())).toEqual(new Set()); + + const refs = await swagger.getRefs(); + expect(new Set(refs.keys())).toEqual(new Set()); + + expect(await swagger.getTypeSpecGenerated()).toEqual(false); + }); + + it("can be created with typespec-generated string content", async () => { + const folder = "/fake"; + const swagger = new Swagger(resolve(folder, "empty.json"), { + content: swaggerTypeSpecGenerated, + }); + + const operations = await swagger.getOperations(); + expect(new Set(operations.keys())).toEqual(new Set()); + + const examples = await swagger.getExamples(); + expect(new Set(examples.keys())).toEqual(new Set()); + + const refs = await swagger.getRefs(); + expect(new Set(refs.keys())).toEqual(new Set()); + + expect(await swagger.getTypeSpecGenerated()).toEqual(true); + }); + + it("can be created with sample string content", async () => { + const content = ` + { + "paths": { + "/foo": { + "parameters": ["unknown", 0], + "get": { + "operationId": "Foo_Get" + }, + "put": { + "operationId": "Foo_CreateOrUpdate" + } + }, + "/bar": { + "get": { + "operationId": "Bar_Get" + } + } + }, + "x-ms-paths": { + "/baz": { + "get": { + "operationId": "Baz_Get" + } + } + } + } + `; + + const folder = "/fake"; + const swagger = new Swagger(resolve(folder, "empty.json"), { + content, + }); + + const operations = await swagger.getOperations(); + expect(new Set(operations.keys())).toEqual( + new Set(["Foo_Get", "Foo_CreateOrUpdate", "Bar_Get", "Baz_Get"]), + ); + + const examples = await swagger.getExamples(); + expect(new Set(examples.keys())).toEqual(new Set()); + + const refs = await swagger.getRefs(); + expect(new Set(refs.keys())).toEqual(new Set()); + }); + + it("throws when created with invalid JSON content", async () => { + const folder = "/fake"; + const swagger = new Swagger(resolve(folder, "invalid.json"), { + content: `not json`, + tag: new Tag("test-tag", [], { readme: new Readme("/fake/readme.md") }), + }); + + await expect(swagger.getRefs()).rejects.toThrowErrorMatchingInlineSnapshot(` + [SpecModelError: Failed to parse JSON for swagger: ${resolve("/fake/invalid.json")} + Problem File: ${resolve("/fake/invalid.json")} + Readme: ${resolve("/fake/readme.md")} + Tag: test-tag + Cause: SyntaxError: Unexpected token 'o', "not json" is not valid JSON] + `); + }); + + it("throws when created with invalid schema content", async () => { + const folder = "/fake"; + const swagger = new Swagger(resolve(folder, "invalid.json"), { + content: `{"paths": "invalid"}`, + tag: new Tag("test-tag", [], { readme: new Readme("/fake/readme.md") }), + }); + + // getRefs() shouldn't throw, since it doesn't care about the zod schema + // ensures we are evaluating each data method lazily + await expect(swagger.getRefs().then((m) => new Set(m.keys()))).resolves.toEqual(new Set()); + + // getOperations() should throw, since the input wasn't valid per the zod schema + await expect(swagger.getOperations()).rejects.toThrowErrorMatchingInlineSnapshot(` + [SpecModelError: Failed to parse schema for swagger: ${resolve("/fake/invalid.json")} + Problem File: ${resolve("/fake/invalid.json")} + Readme: ${resolve("/fake/readme.md")} + Tag: test-tag + Cause: [ + { + "expected": "record", + "code": "invalid_type", + "path": [ + "paths" + ], + "message": "Invalid input: expected record, received string" + } + ]] + `); + }); + + it("throws when created with invalid ref content", async () => { + const invalidRefContent = ` + { + "paths": { + "/foo": { + "get": { + "operationId": "Foo_Get", + "$ref": "/does/not/exist.json" + } + } + } + } + `; + + const folder = "/fake"; + const swagger = new Swagger(resolve(folder, "invalid.json"), { + content: invalidRefContent, + tag: new Tag("test-tag", [], { readme: new Readme("/fake/readme.md") }), + }); + + await expect(swagger.getRefs()).rejects.toThrowErrorMatchingInlineSnapshot( + ` + [SpecModelError: Failed to resolve file for swagger: ${resolve("/fake/invalid.json")} + Problem File: ${resolve("/fake/invalid.json")} + Readme: ${resolve("/fake/readme.md")} + Tag: test-tag + Cause: ResolverError: Error reading file "${resolve("/does/not/exist.json").replace(/\\/g, "/").toLowerCase()}"] + `, + ); + }); + + it("sorts refs in toJSONAsync", async () => { + // a.json has 2+ refs (nesting/b.json, c.json, etc.) so the sort comparator gets invoked + const swagger = new Swagger( + resolve(__dirname, "fixtures/getAffectedSwaggers/specification/1/data-plane/a.json"), + ); + const json = /** @type {import('../src/swagger.js').SwaggerJSON} */ ( + await swagger.toJSONAsync({ includeRefs: true }) + ); + const refs = /** @type {import('../src/swagger.js').SwaggerJSON[]} */ (json.refs); + expect(refs.length).toBe(4); + // ensure at least first two elements are sorted correctly + expect(refs[0].path.localeCompare(refs[1].path)).toBeLessThan(0); + }); + + // TODO: Test that path is resolved against backpointer + + it("excludes example files", async () => { + const swagger = new Swagger(resolve(__dirname, "fixtures/swagger/ignoreExamples/swagger.json")); + const refs = await swagger.getRefs(); + + const expectedIncludedPath = resolve( + __dirname, + "fixtures/swagger/ignoreExamples/included.json", + ); + expect(refs).toMatchObject( + new Map([ + [ + expectedIncludedPath, + expect.objectContaining({ + path: /** @type {unknown} */ (expect.stringContaining(expectedIncludedPath)), + }), + ], + ]), + ); + }); + + it("returns examples", async () => { + const swagger = new Swagger(resolve(__dirname, "fixtures/swagger/ignoreExamples/swagger.json")); + const examples = await swagger.getExamples(); + + const expectedExamplePath = resolve( + __dirname, + "fixtures/swagger/ignoreExamples/examples/example.json", + ); + expect(examples).toMatchObject( + new Map([ + [ + expectedExamplePath, + expect.objectContaining({ + path: /** @type {unknown} */ (expect.stringContaining(expectedExamplePath)), + }), + ], + ]), + ); + }); + + it("returns cached examples on second call", async () => { + const swagger = new Swagger(resolve(__dirname, "fixtures/swagger/ignoreExamples/swagger.json")); + const examples1 = await swagger.getExamples(); + const examples2 = await swagger.getExamples(); + + // Both calls should return the same (cached) Map instance + expect(examples2).toBe(examples1); + }); + + it("computes versionKind from path", () => { + let swagger = new Swagger(resolve("foo/preview/2025-01-01-preview/foo.json")); + expect(swagger.versionKind).toEqual(API_VERSION_LIFECYCLE_STAGES.PREVIEW); + + swagger = new Swagger(resolve("foo/stable/2025-01-01/foo.json")); + expect(swagger.versionKind).toEqual(API_VERSION_LIFECYCLE_STAGES.STABLE); + }); + + describe("getOperations", () => { + it("should return normal operations", async () => { + const testFixturePath = join(__dirname, "fixtures", "swagger", "specification"); + const targetPath = join( + testFixturePath, + "servicelinker/resource-manager/Microsoft.ServiceLinker/stable/2024-04-01/test.json", + ); + const specModel = new SpecModel(testFixturePath, { + logger: new ConsoleLogger(/*debug*/ true), + }); + const result = await specModel.getSwaggers(); + const swagger = result.find((s) => s.path === targetPath); + + if (!swagger) throw new Error("Swagger not found for the given path"); + const operationsMap = await swagger.getOperations(); + expect(operationsMap.size).toBe(3); + + let expectedApiPath = + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns/{dryrunName}"; + + // Test specific operations by ID + const createDryrun = operationsMap.get("Connector_CreateDryrun"); + const getDryrun = operationsMap.get("Connector_GetDryrun"); + const listDryruns = operationsMap.get("Connector_ListDryrun"); + + expect(createDryrun).toBeDefined(); + if (createDryrun) { + expect(createDryrun.id).toBe("Connector_CreateDryrun"); + expect(createDryrun.httpMethod).toBe("PUT"); + expect(createDryrun.path).toBe(expectedApiPath); + } + + expect(getDryrun).toBeDefined(); + if (getDryrun) { + expect(getDryrun.id).toBe("Connector_GetDryrun"); + expect(getDryrun.httpMethod).toBe("GET"); + expect(getDryrun.path).toBe(expectedApiPath); + } + + expectedApiPath = + "/subscriptions/{subscriptionId}/resourcegroups/{resourceGroupName}/providers/Microsoft.ServiceLinker/locations/{location}/dryruns"; + expect(listDryruns).toBeDefined(); + if (listDryruns) { + expect(listDryruns.id).toBe("Connector_ListDryrun"); + expect(listDryruns.httpMethod).toBe("GET"); + expect(listDryruns.path).toBe(expectedApiPath); + } + }); + }); +}); diff --git a/.github/shared/test/tag.test.js b/.github/shared/test/tag.test.js new file mode 100644 index 000000000000..5c5da8cd406c --- /dev/null +++ b/.github/shared/test/tag.test.js @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest"; + +import { resolve } from "path"; +import { Tag } from "../src/tag.js"; + +describe("Tag", () => { + it("can be created with mock swaggers", async () => { + const tag = new Tag("tag", ["swagger"]); + + expect(tag.name).toBe("tag"); + expect(tag.readme).toBeUndefined(); + + expect(tag.inputFiles.size).toBe(1); + const swagger = [...tag.inputFiles.values()][0]; + expect(swagger.path).toBe(resolve("swagger")); + + await expect(swagger.getRefs()).rejects.toThrowError(/Failed to read file for swagger/i); + }); + + it("sorts input files in toJSONAsync", async () => { + const tag = new Tag("test-tag", ["b.json", "a.json"]); + const json = /** @type {import('../src/tag.js').TagJSON} */ (await tag.toJSONAsync()); + const files = json.inputFiles.map( + (f) => /** @type {import('../src/swagger.js').SwaggerJSON} */ (f).path, + ); + expect(files.length).toBe(2); + expect(files[0].localeCompare(files[1])).toBeLessThan(0); + }); +}); diff --git a/.github/shared/test/time.test.js b/.github/shared/test/time.test.js new file mode 100644 index 000000000000..8567a554d1f2 --- /dev/null +++ b/.github/shared/test/time.test.js @@ -0,0 +1,19 @@ +import { describe, expect, it } from "vitest"; + +import { add, Duration, formatDuration, getDuration, subtract } from "../src/time.js"; + +describe("time", () => { + // Cover Duration, formatDuration, getDuration, add, and subtract in a single test + it.each([ + [Duration.Millisecond, "00:00:00"], + [Duration.Second, "00:00:01"], + [Duration.Minute, "00:01:00"], + [Duration.Hour, "01:00:00"], + [Duration.Day, "24:00:00"], + [Duration.Week, "168:00:00"], + ])("formatDuration(%i)=%s", (duration, expected) => { + const now = new Date(); + expect(formatDuration(getDuration(now, add(now, duration)))).toEqual(expected); + expect(formatDuration(getDuration(now, subtract(now, duration)))).toEqual(expected); + }); +}); diff --git a/.github/shared/tsconfig.json b/.github/shared/tsconfig.json new file mode 100644 index 000000000000..8d782a7d8cbf --- /dev/null +++ b/.github/shared/tsconfig.json @@ -0,0 +1,12 @@ +// Only used for type-checking of JavaScript sources. Folder should contain no TypeScript sources. +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + // Avoid generating tsconfig.tsbuildinfo file, which isn't useful for our scenario + "incremental": false, + "noEmit": true, + }, + "exclude": ["coverage"], +} diff --git a/.github/shared/vitest.config.js b/.github/shared/vitest.config.js new file mode 100644 index 000000000000..e8d8ae739c14 --- /dev/null +++ b/.github/shared/vitest.config.js @@ -0,0 +1,32 @@ +import { configDefaults, defineConfig } from "vitest/config"; + +export default defineConfig({ + esbuild: { + // Ignore tsconfig.json, since it's only used for type checking, and causes + // a warning if vitest tries to load it + // @ts-expect-error: 'tsConfig' does not exist in type 'ESBuildOptions' + tsConfig: false, + }, + + test: { + coverage: { + exclude: [ + ...(configDefaults.coverage.exclude ?? []), + + // Config files (not in defaults) + "eslint*.config.js", + + // Not worth testing CLI code + "cmd/**/*.js", + ], + + // Enforce 100% coverage for all metrics + thresholds: { + branches: 100, + functions: 100, + lines: 100, + statements: 100, + }, + }, + }, +}); diff --git a/.github/tsconfig.json b/.github/tsconfig.json new file mode 100644 index 000000000000..eebc14d2fc9d --- /dev/null +++ b/.github/tsconfig.json @@ -0,0 +1,12 @@ +// Only used for type-checking of JavaScript sources. Folder should contain no TypeScript sources. +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + // Avoid generating tsconfig.tsbuildinfo file, which isn't useful for our scenario + "incremental": false, + "noEmit": true, + }, + "exclude": ["coverage", "shared/coverage"], +} diff --git a/.github/tsconfig.tsbuildinfo b/.github/tsconfig.tsbuildinfo new file mode 100644 index 000000000000..f4a18a6c3ae3 --- /dev/null +++ b/.github/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"root":["./eslint.config.js","./vitest.config.js","./shared/eslint.base.config.js","./shared/eslint.config.js","./shared/vitest.config.js","./shared/cmd/spec-model.js","./shared/perf/perf.js","./shared/src/array.js","./shared/src/breaking-change.js","./shared/src/cache.js","./shared/src/changed-files.js","./shared/src/console.js","./shared/src/exec.js","./shared/src/git.js","./shared/src/github.js","./shared/src/logger.js","./shared/src/math.js","./shared/src/path.js","./shared/src/readme.js","./shared/src/sdk-types.js","./shared/src/set.js","./shared/src/simple-git.js","./shared/src/sleep.js","./shared/src/sort.js","./shared/src/spec-model-error.js","./shared/src/spec-model.js","./shared/src/swagger.js","./shared/src/tag.js","./shared/src/time.js","./shared/test/array.test.js","./shared/test/cache.test.js","./shared/test/changed-files.test.js","./shared/test/console.test.js","./shared/test/examples.js","./shared/test/exec.test.js","./shared/test/git.test.js","./shared/test/logger.test.js","./shared/test/math.test.js","./shared/test/path.test.js","./shared/test/readme.test.js","./shared/test/repo.js","./shared/test/sdk-types.js","./shared/test/sdk-types.test.js","./shared/test/set.test.js","./shared/test/simple-git.test.js","./shared/test/sleep.test.js","./shared/test/sort.test.js","./shared/test/spec-model-error.test.js","./shared/test/spec-model.test.js","./shared/test/swagger.test.js","./shared/test/tag.test.js","./shared/test/time.test.js"],"version":"6.0.3"} \ No newline at end of file diff --git a/.github/vitest.config.js b/.github/vitest.config.js new file mode 100644 index 000000000000..6379773579f6 --- /dev/null +++ b/.github/vitest.config.js @@ -0,0 +1,30 @@ +import { configDefaults, defineConfig } from "vitest/config"; + +export default defineConfig({ + esbuild: { + // Ignore tsconfig.json, since it's only used for type checking, and causes + // a warning if vitest tries to load it + // @ts-expect-error: tsConfig' does not exist in type 'ESBuildOptions' + tsConfig: false, + }, + + test: { + coverage: { + exclude: [ + ...(configDefaults.coverage.exclude ?? []), + + // Config files (not in defaults) + "**/eslint*.config.js", + + // Not worth testing CLI code + "**/cmd/**", + + // Ignore all coverage folders + "**/coverage/**", + + // Ignore all test folders + "**/test/**", + ], + }, + }, +}); diff --git a/.github/workflows/github-test.yaml b/.github/workflows/github-test.yaml new file mode 100644 index 000000000000..6a379999c503 --- /dev/null +++ b/.github/workflows/github-test.yaml @@ -0,0 +1,63 @@ +name: GitHub Actions - Test + +on: + push: + branches: + - main + paths: + - .github/** + pull_request: + paths: + - .github/** + workflow_dispatch: + +permissions: + contents: read + +jobs: + test: + strategy: + matrix: + folder: [.github, .github/shared] + os: [ubuntu, windows] + + runs-on: ${{ fromJSON('{"ubuntu":"ubuntu-24.04", "windows":"windows-2022"}')[matrix.os] }} + + defaults: + run: + working-directory: ./${{ matrix.folder }} + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + sparse-checkout: | + .github + + - if: ${{ matrix.folder == '.github' }} + name: Install dependencies for github-script actions + uses: ./.github/actions/install-deps-github-script + + - if: ${{ matrix.folder == '.github' }} + name: Verify all modules are importable + uses: actions/github-script@v8 + with: + script: | + const { join } = await import("path"); + const { pathToFileURL } = await import("url"); + const fullPath = join(process.env.GITHUB_WORKSPACE, ".github", "workflows", "src", "github-test.js"); + const { default: importAllModules } = await import(pathToFileURL(fullPath).href); + await importAllModules({ core }); + + - name: Install dev deps + uses: ./.github/actions/setup-node-install-deps + with: + # actions/github-script@v8 uses Node 24 + node-version: 24.x + working-directory: ./${{ matrix.folder }} + + - run: npm run test:ci + + - run: npm run lint + + - run: npm run format:check:ci diff --git a/.github/workflows/src/github-test.js b/.github/workflows/src/github-test.js new file mode 100644 index 000000000000..9117aa453cee --- /dev/null +++ b/.github/workflows/src/github-test.js @@ -0,0 +1,40 @@ +import { readdir } from "fs/promises"; +import { basename, join, normalize, sep } from "path"; +import { pathToFileURL } from "url"; +import { inspect } from "util"; + +/** + * @param {import('@actions/github-script').AsyncFunctionArguments} AsyncFunctionArguments + */ +export default async function importAllModules({ core }) { + const workspace = process.env.GITHUB_WORKSPACE; + if (!workspace) { + throw new Error("Env var GITHUB_WORKSPACE must be set"); + } + + const githubDir = join(workspace, ".github"); + + // find all files matching "**/src/**/*.js", sorted for readability + const scriptFiles = (await readdir(githubDir, { recursive: true })) + .filter((f) => normalize(f).split(sep).includes("src") && basename(f).endsWith(".js")) + .sort(); + + core.info("Script Files:"); + scriptFiles.map(core.info); + core.info(""); + + for (const file of scriptFiles) { + core.info(`Importing ${file}`); + + const fullPath = join(githubDir, file); + const fileUrl = pathToFileURL(fullPath).href; + + // if import fails, throws error which causes step to fail + const module = /** @type {unknown} */ (await import(fileUrl)); + + core.info(inspect(module)); + core.info(""); + } + + core.info("All script files are importable"); +} diff --git a/.github/workflows/typespec-python-regenerate.yml b/.github/workflows/typespec-python-regenerate.yml index 979f06cacfd1..0679ad238fe3 100644 --- a/.github/workflows/typespec-python-regenerate.yml +++ b/.github/workflows/typespec-python-regenerate.yml @@ -105,7 +105,7 @@ jobs: # SHA corresponds to actions/setup-node@v6 uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e with: - node-version: lts/* + node-version: 24.x - name: Setup Python # SHA corresponds to actions/setup-python@v5 diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 2d7349a88660..d23ad6b2c9eb 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -1,5 +1,8 @@ { "version": "0.2", + "import": [ + "../.github/cspell.yaml" + ], "language": "en", "languageId": "python", "dictionaries": [ @@ -13,8 +16,7 @@ "ignorePaths": [ ".devcontainer/**", "eng/**", - ".github/CODEOWNERS", - ".github/**/*.lock.yml", + ".github/**", "scripts/**", "**/tests/recordings/**", ".vscode/cspell.json", @@ -138,8 +140,6 @@ "conda/conda-recipes/msrest/meta.yaml", "conda/conda-recipes/uamqp/meta.yaml", "conda/conda-releaselogs/azure-mgmt.md", - ".github/workflows/azure-sdk-tools.yml", - ".github/workflows/actionlint.yml", "sdk/ai/azure-ai-voicelive/azure/ai/voicelive/models/_*.py", "sdk/ai/azure-ai-voicelive/samples/**" ],